TGUI PDAs, legacy code to-be-removed

This commit is contained in:
ShadowLarkens
2020-09-16 01:52:45 -07:00
parent 8c338ed9da
commit bec0942513
49 changed files with 2023 additions and 2462 deletions

View File

@@ -112,17 +112,5 @@
//Commented out because we don't send messages like this anymore. Instead it will just popup in their chat window.
//P.tnote += "<i><b>&larr; From [sender] (Unknown / spam?):</b></i><br>[message]<br>"
if (!P.message_silent)
playsound(P, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(3, P.loc))
if(!P.message_silent) O.show_message(text("[bicon(P)] *[P.ttone]*"))
//Search for holder of the PDA.
var/mob/living/L = null
if(P.loc && isliving(P.loc))
L = P.loc
//Maybe they are a pAI!
else
L = get(P, /mob/living/silicon)
if(L)
to_chat(L, "[bicon(P)] <b>Message from [sender] (Unknown / spam?), </b>\"[message]\" (Unable to Reply)")
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
PM.notify("<b>Message from [sender] (Unknown / spam?), </b>\"[message]\" (Unable to Reply)", 0)

95
code/modules/pda/ai.dm Normal file
View File

@@ -0,0 +1,95 @@
// Special AI/pAI PDAs that cannot explode.
/obj/item/device/pda/ai
icon_state = "NONE"
ttone = "data"
newstone = "news"
detonate = 0
/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text)
owner = newname
ownjob = newjob
if(newrank)
ownrank = newrank
else
ownrank = ownjob
name = newname + " (" + ownjob + ")"
//AI verb and proc for sending PDA messages.
/obj/item/device/pda/ai/verb/cmd_send_pdamesg()
set category = "AI IM"
set name = "Send PDA Message"
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")
/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--
playsound(src, 'sound/items/bikehorn.ogg', 30, 1)
return
/obj/item/device/pda/ai/pai
ttone = "assist"
/obj/item/device/pda/ai/shell
spam_proof = TRUE // Since empty shells get a functional PDA.

View File

@@ -35,7 +35,7 @@
if(L)
to_chat(L, "[bicon(pda)] [message]")
SSnanoui.update_user_uis(L, pda) // Update the receiving user's PDA UI so that they can see the new message
SStgui.update_user_uis(L, pda) // Update the receiving user's PDA UI so that they can see the new message
if(!notify_silent)
pda.play_ringtone()
@@ -59,6 +59,9 @@
var/update = PDA_APP_UPDATE
var/has_back = 0
/datum/data/pda/app/tgui_host(mob/user)
return pda || src
/datum/data/pda/app/New()
if(!title)
title = name

View File

@@ -55,30 +55,9 @@ var/list/civilian_cartridges = list(
pickup_sound = 'sound/items/pickup/component.ogg'
var/obj/item/radio/integrated/radio = null
var/access_security = 0
var/access_engine = 0
var/access_atmos = 0
var/access_medical = 0
var/access_clown = 0
var/access_mime = 0
var/access_janitor = 0
// var/access_flora = 0
var/access_reagent_scanner = 0
var/access_remote_door = 0 // Control some blast doors remotely!!
var/remote_door_id = ""
var/access_status_display = 0
var/access_quartermaster = 0
var/access_detonate_pda = 0
var/access_hydroponics = 0
var/charges = 0
var/mode = null
var/menu
var/datum/data/record/active1 = null //General
var/datum/data/record/active2 = null //Medical
var/datum/data/record/active3 = null //Security
var/selected_sensor = null // Power Sensor
var/message1 // used for status_displays
var/message2
var/list/stored_data = list()
var/list/programs = list()
var/list/messenger_plugins = list()
@@ -89,31 +68,47 @@ var/list/civilian_cartridges = list(
QDEL_LIST(messenger_plugins)
return ..()
/obj/item/weapon/cartridge/proc/update_programs(obj/item/device/pda/pda)
for(var/A in programs)
var/datum/data/pda/P = A
P.pda = pda
for(var/A in messenger_plugins)
var/datum/data/pda/messenger_plugin/P = A
P.pda = pda
/obj/item/weapon/cartridge/engineering
name = "\improper Power-ON cartridge"
icon_state = "cart-e"
access_engine = 1
programs = list(
new/datum/data/pda/app/power,
new/datum/data/pda/utility/scanmode/halogen)
/obj/item/weapon/cartridge/atmos
name = "\improper BreatheDeep cartridge"
icon_state = "cart-a"
access_atmos = 1
programs = list(new/datum/data/pda/utility/scanmode/gas)
/obj/item/weapon/cartridge/medical
name = "\improper Med-U cartridge"
icon_state = "cart-m"
access_medical = 1
programs = list(
new/datum/data/pda/app/crew_records/medical,
new/datum/data/pda/utility/scanmode/medical)
/obj/item/weapon/cartridge/chemistry
name = "\improper ChemWhiz cartridge"
icon_state = "cart-chem"
access_reagent_scanner = 1
access_medical = 1
programs = list(
new/datum/data/pda/app/crew_records/medical,
new/datum/data/pda/utility/scanmode/medical,
new/datum/data/pda/utility/scanmode/reagent)
/obj/item/weapon/cartridge/security
name = "\improper R.O.B.U.S.T. cartridge"
icon_state = "cart-s"
access_security = 1
programs = list(
new/datum/data/pda/app/crew_records/security,
new/datum/data/pda/app/secbot_control)
/obj/item/weapon/cartridge/security/Initialize()
radio = new /obj/item/radio/integrated/beepsky(src)
@@ -122,38 +117,36 @@ var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/detective
name = "\improper D.E.T.E.C.T. cartridge"
icon_state = "cart-s"
access_security = 1
access_medical = 1
programs = list(
new/datum/data/pda/app/crew_records/medical,
new/datum/data/pda/utility/scanmode/medical,
new/datum/data/pda/app/crew_records/security)
/obj/item/weapon/cartridge/janitor
name = "\improper CustodiPRO cartridge"
desc = "The ultimate in clean-room design."
icon_state = "cart-j"
access_janitor = 1
programs = list(new/datum/data/pda/app/janitor)
/obj/item/weapon/cartridge/lawyer
name = "\improper P.R.O.V.E. cartridge"
icon_state = "cart-s"
access_security = 1
programs = list(new/datum/data/pda/app/crew_records/security)
/obj/item/weapon/cartridge/clown
name = "\improper Honkworks 5.0 cartridge"
icon_state = "cart-clown"
access_clown = 1
charges = 5
programs = list(new/datum/data/pda/utility/honk)
messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/clown)
/obj/item/weapon/cartridge/mime
name = "\improper Gestur-O 1000 cartridge"
icon_state = "cart-mi"
access_mime = 1
charges = 5
/*
/obj/item/weapon/cartridge/botanist
name = "Green Thumb v4.20"
icon_state = "cart-b"
access_flora = 1
*/
messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/mime)
/obj/item/weapon/cartridge/service
name = "\improper Serv-U Pro cartridge"
@@ -162,24 +155,34 @@ var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/signal
name = "generic signaler cartridge"
desc = "A data cartridge with an integrated radio signaler module."
var/qdeled = 0
programs = list(new/datum/data/pda/app/signaller)
/obj/item/weapon/cartridge/signal/Initialize()
radio = new /obj/item/radio/integrated/signal(src)
..()
/obj/item/weapon/cartridge/signal/science
name = "\improper Signal Ace 2 cartridge"
desc = "Complete with integrated radio signaler!"
icon_state = "cart-tox"
access_reagent_scanner = 1
access_atmos = 1
programs = list(
new/datum/data/pda/utility/scanmode/gas,
/obj/item/weapon/cartridge/signal/Initialize()
radio = new /obj/item/radio/integrated/signal(src)
. = ..()
new/datum/data/pda/utility/scanmode/reagent,
new/datum/data/pda/app/signaller)
/obj/item/weapon/cartridge/quartermaster
name = "\improper Space Parts & Space Vendors cartridge"
desc = "Perfect for the Quartermaster on the go!"
icon_state = "cart-q"
access_quartermaster = 1
programs = list(
new/datum/data/pda/app/supply,
new/datum/data/pda/app/mule_control)
/obj/item/weapon/cartridge/quartermaster/Initialize()
radio = new /obj/item/radio/integrated/mule(src)
..()
/obj/item/weapon/cartridge/miner
name = "\improper Drill-Jockey 4.5 cartridge"
@@ -189,21 +192,33 @@ var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/head
name = "\improper Easy-Record DELUXE cartridge"
icon_state = "cart-h"
access_status_display = 1
programs = list(new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/hop
name = "\improper HumanResources9001 cartridge"
icon_state = "cart-h"
access_status_display = 1
access_quartermaster = 1
access_janitor = 1
access_security = 1
programs = list(
new/datum/data/pda/app/crew_records/security,
new/datum/data/pda/app/janitor,
new/datum/data/pda/app/supply,
new/datum/data/pda/app/mule_control,
new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/hop/Initialize()
radio = new /obj/item/radio/integrated/mule(src)
..()
/obj/item/weapon/cartridge/hos
name = "\improper R.O.B.U.S.T. DELUXE cartridge"
icon_state = "cart-hos"
access_status_display = 1
access_security = 1
programs = list(
new/datum/data/pda/app/crew_records/security,
new/datum/data/pda/app/secbot_control,
new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/hos/Initialize()
radio = new /obj/item/radio/integrated/beepsky(src)
@@ -212,23 +227,36 @@ var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/ce
name = "\improper Power-On DELUXE cartridge"
icon_state = "cart-ce"
access_status_display = 1
access_engine = 1
access_atmos = 1
programs = list(
new/datum/data/pda/app/power,
new/datum/data/pda/utility/scanmode/halogen,
new/datum/data/pda/utility/scanmode/gas,
new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/cmo
name = "\improper Med-U DELUXE cartridge"
icon_state = "cart-cmo"
access_status_display = 1
access_reagent_scanner = 1
access_medical = 1
programs = list(
new/datum/data/pda/app/crew_records/medical,
new/datum/data/pda/utility/scanmode/medical,
new/datum/data/pda/utility/scanmode/reagent,
new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/rd
name = "\improper Signal Ace DELUXE cartridge"
icon_state = "cart-rd"
access_status_display = 1
access_reagent_scanner = 1
access_atmos = 1
programs = list(
new/datum/data/pda/utility/scanmode/gas,
new/datum/data/pda/utility/scanmode/reagent,
new/datum/data/pda/app/signaller,
new/datum/data/pda/app/status_display)
/obj/item/weapon/cartridge/rd/Initialize()
radio = new /obj/item/radio/integrated/signal(src)
@@ -261,10 +289,15 @@ var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/syndicate
name = "\improper Detomatix cartridge"
icon_state = "cart"
access_remote_door = 1
access_detonate_pda = 1
remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
var/initial_remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
charges = 4
programs = list(new/datum/data/pda/utility/toggle_door)
messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/detonate)
/obj/item/weapon/cartridge/syndicate/New()
var/datum/data/pda/utility/toggle_door/D = programs[1]
if(istype(D))
D.remote_door_id = initial_remote_door_id
/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2)
@@ -297,356 +330,3 @@ var/list/civilian_cartridges = list(
charges = 5
var/telecrystals = 0
messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/frame)
/*
This generates the nano values of the cart menus.
Because we close the UI when we insert a new cart
we don't have to worry about null values on items
the user can't access. Well, unless they are href hacking.
But in that case their UI will just lock up.
*/
/obj/item/weapon/cartridge/proc/create_NanoUI_values(mob/user as mob)
var/values[0]
/* Signaler (Mode: 40) */
if(istype(radio,/obj/item/radio/integrated/signal) && (mode==40))
var/obj/item/radio/integrated/signal/R = radio
values["signal_freq"] = format_frequency(R.frequency)
values["signal_code"] = R.code
/* Station Display (Mode: 42) */
if(mode==42)
values["message1"] = message1 ? message1 : "(none)"
values["message2"] = message2 ? message2 : "(none)"
/* Power Monitor (Mode: 43 / 433) */
if(mode==43 || mode==433)
var/list/sensors = list()
var/obj/machinery/power/sensor/MS = null
var/my_z = get_z(user)
var/list/levels = using_map.get_map_levels(my_z)
for(var/obj/machinery/power/sensor/S in machines)
if(!(get_z(S) in levels))
continue
sensors.Add(list(list("name_tag" = S.name_tag)))
if(S.name_tag == selected_sensor)
MS = S
values["power_sensors"] = sensors
if(selected_sensor && MS)
values["sensor_reading"] = MS.return_reading_data()
/* General Records (Mode: 44 / 441 / 45 / 451) */
if(mode == 44 || mode == 441 || mode == 45 || mode ==451)
if(istype(active1, /datum/data/record) && (active1 in data_core.general))
values["general"] = active1.fields
values["general_exists"] = 1
else
values["general_exists"] = 0
/* Medical Records (Mode: 44 / 441) */
if(mode == 44 || mode == 441)
var/medData[0]
for(var/datum/data/record/R in sortRecord(data_core.general))
medData[++medData.len] = list(Name = R.fields["name"],"ref" = "\ref[R]")
values["medical_records"] = medData
if(istype(active2, /datum/data/record) && (active2 in data_core.medical))
values["medical"] = active2.fields
values["medical_exists"] = 1
else
values["medical_exists"] = 0
/* Security Records (Mode:45 / 451) */
if(mode == 45 || mode == 451)
var/secData[0]
for (var/datum/data/record/R in sortRecord(data_core.general))
secData[++secData.len] = list(Name = R.fields["name"], "ref" = "\ref[R]")
values["security_records"] = secData
if(istype(active3, /datum/data/record) && (active3 in data_core.security))
values["security"] = active3.fields
values["security_exists"] = 1
else
values["security_exists"] = 0
/* Security Bot Control (Mode: 46) */
if(mode==46)
var/botsData[0]
var/beepskyData[0]
if(istype(radio,/obj/item/radio/integrated/beepsky))
var/obj/item/radio/integrated/beepsky/SC = radio
beepskyData["active"] = SC.active
if(SC.active && !isnull(SC.botstatus))
var/area/loca = SC.botstatus["loca"]
var/loca_name = sanitize(loca.name)
beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"])
else
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
var/botsCount=0
if(SC.botlist && SC.botlist.len)
for(var/mob/living/bot/B in SC.botlist)
botsCount++
if(B.loc)
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
if(!botsData.len)
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
beepskyData["bots"] = botsData
beepskyData["count"] = botsCount
else
beepskyData["active"] = 0
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
beepskyData["botstatus"] = list("loca" = null, "mode" = null)
beepskyData["bots"] = botsData
beepskyData["count"] = 0
values["beepsky"] = beepskyData
/* MULEBOT Control (Mode: 48) */
if(mode==48)
var/mulebotsData[0]
var/count = 0
for(var/mob/living/bot/mulebot/M in living_mob_list)
if(!M.on)
continue
++count
var/muleData[0]
muleData["name"] = M.suffix
muleData["location"] = get_area(M)
muleData["paused"] = M.paused
muleData["home"] = M.homeName
muleData["target"] = M.targetName
muleData["ref"] = "\ref[M]"
muleData["load"] = M.load ? M.load.name : "Nothing"
mulebotsData[++mulebotsData.len] = muleData.Copy()
values["mulebotcount"] = count
values["mulebots"] = mulebotsData
/* Supply Shuttle Requests Menu (Mode: 47) */
if(mode==47)
var/supplyData[0]
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (shuttle)
supplyData["shuttle_moving"] = shuttle.has_arrive_time()
supplyData["shuttle_eta"] = shuttle.eta_minutes()
supplyData["shuttle_loc"] = shuttle.at_station() ? "Station" : "Dock"
var/supplyOrderCount = 0
var/supplyOrderData[0]
for(var/S in SSsupply.shoppinglist)
var/datum/supply_order/SO = S
supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
if(!supplyOrderData.len)
supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null)
supplyData["approved"] = supplyOrderData
supplyData["approved_count"] = supplyOrderCount
var/requestCount = 0
var/requestData[0]
for(var/S in SSsupply.order_history)
var/datum/supply_order/SO = S
if(SO.status != SUP_ORDER_REQUESTED)
continue
requestCount++
requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
if(!requestData.len)
requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null)
supplyData["requests"] = requestData
supplyData["requests_count"] = requestCount
values["supply"] = supplyData
/* Janitor Supplies Locator (Mode: 49) */
if(mode==49)
var/JaniData[0]
var/turf/cl = get_turf(src)
if(cl)
JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y)
else
JaniData["user_loc"] = list("x" = 0, "y" = 0)
var/MopData[0]
for(var/obj/item/weapon/mop/M in all_mops)
var/turf/ml = get_turf(M)
if(ml)
if(ml.z != cl.z)
continue
var/direction = get_dir(src, M)
MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry")
if(!MopData.len)
MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/BucketData[0]
for(var/obj/structure/mopbucket/B in all_mopbuckets)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
if(!BucketData.len)
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
for(var/mob/living/bot/cleanbot/B in mob_list)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline")
if(!CbotData.len)
CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CartData[0]
for(var/obj/structure/janitorialcart/B in all_janitorial_carts)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
var/status = "No Bucket"
if(B.mybucket)
status = B.mybucket.reagents.total_volume / 100
CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = status)
if(!CartData.len)
CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
JaniData["mops"] = MopData
JaniData["buckets"] = BucketData
JaniData["cleanbots"] = CbotData
JaniData["carts"] = CartData
values["janitor"] = JaniData
return values
/obj/item/weapon/cartridge/Topic(href, href_list)
..()
if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr.unset_machine()
usr << browse(null, "window=pda")
return
switch(href_list["choice"])
if("Medical Records")
var/datum/data/record/R = locate(href_list["target"])
var/datum/data/record/M = locate(href_list["target"])
loc:mode = 441
mode = 441
if (R in data_core.general)
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
break
active1 = R
active2 = M
if("Security Records")
var/datum/data/record/R = locate(href_list["target"])
var/datum/data/record/S = locate(href_list["target"])
loc:mode = 451
mode = 451
if (R in data_core.general)
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
break
active1 = R
active3 = S
if("Send Signal")
if(is_jammed(src))
return
spawn( 0 )
radio:send_signal("ACTIVATE")
return
if("Signal Frequency")
var/new_frequency = sanitize_frequency(radio:frequency + text2num(href_list["sfreq"]))
radio:set_frequency(new_frequency)
if("Signal Code")
radio:code += text2num(href_list["scode"])
radio:code = round(radio:code)
radio:code = min(100, radio:code)
radio:code = max(1, radio:code)
if("Status")
switch(href_list["statdisp"])
if("message")
post_status("message", message1, message2)
if("alert")
post_status("alert", href_list["alert"])
if("setmsg1")
message1 = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", message1) as text|null, 40), 40)
updateSelfDialog()
if("setmsg2")
message2 = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", message2) as text|null, 40), 40)
updateSelfDialog()
else
post_status(href_list["statdisp"])
if("Power Select")
selected_sensor = href_list["target"]
loc:mode = 433
mode = 433
if("Power Clear")
selected_sensor = null
loc:mode = 43
mode = 43
if("MULEbot")
var/mob/living/bot/mulebot/M = locate(href_list["ref"])
if(istype(M))
M.obeyCommand(href_list["command"])
return 1

View File

@@ -12,20 +12,23 @@
"message1" = message1 ? message1 : "(none)",
"message2" = message2 ? message2 : "(none)")
/datum/data/pda/app/status_display/Topic(href, list/href_list)
switch(href_list["choice"])
/datum/data/pda/app/status_display/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("Status")
switch(href_list["statdisp"])
switch(params["statdisp"])
if("message")
post_status("message", message1, message2)
if("alert")
post_status("alert", href_list["alert"])
post_status("alert", params["alert"])
if("setmsg1")
message1 = clean_input("Line 1", "Enter Message Text", message1)
if("setmsg2")
message2 = clean_input("Line 2", "Enter Message Text", message2)
else
post_status(href_list["statdisp"])
post_status(params["statdisp"])
return TRUE
/datum/data/pda/app/status_display/proc/post_status(var/command, var/data1, var/data2)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
@@ -43,7 +46,7 @@
status_signal.data["msg2"] = data2
var/mob/user = pda.fingerprintslast
if(istype(pda.loc, /mob/living))
name = pda.loc
user = pda.loc
log_admin("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]")
message_admins("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]")
@@ -66,21 +69,23 @@
data["signal_freq"] = format_frequency(R.frequency)
data["signal_code"] = R.code
/datum/data/pda/app/signaller/Topic(href, list/href_list)
/datum/data/pda/app/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/signal))
var/obj/item/radio/integrated/signal/R = pda.cartridge.radio
switch(href_list["choice"])
switch(action)
if("Send Signal")
spawn(0)
R.send_signal("ACTIVATE")
if("Signal Frequency")
var/new_frequency = sanitize_frequency(R.frequency + text2num(href_list["sfreq"]))
var/new_frequency = sanitize_frequency(R.frequency + text2num(params["sfreq"]))
R.set_frequency(new_frequency)
if("Signal Code")
R.code += text2num(href_list["scode"])
R.code += text2num(params["scode"])
R.code = round(R.code)
R.code = min(100, R.code)
R.code = max(1, R.code)
@@ -90,36 +95,29 @@
icon = "exclamation-triangle"
template = "pda_power"
category = "Engineering"
update = PDA_APP_UPDATE_SLOW
// var/obj/machinery/computer/monitor/powmonitor = null
var/datum/tgui_module/power_monitor/power_monitor
// /datum/data/pda/app/power/update_ui(mob/user as mob, list/data)
// update = PDA_APP_UPDATE_SLOW
/datum/data/pda/app/power/New()
power_monitor = new(src)
. = ..()
// if(powmonitor && !isnull(powmonitor.powernet))
// data["records"] = list(
// "powerconnected" = 1,
// "poweravail" = powmonitor.powernet.avail,
// "powerload" = num2text(powmonitor.powernet.viewload, 10),
// "powerdemand" = powmonitor.powernet.load,
// "apcs" = GLOB.apc_repository.apc_data(powmonitor.powernet))
// has_back = 1
// else
// data["records"] = list(
// "powerconnected" = 0,
// "powermonitors" = GLOB.powermonitor_repository.powermonitor_data())
// has_back = 0
/datum/data/pda/app/power/Destroy()
QDEL_NULL(power_monitor)
return ..()
// /datum/data/pda/app/power/Topic(href, list/href_list)
// switch(href_list["choice"])
// if("Power Select")
// var/pref = href_list["target"]
// powmonitor = locate(pref)
// update = PDA_APP_UPDATE
// if("Back")
// powmonitor = null
// update = PDA_APP_UPDATE
/datum/data/pda/app/power/update_ui(mob/user as mob, list/data)
data.Add(power_monitor.tgui_data(user))
/datum/data/pda/app/power/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(power_monitor.tgui_act(action, params, ui, state))
return TRUE
switch(action)
if("Back")
power_monitor.active_sensor = null
return TRUE
/datum/data/pda/app/crew_records
var/datum/data/record/general_records = null
@@ -137,17 +135,22 @@
if(R)
records += list(list(Name = R.fields["name"], "ref" = "\ref[R]"))
data["recordsList"] = records
data["records"] = null
return null
/datum/data/pda/app/crew_records/Topic(href, list/href_list)
switch(href_list["choice"])
/datum/data/pda/app/crew_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("Records")
var/datum/data/record/R = locate(href_list["target"])
var/datum/data/record/R = locate(params["target"])
if(R && (R in data_core.general))
load_records(R)
return TRUE
if("Back")
general_records = null
has_back = 0
return TRUE
/datum/data/pda/app/crew_records/proc/load_records(datum/data/record/R)
general_records = R
@@ -247,11 +250,14 @@
data["beepsky"] = beepskyData
/datum/data/pda/app/secbot_control/Topic(href, list/href_list)
switch(href_list["choice"])
/datum/data/pda/app/secbot_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("Back")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/beepsky))
pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist"))
return TRUE
/datum/data/pda/app/mule_control
name = "Delivery Bot Control"
@@ -259,104 +265,97 @@
template = "pda_mule"
category = "Quartermaster"
// /datum/data/pda/app/mule_control/update_ui(mob/user as mob, list/data)
// var/muleData[0]
// var/mulebotsData[0]
// if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
// var/obj/item/radio/integrated/mule/QC = pda.cartridge.radio
// muleData["active"] = QC.active ? sanitize(QC.active.name) : null
// has_back = QC.active ? 1 : 0
// if(QC.active && !isnull(QC.botstatus))
// var/area/loca = QC.botstatus["loca"]
// var/loca_name = sanitize(loca.name)
// muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"]))
/datum/data/pda/app/mule_control/update_ui(mob/user as mob, list/data)
var/muleData[0]
var/mulebotsData[0]
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
var/obj/item/radio/integrated/mule/QC = pda.cartridge.radio
muleData["active"] = QC.active ? sanitize(QC.active.name) : null
has_back = QC.active ? 1 : 0
if(QC.active && !isnull(QC.botstatus))
var/area/loca = QC.botstatus["loca"]
var/loca_name = sanitize(loca.name)
muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"]))
// else
// muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
else
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
// var/mulebotsCount=0
// for(var/mob/living/bot/B in QC.botlist)
// mulebotsCount++
// if(B.loc)
// mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
var/mulebotsCount=0
for(var/mob/living/bot/B in QC.botlist)
mulebotsCount++
if(B.loc)
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
// if(!mulebotsData.len)
// mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
if(!mulebotsData.len)
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
// muleData["bots"] = mulebotsData
// muleData["count"] = mulebotsCount
muleData["bots"] = mulebotsData
muleData["count"] = mulebotsCount
// else
// muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
// muleData["active"] = 0
// mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
// muleData["bots"] = mulebotsData
// muleData["count"] = 0
// has_back = 0
else
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
muleData["active"] = 0
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
muleData["bots"] = mulebotsData
muleData["count"] = 0
has_back = 0
// data["mulebot"] = muleData
data["mulebot"] = muleData
// /datum/data/pda/app/mule_control/Topic(href, list/href_list)
// switch(href_list["choice"])
// if("Back")
// if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
// pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist"))
/datum/data/pda/app/mule_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("Back")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist"))
return TRUE
/datum/data/pda/app/supply
name = "Supply Records"
icon = "file-text-o"
icon = "file-word-o"
template = "pda_supply"
category = "Quartermaster"
update = PDA_APP_UPDATE_SLOW
// /datum/data/pda/app/supply/update_ui(mob/user as mob, list/data)
// var/supplyData[0]
/datum/data/pda/app/supply/update_ui(mob/user as mob, list/data)
var/supplyData[0]
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (shuttle)
supplyData["shuttle_moving"] = shuttle.has_arrive_time()
supplyData["shuttle_eta"] = shuttle.eta_minutes()
supplyData["shuttle_loc"] = shuttle.at_station() ? "Station" : "Dock"
var/supplyOrderCount = 0
var/supplyOrderData[0]
for(var/S in SSsupply.shoppinglist)
var/datum/supply_order/SO = S
// if(SSshuttle.supply.mode == SHUTTLE_CALL)
// supplyData["shuttle_moving"] = 1
supplyOrderCount++
supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
// if(is_station_level(SSshuttle.supply.z))
// supplyData["shuttle_loc"] = "Station"
// else
// supplyData["shuttle_loc"] = "CentCom"
supplyData["approved"] = supplyOrderData
supplyData["approved_count"] = supplyOrderCount
// supplyData["shuttle_time"] = "([SSshuttle.supply.timeLeft(600)] Mins)"
var/requestCount = 0
var/requestData[0]
for(var/S in SSsupply.order_history)
var/datum/supply_order/SO = S
if(SO.status != SUP_ORDER_REQUESTED)
continue
// var/supplyOrderCount = 0
// var/supplyOrderData[0]
// for(var/S in SSshuttle.shoppinglist)
// var/datum/supply_order/SO = S
// supplyOrderCount++
// supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderedby, "Comment" = html_encode(SO.comment))
requestCount++
requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
// if(!supplyOrderData.len)
// supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null)
supplyData["requests"] = requestData
supplyData["requests_count"] = requestCount
// supplyData["approved"] = supplyOrderData
// supplyData["approved_count"] = supplyOrderCount
// var/requestCount = 0
// var/requestData[0]
// for(var/S in SSshuttle.requestlist)
// var/datum/supply_order/SO = S
// requestCount++
// requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderedby, "Comment" = html_encode(SO.comment))
// if(!requestData.len)
// requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null)
// supplyData["requests"] = requestData
// supplyData["requests_count"] = requestCount
// data["supply"] = supplyData
data["supply"] = supplyData
/datum/data/pda/app/janitor
name = "Custodial Locator"
icon = "trash-o"
icon = "trash-alt-o"
template = "pda_janitor"
category = "Utilities"
update = PDA_APP_UPDATE_SLOW
/datum/data/pda/app/janitor/update_ui(mob/user as mob, list/data)
var/JaniData[0]

View File

@@ -6,12 +6,15 @@ var/list/exploration_cartridges = list(
/obj/item/weapon/cartridge/explorer
name = "\improper Explorator cartridge"
icon_state = "cart-e"
access_reagent_scanner = 1
access_atmos = 1
programs = list(
new/datum/data/pda/utility/scanmode/reagent,
new/datum/data/pda/utility/scanmode/gas)
/obj/item/weapon/cartridge/sar
name = "\improper Med-Exp cartridge"
icon_state = "cart-m"
access_medical = 1
access_reagent_scanner = 1
access_atmos = 1
programs = list(
new/datum/data/pda/app/crew_records/medical,
new/datum/data/pda/utility/scanmode/medical,
new/datum/data/pda/utility/scanmode/reagent,
new/datum/data/pda/utility/scanmode/gas)

View File

@@ -17,18 +17,21 @@
notifying["\ref[P]"] = 1
data["notifying"] = notifying
/datum/data/pda/app/main_menu/Topic(href, list/href_list)
switch(href_list["choice"])
/datum/data/pda/app/main_menu/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("UpdateInfo")
pda.ownjob = pda.id.assignment
pda.ownrank = pda.id.rank
pda.name = "PDA-[pda.owner] ([pda.ownjob])"
return TRUE
if("pai")
if(pda.pai)
if(pda.pai.loc != pda)
pda.pai = null
else
switch(href_list["option"])
switch(params["option"])
if("1") // Configure pAI device
pda.pai.attack_self(usr)
if("2") // Eject pAI device
@@ -36,6 +39,7 @@
if(T)
pda.pai.loc = T
pda.pai = null
return TRUE
/datum/data/pda/app/notekeeper
name = "Notekeeper"
@@ -53,8 +57,10 @@
/datum/data/pda/app/notekeeper/update_ui(mob/user as mob, list/data)
data["note"] = note // current pda notes
/datum/data/pda/app/notekeeper/Topic(href, list/href_list)
switch(href_list["choice"])
/datum/data/pda/app/notekeeper/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("Edit")
var/n = input("Please enter message", name, notehtml) as message
if(pda.loc == usr)
@@ -63,49 +69,59 @@
note = replacetext(note, "\n", "<br>")
else
pda.close(usr)
return TRUE
/datum/data/pda/app/manifest
name = "Crew Manifest"
icon = "user"
template = "pda_manifest"
update = PDA_APP_UPDATE_SLOW
// /datum/data/pda/app/manifest/update_ui(mob/user as mob, list/data)
// data_core.get_manifest_json()
// data["manifest"] = PDA_Manifest
/datum/data/pda/app/manifest/update_ui(mob/user as mob, list/data)
if(data_core)
data_core.get_manifest_list()
data["manifest"] = PDA_Manifest
/datum/data/pda/app/manifest/Topic(href, list/href_list)
/datum/data/pda/app/manifest/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
/datum/data/pda/app/atmos_scanner
name = "Atmospheric Scan"
icon = "fire"
template = "pda_atmos_scan"
category = "Utilities"
update = PDA_APP_UPDATE_SLOW
// /datum/data/pda/app/atmos_scanner/update_ui(mob/user as mob, list/data)
// var/turf/T = get_turf(user.loc)
// if(!isnull(T))
// var/datum/gas_mixture/environment = T.return_air()
/datum/data/pda/app/atmos_scanner/update_ui(mob/user as mob, list/data)
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)
// var/pressure = environment.return_pressure()
// var/total_moles = environment.total_moles
// 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(total_moles)
// var/o2_level = environment.oxygen/total_moles
// var/n2_level = environment.nitrogen/total_moles
// var/co2_level = environment.carbon_dioxide/total_moles
// var/plasma_level = environment.toxins/total_moles
// var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
// data["aircontents"] = list(
// "pressure" = pressure,
// "nitrogen" = n2_level*100,
// "oxygen" = o2_level*100,
// "carbon_dioxide" = co2_level*100,
// "plasma" = plasma_level*100,
// "other" = unknown_level,
// "temp" = environment.temperature-T0C,
// "reading" = 1
// )
// if(isnull(data["aircontents"]))
// data["aircontents"] = list("reading" = 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

View File

@@ -12,13 +12,10 @@
var/m_hidden = 0 // Is the PDA hidden from the PDA list?
var/active_conversation = null // New variable that allows us to only view a single conversation.
var/list/conversations = list() // For keeping up with who we have PDA messsages from.
var/latest_post = 0
var/auto_scroll = 1
/datum/data/pda/app/messenger/start()
. = ..()
unnotify()
latest_post = 0
/datum/data/pda/app/messenger/update_ui(mob/user as mob, list/data)
data["silent"] = notify_silent // does the pda make noise when it receives a message?
@@ -33,9 +30,6 @@
data["convo_name"] = sanitize(c["owner"])
data["convo_job"] = sanitize(c["job"])
break
data["auto_scroll"] = auto_scroll
data["latest_post"] = latest_post
latest_post = tnote.len
else
var/convopdas[0]
var/pdas[0]
@@ -63,21 +57,23 @@
if(pda.cartridge)
data["charges"] = pda.cartridge.charges ? pda.cartridge.charges : 0
/datum/data/pda/app/messenger/Topic(href, list/href_list)
if(!pda.can_use())
return
/datum/data/pda/app/messenger/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
unnotify()
switch(href_list["choice"])
. = TRUE
switch(action)
if("Toggle Messenger")
toff = !toff
if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
notify_silent = !notify_silent
if("Clear")//Clears messages
if(href_list["option"] == "All")
if(params["option"] == "All")
tnote.Cut()
conversations.Cut()
if(href_list["option"] == "Convo")
if(params["option"] == "Convo")
var/new_tnote[0]
for(var/i in tnote)
if(i["target"] != active_conversation)
@@ -86,36 +82,30 @@
conversations.Remove(active_conversation)
active_conversation = null
latest_post = 0
if("Message")
var/obj/item/device/pda/P = locate(href_list["target"])
var/obj/item/device/pda/P = locate(params["target"])
create_message(usr, P)
if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp.
active_conversation = href_list["target"]
latest_post = 0
if(params["target"] in conversations) // Need to make sure the message went through, if not welp.
active_conversation = params["target"]
if("Select Conversation")
var/P = href_list["convo"]
var/P = params["target"]
for(var/n in conversations)
if(P == n)
active_conversation = P
latest_post = 0
if("Messenger Plugin")
if(!href_list["target"] || !href_list["plugin"])
if(!params["target"] || !params["plugin"])
return
var/obj/item/device/pda/P = locate(href_list["target"])
var/obj/item/device/pda/P = locate(params["target"])
if(!P)
to_chat(usr, "PDA not found.")
var/datum/data/pda/messenger_plugin/plugin = locate(href_list["plugin"])
var/datum/data/pda/messenger_plugin/plugin = locate(params["plugin"])
if(plugin && (plugin in pda.cartridge.messenger_plugins))
plugin.messenger = src
plugin.user_act(usr, P)
if("Back")
active_conversation = null
latest_post = 0
if("Autoscroll")
auto_scroll = !auto_scroll
/datum/data/pda/app/messenger/proc/create_message(var/mob/living/U, var/obj/item/device/pda/P)
var/t = input(U, "Please enter message", name, null) as text|null
@@ -178,7 +168,7 @@
if(!PM.conversations.Find("\ref[pda]"))
PM.conversations.Add("\ref[pda]")
SSnanoui.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message
SStgui.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message
PM.notify("<b>Message from [pda.owner] ([pda.ownjob]), </b>\"[t]\" (<a href='?src=[REF(PM)];choice=Message;target=\ref[pda]'>Reply</a>)")
log_pda("(PDA: [src.name]) sent \"[t]\" to [P.name]", usr)
else

View File

@@ -18,7 +18,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/owner = null
var/default_cartridge = 0 // Access level defined by cartridge
var/obj/item/weapon/cartridge/cartridge = null //current cartridge
var/ui_tick = 0
//Secondary variables
// var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner.
@@ -144,347 +143,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
close(usr)
return 0
/obj/item/device/pda/medical
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-m"
/obj/item/device/pda/viro
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-v"
/obj/item/device/pda/engineering
default_cartridge = /obj/item/weapon/cartridge/engineering
icon_state = "pda-e"
/obj/item/device/pda/security
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-s"
/obj/item/device/pda/detective
default_cartridge = /obj/item/weapon/cartridge/detective
icon_state = "pda-det"
/obj/item/device/pda/warden
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-warden"
/obj/item/device/pda/janitor
default_cartridge = /obj/item/weapon/cartridge/janitor
icon_state = "pda-j"
ttone = "slip"
/obj/item/device/pda/science
default_cartridge = /obj/item/weapon/cartridge/signal/science
icon_state = "pda-tox"
ttone = "boom"
/obj/item/device/pda/clown
default_cartridge = /obj/item/weapon/cartridge/clown
icon_state = "pda-clown"
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
ttone = "honk"
/obj/item/device/pda/mime
default_cartridge = /obj/item/weapon/cartridge/mime
icon_state = "pda-mime"
message_silent = 1
news_silent = 1
ttone = "silence"
newstone = "silence"
/obj/item/device/pda/heads
default_cartridge = /obj/item/weapon/cartridge/head
icon_state = "pda-h"
news_silent = 1
/obj/item/device/pda/heads/hop
default_cartridge = /obj/item/weapon/cartridge/hop
icon_state = "pda-hop"
/obj/item/device/pda/heads/hos
default_cartridge = /obj/item/weapon/cartridge/hos
icon_state = "pda-hos"
/obj/item/device/pda/heads/ce
default_cartridge = /obj/item/weapon/cartridge/ce
icon_state = "pda-ce"
/obj/item/device/pda/heads/cmo
default_cartridge = /obj/item/weapon/cartridge/cmo
icon_state = "pda-cmo"
/obj/item/device/pda/heads/rd
default_cartridge = /obj/item/weapon/cartridge/rd
icon_state = "pda-rd"
/obj/item/device/pda/captain
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-c"
detonate = 0
//toff = 1
/obj/item/device/pda/ert
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-h"
detonate = 0
// hidden = 1
/obj/item/device/pda/cargo
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-cargo"
/obj/item/device/pda/quartermaster
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-q"
/obj/item/device/pda/shaftminer
icon_state = "pda-miner"
default_cartridge = /obj/item/weapon/cartridge/miner
/obj/item/device/pda/syndicate
default_cartridge = /obj/item/weapon/cartridge/syndicate
icon_state = "pda-syn"
// name = "Military PDA" // Vorestation Edit
// owner = "John Doe"
hidden = 1
/obj/item/device/pda/chaplain
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-holy"
ttone = "holy"
/obj/item/device/pda/lawyer
default_cartridge = /obj/item/weapon/cartridge/lawyer
icon_state = "pda-lawyer"
ttone = "..."
/obj/item/device/pda/botanist
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-hydro"
/obj/item/device/pda/roboticist
default_cartridge = /obj/item/weapon/cartridge/signal/science
icon_state = "pda-robot"
/obj/item/device/pda/librarian
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-libb"
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader."
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
message_silent = 1 //Quiet in the library!
news_silent = 0 // Librarian is above the law! (That and alt job title is reporter)
/obj/item/device/pda/clear
icon_state = "pda-transp"
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case."
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
/obj/item/device/pda/chef
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-chef"
/obj/item/device/pda/bar
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-bar"
/obj/item/device/pda/atmos
default_cartridge = /obj/item/weapon/cartridge/atmos
icon_state = "pda-atmo"
/obj/item/device/pda/chemist
default_cartridge = /obj/item/weapon/cartridge/chemistry
icon_state = "pda-chem"
/obj/item/device/pda/geneticist
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-gene"
// Special AI/pAI PDAs that cannot explode.
/obj/item/device/pda/ai
icon_state = "NONE"
ttone = "data"
newstone = "news"
detonate = 0
/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text)
owner = newname
ownjob = newjob
if(newrank)
ownrank = newrank
else
ownrank = ownjob
name = newname + " (" + ownjob + ")"
//AI verb and proc for sending PDA messages.
/obj/item/device/pda/ai/verb/cmd_send_pdamesg()
set category = "AI IM"
set name = "Send Message"
set src in usr
if(usr.stat == 2)
to_chat(usr, "You can't send PDA messages because you are dead!")
return
var/list/plist = 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]
create_message(usr, selected, 0)
/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver()
set category = "AI IM"
set name = "Toggle Sender/Receiver"
set src in usr
if(usr.stat == 2)
to_chat(usr, "You can't send PDA messages because you are dead!")
return
toff = !toff
to_chat(usr, "<span class='notice'>PDA sender/receiver toggled [(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(usr.stat == 2)
to_chat(usr, "You can't send PDA messages because you are dead!")
return
message_silent=!message_silent
to_chat(usr, "<span class='notice'>PDA ringer toggled [(message_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(usr.stat == 2)
to_chat(usr, "You can't send PDA messages because you are dead!")
return
var/HTML = "<html><head><title>AI PDA Message Log</title></head><body>"
for(var/index in tnote)
if(index["sent"])
HTML += addtext("<i><b>&rarr; To <a href='byond://?src=\ref[src];choice=Message;notap=1;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;notap=1;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")
/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--
playsound(src, 'sound/items/bikehorn.ogg', 30, 1)
return
/obj/item/device/pda/ai/pai
ttone = "assist"
/obj/item/device/pda/ai/shell
spam_proof = TRUE // Since empty shells get a functional PDA.
// Used for the PDA multicaster, which mirrors messages sent to it to a specific department,
/obj/item/device/pda/multicaster
ownjob = "Relay"
icon_state = "NONE"
ttone = "data"
detonate = 0
news_silent = 1
spam_proof = TRUE // Spam messages don't actually work and its difficult to disable these.
var/list/cartridges_to_send_to = list()
// This is what actually mirrors the message,
/obj/item/device/pda/multicaster/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
if(sender)
var/list/targets = list()
for(var/obj/item/device/pda/pda in PDAs)
if(pda.cartridge && pda.owner && is_type_in_list(pda.cartridge, cartridges_to_send_to))
targets |= pda
if(targets.len)
for(var/obj/item/device/pda/target in targets)
create_message(target, sender, sender_job, message)
// This has so much copypasta,
/obj/item/device/pda/multicaster/create_message(var/obj/item/device/pda/P, var/original_sender, var/original_job, var/t)
t = sanitize(t, MAX_MESSAGE_LEN, 0)
t = replace_characters(t, list("&#34;" = "\""))
if (!t || !istype(P))
return
if (isnull(P)||P.toff || toff)
return
last_text = world.time
var/datum/reception/reception = get_reception(src, P, t)
t = reception.message
if(reception.message_server && (reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER)) // only send the message if it's stable,
if(reception.telecomms_reception & TELECOMMS_RECEPTION_RECEIVER == 0) // Does our recipient have a broadcaster on their level?,
return
var/send_result = reception.message_server.send_pda_message("[P.owner]","[owner]","[t]")
if (send_result)
return
P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]")))
if(!P.conversations.Find("\ref[src]"))
P.conversations.Add("\ref[src]")
P.new_message(src, "[original_sender] \[Relayed\]", original_job, t, 0)
else
return
/obj/item/device/pda/multicaster/command/New()
..()
owner = "Command Department"
name = "Command Department (Relay)"
cartridges_to_send_to = command_cartridges
/obj/item/device/pda/multicaster/security/New()
..()
owner = "Security Department"
name = "Security Department (Relay)"
cartridges_to_send_to = security_cartridges
/obj/item/device/pda/multicaster/engineering/New()
..()
owner = "Engineering Department"
name = "Engineering Department (Relay)"
cartridges_to_send_to = engineering_cartridges
/obj/item/device/pda/multicaster/medical/New()
..()
owner = "Medical Department"
name = "Medical Department (Relay)"
cartridges_to_send_to = medical_cartridges
/obj/item/device/pda/multicaster/research/New()
..()
owner = "Research Department"
name = "Research Department (Relay)"
cartridges_to_send_to = research_cartridges
/obj/item/device/pda/multicaster/cargo/New()
..()
owner = "Cargo Department"
name = "Cargo Department (Relay)"
cartridges_to_send_to = cargo_cartridges
/obj/item/device/pda/multicaster/civilian/New()
..()
owner = "Civilian Services Department"
name = "Civilian Services Department (Relay)"
cartridges_to_send_to = civilian_cartridges
/*
* The Actual PDA
*/
/obj/item/device/pda/New(var/mob/living/carbon/human/H)
..()
PDAs += src
@@ -492,6 +150,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
update_programs()
if(default_cartridge)
cartridge = new default_cartridge(src)
cartridge.update_programs(src)
new /obj/item/weapon/pen(src)
pdachoice = isnull(H) ? 1 : (ishuman(H) ? H.pdachoice : 1)
switch(pdachoice)
@@ -519,19 +178,16 @@ var/global/list/obj/item/device/pda/PDAs = list()
log_debug("Invalid switch for PDA, defaulting to old PDA icons. [pdachoice] chosen.")
start_program(find_program(/datum/data/pda/app/main_menu))
/obj/item/device/pda/proc/can_use()
if(!ismob(loc))
return 0
return FALSE
var/mob/M = loc
if(M.stat || M.restrained() || M.paralysis || M.stunned || M.weakened)
return 0
if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) ))
return 1
else
return 0
if(M.incapacitated(INCAPACITATION_ALL))
return FALSE
if(src in M.contents)
return TRUE
return FALSE
/obj/item/device/pda/GetAccess()
if(id)
@@ -549,97 +205,14 @@ var/global/list/obj/item/device/pda/PDAs = list()
return
/obj/item/device/pda/proc/close(mob/user)
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
ui.close()
SStgui.close_uis(src)
/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui_tick++
var/datum/nanoui/old_ui = SSnanoui.get_open_ui(user, src, "main")
var/auto_update = 1
if(!current_app)
return
if(current_app.update == PDA_APP_NOUPDATE && current_app == lastapp)
auto_update = 0
if(old_ui && (current_app == lastapp && ui_tick % 5 && current_app.update == PDA_APP_UPDATE_SLOW))
return
lastapp = current_app
var/title = "Personal Data Assistant"
var/data[0] // This is the data that will be sent to the PDA
data["owner"] = owner // Who is your daddy...
data["ownjob"] = ownjob // ...and what does he do?
// update list of shortcuts, only if they changed
if(!shortcut_cache.len)
shortcut_cache = list()
shortcut_cat_order = list()
var/prog_list = programs.Copy()
if(cartridge)
prog_list |= cartridge.programs
for(var/A in prog_list)
var/datum/data/pda/P = A
if(P.hidden)
continue
var/list/cat
if(P.category in shortcut_cache)
cat = shortcut_cache[P.category]
else
cat = list()
shortcut_cache[P.category] = cat
shortcut_cat_order += P.category
cat |= list(list(name = P.name, icon = P.icon, notify_icon = P.notify_icon, ref = "\ref[P]"))
// force the order of a few core categories
shortcut_cat_order = list("General") \
+ sortList(shortcut_cat_order - list("General", "Scanners", "Utilities")) \
+ list("Scanners", "Utilities")
data["idInserted"] = (id ? 1 : 0)
data["idLink"] = (id ? text("[id.registered_name], [id.assignment]") : "--------")
data["useRetro"] = retro_mode
data["cartridge_name"] = cartridge ? cartridge.name : ""
data["stationTime"] = worldtime2stationtime(world.time)
data["app"] = list()
current_app.update_ui(user, data)
data["app"] |= list(
"name" = current_app.title,
"icon" = current_app.icon,
"template" = current_app.template,
"has_back" = current_app.has_back)
// 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, "pda.tmpl", title, 520, 400, state = inventory_state)
ui.set_state_key("pda")
// 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(auto_update)
/obj/item/device/pda/attack_self(mob/user as mob)
user.set_machine(src)
if(active_uplink_check(user))
return
ui_interact(user) //NanoUI requires this proc
tgui_interact(user)
return
@@ -667,76 +240,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/datum/data/pda/P = A
P.pda = src
/obj/item/device/pda/Topic(href, href_list)
. = ..()
if(.)
return
var/mob/user = usr
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
var/mob/living/U = usr
if(usr.stat == DEAD)
return 0
if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that.
U.unset_machine()
if(ui)
ui.close()
return 0
add_fingerprint(U)
U.set_machine(src)
if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio))
cartridge.radio.Topic(href, href_list)
return 1
. = 1
switch(href_list["choice"])
if("Home")//Go home, largely replaces the old Return
var/datum/data/pda/app/main_menu/A = find_program(/datum/data/pda/app/main_menu)
if(A)
start_program(A)
if("StartProgram")
if(href_list["program"])
var/datum/data/pda/app/A = locate(href_list["program"])
if(A)
start_program(A)
if("Eject")//Ejects the cart, only done from hub.
if(!isnull(cartridge))
var/turf/T = loc
if(ismob(T))
T = T.loc
var/obj/item/weapon/cartridge/C = cartridge
C.forceMove(T)
if(scanmode in C.programs)
scanmode = null
if(current_app in C.programs)
start_program(find_program(/datum/data/pda/app/main_menu))
if(C.radio)
C.radio.hostpda = null
for(var/datum/data/pda/P in notifying_programs)
if(P in C.programs)
P.unnotify()
cartridge = null
update_shortcuts()
if("Authenticate")//Checks for ID
id_check(usr, 1)
if("Retro")
retro_mode = !retro_mode
if("Ringtone")
return set_ringtone()
else
if(current_app)
. = current_app.Topic(href, href_list)
//EXTRA FUNCTIONS===================================
if((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
return // return 1 tells it to refresh the UI in NanoUI
/obj/item/device/pda/update_icon()
..()
@@ -895,7 +398,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
ai.show_message("<i>Intercepted message from <b>[who]</b>: [t]</i>")
P.new_message_from_pda(src, t)
SSnanoui.update_user_uis(U, src) // Update the sending user's PDA UI so that they can see the new message
SStgui.update_user_uis(U, src) // Update the sending user's PDA UI so that they can see the new message
else
to_chat(U, "<span class='notice'>ERROR: Messaging server is not responding.</span>")
@@ -915,7 +418,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(L)
if(reception_message)
to_chat(L,reception_message)
SSnanoui.update_user_uis(L, src) // Update the receiving user's PDA UI so that they can see the new message
SStgui.update_user_uis(L, src) // Update the receiving user's PDA UI so that they can see the new message
/obj/item/device/pda/proc/new_news(var/message)
new_info(news_silent, newstone, news_silent ? "" : "[bicon(src)] <b>[message]</b>")
@@ -924,9 +427,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_news = 1
update_icon()
/obj/item/device/pda/ai/new_news(var/message)
// Do nothing
/obj/item/device/pda/proc/new_message_from_pda(var/obj/item/device/pda/sending_device, var/message)
if (is_jammed(src))
return
@@ -940,17 +440,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_message = 1
update_icon()
/obj/item/device/pda/ai/new_message(var/atom/movable/sending_unit, var/sender, var/sender_job, var/message)
var/track = ""
if(ismob(sending_unit.loc) && isAI(loc))
track = "(<a href='byond://?src=\ref[loc];track=\ref[sending_unit.loc];trackname=[html_encode(sender)]'>Follow</a>)"
var/reception_message = "[bicon(src)] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=1;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
new_info(message_silent, newstone, reception_message)
log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]",usr)
new_message = 1
/obj/item/device/pda/proc/spam_message(sender, message)
var/reception_message = "\icon[src] <b>Message from [sender] (Unknown / spam?), </b>\"[message]\" (Unable to Reply)"
new_info(message_silent, ttone, reception_message)
@@ -1062,8 +551,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
cartridge = C
user.drop_item()
cartridge.loc = src
cartridge.update_programs(src)
update_shortcuts()
to_chat(usr, "<span class='notice'>You insert [cartridge] into [src].</span>")
SSnanoui.update_uis(src) // update all UIs attached to src
if(cartridge.radio)
cartridge.radio.hostpda = src
@@ -1091,7 +581,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
C.loc = src
pai = C
to_chat(user, "<span class='notice'>You slot \the [C] into \the [src].</span>")
SSnanoui.update_uis(src) // update all UIs attached to src
SStgui.update_uis(src) // update all UIs attached to src
else if(istype(C, /obj/item/weapon/pen))
var/obj/item/weapon/pen/O = locate() in src
if(O)
@@ -1253,16 +743,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
QDEL_NULL(cartridge)
return ..()
/obj/item/device/pda/clown/Crossed(atom/movable/AM as mob|obj) //Clown PDA is slippery.
if(AM.is_incorporeal())
return
if (istype(AM, /mob/living))
var/mob/living/M = AM
if(M.slip("the PDA",8) && M.real_name != src.owner && istype(src.cartridge, /obj/item/weapon/cartridge/clown))
if(src.cartridge.charges < 5)
src.cartridge.charges++
/obj/item/device/pda/proc/available_pdas()
var/list/names = list()
var/list/plist = list()
@@ -1301,7 +781,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
icon = 'icons/obj/pda.dmi'
icon_state = "pdabox"
New()
/obj/item/weapon/storage/box/PDAs/New()
..()
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)

View File

@@ -0,0 +1,282 @@
/obj/item/device/pda/medical
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-m"
/obj/item/device/pda/viro
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-v"
/obj/item/device/pda/engineering
default_cartridge = /obj/item/weapon/cartridge/engineering
icon_state = "pda-e"
/obj/item/device/pda/security
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-s"
/obj/item/device/pda/detective
default_cartridge = /obj/item/weapon/cartridge/detective
icon_state = "pda-det"
/obj/item/device/pda/warden
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-warden"
/obj/item/device/pda/janitor
default_cartridge = /obj/item/weapon/cartridge/janitor
icon_state = "pda-j"
ttone = "slip"
/obj/item/device/pda/science
default_cartridge = /obj/item/weapon/cartridge/signal/science
icon_state = "pda-tox"
ttone = "boom"
/obj/item/device/pda/clown
default_cartridge = /obj/item/weapon/cartridge/clown
icon_state = "pda-clown"
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
ttone = "honk"
/obj/item/device/pda/mime
default_cartridge = /obj/item/weapon/cartridge/mime
icon_state = "pda-mime"
message_silent = 1
news_silent = 1
ttone = "silence"
newstone = "silence"
/obj/item/device/pda/heads
default_cartridge = /obj/item/weapon/cartridge/head
icon_state = "pda-h"
news_silent = 1
/obj/item/device/pda/heads/hop
default_cartridge = /obj/item/weapon/cartridge/hop
icon_state = "pda-hop"
/obj/item/device/pda/heads/hos
default_cartridge = /obj/item/weapon/cartridge/hos
icon_state = "pda-hos"
/obj/item/device/pda/heads/ce
default_cartridge = /obj/item/weapon/cartridge/ce
icon_state = "pda-ce"
/obj/item/device/pda/heads/cmo
default_cartridge = /obj/item/weapon/cartridge/cmo
icon_state = "pda-cmo"
/obj/item/device/pda/heads/rd
default_cartridge = /obj/item/weapon/cartridge/rd
icon_state = "pda-rd"
/obj/item/device/pda/captain
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-c"
detonate = 0
//toff = 1
/obj/item/device/pda/ert
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-h"
detonate = 0
// hidden = 1
/obj/item/device/pda/cargo
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-cargo"
/obj/item/device/pda/quartermaster
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-q"
/obj/item/device/pda/shaftminer
icon_state = "pda-miner"
default_cartridge = /obj/item/weapon/cartridge/miner
/obj/item/device/pda/syndicate
default_cartridge = /obj/item/weapon/cartridge/syndicate
icon_state = "pda-syn"
// name = "Military PDA" // Vorestation Edit
// owner = "John Doe"
hidden = 1
/obj/item/device/pda/chaplain
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-holy"
ttone = "holy"
/obj/item/device/pda/lawyer
default_cartridge = /obj/item/weapon/cartridge/lawyer
icon_state = "pda-lawyer"
ttone = "..."
/obj/item/device/pda/botanist
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-hydro"
/obj/item/device/pda/roboticist
default_cartridge = /obj/item/weapon/cartridge/signal/science
icon_state = "pda-robot"
/obj/item/device/pda/librarian
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-libb"
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader."
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
message_silent = 1 //Quiet in the library!
news_silent = 0 // Librarian is above the law! (That and alt job title is reporter)
/obj/item/device/pda/clear
icon_state = "pda-transp"
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case."
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
/obj/item/device/pda/chef
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-chef"
/obj/item/device/pda/bar
default_cartridge = /obj/item/weapon/cartridge/service
icon_state = "pda-bar"
/obj/item/device/pda/atmos
default_cartridge = /obj/item/weapon/cartridge/atmos
icon_state = "pda-atmo"
/obj/item/device/pda/chemist
default_cartridge = /obj/item/weapon/cartridge/chemistry
icon_state = "pda-chem"
/obj/item/device/pda/geneticist
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-gene"
// Used for the PDA multicaster, which mirrors messages sent to it to a specific department,
/obj/item/device/pda/multicaster
ownjob = "Relay"
icon_state = "NONE"
ttone = "data"
detonate = 0
news_silent = 1
spam_proof = TRUE // Spam messages don't actually work and its difficult to disable these.
var/list/cartridges_to_send_to = list()
// This is what actually mirrors the message,
/obj/item/device/pda/multicaster/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
if(sender)
var/list/targets = list()
for(var/obj/item/device/pda/pda in PDAs)
if(pda.cartridge && pda.owner && is_type_in_list(pda.cartridge, cartridges_to_send_to))
targets |= pda
if(targets.len)
for(var/obj/item/device/pda/target in targets)
create_message(target, sender, sender_job, message)
// This has so much copypasta,
/obj/item/device/pda/multicaster/create_message(var/obj/item/device/pda/P, var/original_sender, var/original_job, var/t)
t = sanitize(t, MAX_MESSAGE_LEN, 0)
t = replace_characters(t, list("&#34;" = "\""))
if (!t || !istype(P))
return
if (isnull(P)||P.toff || toff)
return
last_text = world.time
var/datum/reception/reception = get_reception(src, P, t)
t = reception.message
if(reception.message_server && (reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER)) // only send the message if it's stable,
if(reception.telecomms_reception & TELECOMMS_RECEPTION_RECEIVER == 0) // Does our recipient have a broadcaster on their level?,
return
var/send_result = reception.message_server.send_pda_message("[P.owner]","[owner]","[t]")
if (send_result)
return
P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]")))
if(!P.conversations.Find("\ref[src]"))
P.conversations.Add("\ref[src]")
P.new_message(src, "[original_sender] \[Relayed\]", original_job, t, 0)
else
return
/obj/item/device/pda/multicaster/command/New()
..()
owner = "Command Department"
name = "Command Department (Relay)"
cartridges_to_send_to = command_cartridges
/obj/item/device/pda/multicaster/security/New()
..()
owner = "Security Department"
name = "Security Department (Relay)"
cartridges_to_send_to = security_cartridges
/obj/item/device/pda/multicaster/engineering/New()
..()
owner = "Engineering Department"
name = "Engineering Department (Relay)"
cartridges_to_send_to = engineering_cartridges
/obj/item/device/pda/multicaster/medical/New()
..()
owner = "Medical Department"
name = "Medical Department (Relay)"
cartridges_to_send_to = medical_cartridges
/obj/item/device/pda/multicaster/research/New()
..()
owner = "Research Department"
name = "Research Department (Relay)"
cartridges_to_send_to = research_cartridges
/obj/item/device/pda/multicaster/cargo/New()
..()
owner = "Cargo Department"
name = "Cargo Department (Relay)"
cartridges_to_send_to = cargo_cartridges
/obj/item/device/pda/multicaster/civilian/New()
..()
owner = "Civilian Services Department"
name = "Civilian Services Department (Relay)"
cartridges_to_send_to = civilian_cartridges
/obj/item/device/pda/clown/Crossed(atom/movable/AM as mob|obj) //Clown PDA is slippery.
if(AM.is_incorporeal())
return
if (istype(AM, /mob/living))
var/mob/living/M = AM
if(M.slip("the PDA",8) && M.real_name != src.owner && istype(src.cartridge, /obj/item/weapon/cartridge/clown))
if(src.cartridge.charges < 5)
src.cartridge.charges++
//Some spare PDAs in a box
/obj/item/weapon/storage/box/PDAs
name = "box of spare PDAs"
desc = "A box of spare PDA microcomputers."
icon = 'icons/obj/pda.dmi'
icon_state = "pdabox"
/obj/item/weapon/storage/box/PDAs/New()
..()
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/weapon/cartridge/head(src)
var/newcart = pick( /obj/item/weapon/cartridge/engineering,
/obj/item/weapon/cartridge/security,
/obj/item/weapon/cartridge/medical,
/obj/item/weapon/cartridge/signal/science,
/obj/item/weapon/cartridge/quartermaster)
new newcart(src)

View File

@@ -2,6 +2,11 @@
/obj/item/device/pda/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/pda/tgui_status(mob/user, datum/tgui_state/state)
. = ..()
if(!can_use())
. = min(., STATUS_UPDATE)
/obj/item/device/pda/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -47,13 +52,142 @@
data["useRetro"] = retro_mode
data["cartridge_name"] = cartridge ? cartridge.name : ""
data["stationTime"] = worldtime2stationtime(world.time)
data["stationTime"] = stationtime2text() //worldtime2stationtime(world.time) // Aaa which fucking one is canonical there's SO MANY
data["app"] = list(
"name" = current_app.title,
"icon" = current_app.icon,
"template" = current_app.template,
"has_back" = current_app.has_back)
current_app.update_ui(user, data)
return data
/obj/item/device/pda/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(!can_use())
usr.unset_machine()
if(ui)
ui.close()
return FALSE
add_fingerprint(usr)
usr.set_machine(src)
. = TRUE
switch(action)
if("Home") //Go home, largely replaces the old Return
var/datum/data/pda/app/main_menu/A = find_program(/datum/data/pda/app/main_menu)
if(A)
start_program(A)
if("StartProgram")
if(params["program"])
var/datum/data/pda/app/A = locate(params["program"])
if(A)
start_program(A)
if("Eject")//Ejects the cart, only done from hub.
if(!isnull(cartridge))
var/turf/T = loc
if(ismob(T))
T = T.loc
var/obj/item/weapon/cartridge/C = cartridge
C.forceMove(T)
if(scanmode in C.programs)
scanmode = null
if(current_app in C.programs)
start_program(find_program(/datum/data/pda/app/main_menu))
if(C.radio)
C.radio.hostpda = null
for(var/datum/data/pda/P in notifying_programs)
if(P in C.programs)
P.unnotify()
cartridge = null
update_shortcuts()
if("Authenticate")//Checks for ID
id_check(usr, 1)
if("Retro")
retro_mode = !retro_mode
if("Ringtone")
return set_ringtone()
else
if(current_app)
. = current_app.tgui_act(action, params, ui, state)
if((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
// Reference only, TODO: Remove
/obj/item/device/pda/Topic(href, href_list)
. = ..()
if(.)
return
var/mob/user = usr
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
var/mob/living/U = usr
if(usr.stat == DEAD)
return 0
if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that.
U.unset_machine()
if(ui)
ui.close()
return 0
add_fingerprint(U)
U.set_machine(src)
if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio))
cartridge.radio.Topic(href, href_list)
return 1
. = 1
switch(href_list["choice"])
if("Home")//Go home, largely replaces the old Return
var/datum/data/pda/app/main_menu/A = find_program(/datum/data/pda/app/main_menu)
if(A)
start_program(A)
if("StartProgram")
if(href_list["program"])
var/datum/data/pda/app/A = locate(href_list["program"])
if(A)
start_program(A)
if("Eject")//Ejects the cart, only done from hub.
if(!isnull(cartridge))
var/turf/T = loc
if(ismob(T))
T = T.loc
var/obj/item/weapon/cartridge/C = cartridge
C.forceMove(T)
if(scanmode in C.programs)
scanmode = null
if(current_app in C.programs)
start_program(find_program(/datum/data/pda/app/main_menu))
if(C.radio)
C.radio.hostpda = null
for(var/datum/data/pda/P in notifying_programs)
if(P in C.programs)
P.unnotify()
cartridge = null
update_shortcuts()
if("Authenticate")//Checks for ID
id_check(usr, 1)
if("Retro")
retro_mode = !retro_mode
if("Ringtone")
return set_ringtone()
else
if(current_app)
. = current_app.Topic(href, href_list)
//EXTRA FUNCTIONS===================================
if((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
return // return 1 tells it to refresh the UI in NanoUI

View File

@@ -5,20 +5,39 @@
icon_state = "power_mod"
var/obj/item/device/pda/hostpda = null
var/list/botlist = null // list of bots
var/mob/living/bot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/bot_type //The type of bot it is.
var/bot_filter //Determines which radio filter to use.
var/control_freq = BOT_FREQ
var/on = 0 //Are we currently active??
var/menu_message = ""
New()
/obj/item/radio/integrated/New()
..()
if(istype(loc.loc, /obj/item/device/pda))
hostpda = loc.loc
if(bot_filter)
spawn(5)
add_to_radio(bot_filter)
proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter)
/obj/item/radio/integrated/Destroy()
if(radio_controller)
radio_controller.remove_object(src, control_freq)
hostpda = null
return ..()
/obj/item/radio/integrated/proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter)
//to_world("Post: [freq]: [key]=[value], [key2]=[value2]")
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
if(!frequency) return
if(!frequency)
return
var/datum/signal/signal = new()
signal.source = src
@@ -31,91 +50,120 @@
frequency.post_signal(src, signal, radio_filter = s_filter)
return
proc/generate_menu()
/obj/item/radio/integrated/beepsky
var/list/botlist = null // list of bots
var/mob/living/bot/secbot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/control_freq = BOT_FREQ
// create a new QM cartridge, and register to receive bot control & beacon message
New()
/obj/item/radio/integrated/Topic(href, href_list)
..()
spawn(5)
if(radio_controller)
radio_controller.add_object(src, control_freq, radio_filter = RADIO_SECBOT)
switch(href_list["op"])
if("control")
active = locate(href_list["bot"])
spawn(0)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
// receive radio signals
// can detect bot status signals
// create/populate list as they are recvd
if("scanbots") // find all bots
botlist = null
spawn(0)
post_signal(control_freq, "command", "bot_status", s_filter = bot_filter)
receive_signal(datum/signal/signal)
// var/obj/item/device/pda/P = src.loc
if("botlist")
active = null
/*
to_world("recvd:[P] : [signal.source]")
for(var/d in signal.data)
to_world("- [d] = [signal.data[d]]")
*/
if (signal.data["type"] == "secbot")
if("stop", "go", "home")
spawn(0)
post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
if("summon")
spawn(0)
post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(hostpda), "useraccess", hostpda.GetAccess(), "user", usr, s_filter = bot_filter)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
/obj/item/radio/integrated/receive_signal(datum/signal/signal)
if(bot_type && istype(signal.source, /mob/living/bot) && signal.data["type"] == bot_type)
if(!botlist)
botlist = new()
if(!(signal.source in botlist))
botlist += signal.source
botlist |= signal.source
if(active == signal.source)
var/list/b = signal.data
botstatus = b.Copy()
// if (istype(P)) P.updateSelfDialog()
Topic(href, href_list)
..()
var/obj/item/device/pda/PDA = src.hostpda
switch(href_list["op"])
if("control")
active = locate(href_list["bot"])
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
if("scanbots") // find all bots
botlist = null
post_signal(control_freq, "command", "bot_status", s_filter = RADIO_SECBOT)
if("botlist")
active = null
if("stop", "go")
post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = RADIO_SECBOT)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
if("summon")
post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , s_filter = RADIO_SECBOT)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
/obj/item/radio/integrated/beepsky/Destroy()
/obj/item/radio/integrated/proc/add_to_radio(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots.
if(radio_controller)
radio_controller.remove_object(src, control_freq)
return ..()
radio_controller.add_object(src, control_freq, radio_filter = bot_filter)
/obj/item/radio/integrated/beepsky
bot_filter = RADIO_SECBOT
bot_type = "secbot"
/obj/item/radio/integrated/mule
bot_filter = RADIO_MULEBOT
bot_type = "mulebot"
/obj/item/radio/integrated/mule/proc/GetBeaconList()
var/list/beaconlist = list()
for(var/obj/machinery/navbeacon/N in navbeacons)
if(!N.codes["delivery"])
continue
beaconlist.Add(N.location)
beaconlist[N.location] = N
return beaconlist
/obj/item/radio/integrated/mule/Topic(href, href_list)
..()
switch(href_list["op"])
if("start")
spawn(0)
post_signal(control_freq, "command", "start", "active", active, s_filter = RADIO_MULEBOT)
if("unload")
spawn(0)
post_signal(control_freq, "command", "unload", "active", active, s_filter = RADIO_MULEBOT)
if("setdest")
var/dest
var/list/beaconlist = GetBeaconList()
if(LAZYLEN(beaconlist))
dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.target) as null|anything in beaconlist
else
alert("No destination beacons available.")
if(dest)
spawn(0)
post_signal(control_freq, "command", "target", "active", active, "destination", dest, s_filter = RADIO_MULEBOT)
if("retoff")
spawn(0)
post_signal(control_freq, "command", "autoret", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
if("reton")
spawn(0)
post_signal(control_freq, "command", "autoret", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
if("pickoff")
spawn(0)
post_signal(control_freq, "command", "autopick", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
if("pickon")
spawn(0)
post_signal(control_freq, "command", "autopick", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
spawn(10)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_MULEBOT)
/*
* Radio Cartridge, essentially a signaler.
*/
/obj/item/radio/integrated/signal
var/frequency = 1457
var/code = 30.0
var/last_transmission
var/datum/radio_frequency/radio_connection
/obj/item/radio/integrated/signal/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
radio_connection = null
return ..()
/obj/item/radio/integrated/signal/Initialize()
if(!radio_controller)
return
@@ -131,7 +179,6 @@
radio_connection = radio_controller.add_object(src, frequency)
/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE")
if(last_transmission && world.time < (last_transmission + 5))
return
last_transmission = world.time
@@ -145,9 +192,5 @@
signal.encryption = code
signal.data["message"] = message
spawn(0)
radio_connection.post_signal(src, signal)
/obj/item/radio/integrated/signal/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
return ..()

View File

@@ -43,22 +43,28 @@
/datum/data/pda/utility/scanmode/medical/scan_mob(mob/living/C as mob, mob/living/user as mob)
C.visible_message("<span class=warning>[user] has analyzed [C]'s vitals!</span>")
user.show_message("<span class=notice>Analyzing Results for [C]:</span>")
user.show_message("<span class=notice>\t Overall Status: [C.stat > 1 ? "dead" : "[C.health]% healthy"]</span>", 1)
user.show_message("<span class=notice>\t Damage Specifics: [C.getOxyLoss() > 50 ? "</span><span class=warning>" : ""][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getBruteLoss()]</span>", 1)
user.show_message("<span class=notice>\t Key: Suffocation/Toxin/Burns/Brute</span>", 1)
user.show_message("<span class=notice>\t Body Temperature: [C.bodytemperature-T0C]&deg;C ([C.bodytemperature*1.8-459.67]&deg;F)</span>", 1)
user.show_message("<span class='notice'>Analyzing Results for [C]:</span>")
user.show_message("<span class='notice'> Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]</span>", 1)
user.show_message(text("<span class='notice'> Damage Specifics:</span> <span class='[]'>[]</span>-<span class='[]'>[]</span>-<span class='[]'>[]</span>-<span class='[]'>[]</span>",
(C.getOxyLoss() > 50) ? "warning" : "", C.getOxyLoss(),
(C.getToxLoss() > 50) ? "warning" : "", C.getToxLoss(),
(C.getFireLoss() > 50) ? "warning" : "", C.getFireLoss(),
(C.getBruteLoss() > 50) ? "warning" : "", C.getBruteLoss()
), 1)
user.show_message("<span class='notice'> Key: Suffocation/Toxin/Burns/Brute</span>", 1)
user.show_message("<span class='notice'> Body Temperature: [C.bodytemperature-T0C]&deg;C ([C.bodytemperature*1.8-459.67]&deg;F)</span>", 1)
if(C.tod && (C.stat == DEAD || (C.status_flags & FAKEDEATH)))
user.show_message("<span class=notice>\t Time of Death: [C.tod]</span>")
user.show_message("<span class='notice'> Time of Death: [C.tod]</span>")
if(istype(C, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C
var/list/damaged = H.get_damaged_organs(1,1)
user.show_message("<span class=notice>Localized Damage, Brute/Burn:</span>",1)
user.show_message("<span class='notice'>Localized Damage, Brute/Burn:</span>",1)
if(length(damaged)>0)
for(var/obj/item/organ/external/org in damaged)
user.show_message("<span class=notice>\t [capitalize(org.name)]: [org.brute_dam > 0 ? "<span class=warning>[org.brute_dam]</span>" : "0"]-[org.burn_dam > 0 ? "<span class=warning>[org.burn_dam]</span>" : "0"]", 1)
user.show_message(text("<span class='notice'> []: <span class='[]'>[]</span>-<span class='[]'>[]</span></span>",
capitalize(org.name), (org.brute_dam > 0) ? "warning" : "notice", org.brute_dam, (org.burn_dam > 0) ? "warning" : "notice", org.burn_dam),1)
else
user.show_message("<span class=notice>\t Limbs are OK.",1)
user.show_message("<span class='notice'> Limbs are OK.</span>",1)
/datum/data/pda/utility/scanmode/dna
base_name = "DNA Scanner"
@@ -118,32 +124,10 @@
/datum/data/pda/utility/scanmode/gas
base_name = "Gas Scanner"
icon = "tachometer"
icon = "tachometer-alt"
/datum/data/pda/utility/scanmode/gas/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
// if(istype(A, /obj/item/tank))
// var/obj/item/tank/T = A
// pda.atmosanalyzer_scan(T.air_contents, user, T)
// else if(istype(A, /obj/machinery/portable_atmospherics))
// var/obj/machinery/portable_atmospherics/T = A
// pda.atmosanalyzer_scan(T.air_contents, user, T)
// else if(istype(A, /obj/machinery/atmospherics/pipe))
// var/obj/machinery/atmospherics/pipe/T = A
// pda.atmosanalyzer_scan(T.parent.air, user, T)
// else if(istype(A, /obj/machinery/power/rad_collector))
// var/obj/machinery/power/rad_collector/T = A
// if(T.P)
// pda.atmosanalyzer_scan(T.P.air_contents, user, T)
// else if(istype(A, /obj/item/flamethrower))
// var/obj/item/flamethrower/T = A
// if(T.ptank)
// pda.atmosanalyzer_scan(T.ptank.air_contents, user, T)
// else if(istype(A, /obj/machinery/portable_atmospherics/scrubber/huge))
// var/obj/machinery/portable_atmospherics/scrubber/huge/T = A
// pda.atmosanalyzer_scan(T.air_contents, user, T)
// else if(istype(A, /obj/machinery/atmospherics/unary/tank))
// var/obj/machinery/atmospherics/unary/tank/T = A
// pda.atmosanalyzer_scan(T.air_contents, user, T)
pda.analyze_gases(A, user)
/datum/data/pda/utility/scanmode/notes
base_name = "Note Scanner"

View File

@@ -1,51 +0,0 @@
NanoStatePDAClass.inheritsFrom(NanoStateClass);
var NanoStatePDA = new NanoStatePDAClass();
function NanoStatePDAClass() {
this.key = 'pda';
this.key = this.key.toLowerCase();
this.current_template = "";
NanoStateManager.addState(this);
}
NanoStatePDAClass.prototype.onUpdate = function(data) {
NanoStateClass.prototype.onUpdate.call(this, data);
var state = this;
try {
if(data['data']['app'] != null) {
var template = data['data']['app']['template'];
if(template != null && template != state.current_template) {
var templateMarkup = nanouiTemplateBundle()[template + ".tmpl"];
if (templateMarkup) {
templateMarkup += '<div class="clearBoth"></div>';
try {
NanoTemplate.addTemplate('app', templateMarkup);
NanoTemplate.resetTemplate('app');
$("#uiApp").html(NanoTemplate.parse('app', data));
state.current_template = template;
if(data['config']['status'] == 2) {
$('#uiApp .linkActive').addClass('linkPending');
$('#uiApp .linkActive').oneTime(400, 'linkPending', function () {
$('#uiApp .linkActive').removeClass('linkPending inactive');
});
}
} catch(error) {
reportError('ERROR: An error occurred while loading the PDA App UI: ' + error.message);
return;
}
}
} else {
if (NanoTemplate.templateExists('app')) {
$("#uiApp").html(NanoTemplate.parse('app', data));
}
}
}
} catch(error) {
reportError('ERROR: An error occurred while rendering the PDA App UI: ' + error.message);
return;
}
}

View File

@@ -1,156 +0,0 @@
<!--
Title: PDA UI
Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm
-->
{{if data.useRetro}}
<head>
<style type="text/css">
html {
height: 100%;
overflow: auto;
}
.mainBG {
background: #6F7961;
}
.itemLabelNarrow, .itemLabel, .itemLabelWide, .itemLabelWider, .itemLabelWidest {
color: #000000;
font-weight: bold;
}
.good {
color: #444444;
}
.average {
color: #222222;
}
.bad {
color: #333333;
}
.pdanote {
color: #777777;
}
.link, .linkOn, .linkOff, .selected, .disabled, .yellowButton, .redButton {
color: #000000;
background: #565D4B;
}
.pdalink, .pdalink.disabled {
min-width: 15px;
height: 16px;
text-align: center;
color: #000000;
text-decoration: none;
background: #565D4B;
border: 1px solid #161616;
padding: 0px 4px 4px 4px;
margin: 0 2px 2px 0;
cursor: default;
white-space: nowrap;
}
.pdalink.disabled {
color: #333;
background: #565D4B;
}
#pdaFooter {
background: #6F7961;
}
.pdaFooterButton {
background: none;
color: #000;
}
.pdaFooterButton.disabled {
color: #444 !important;
}
div.clock {
color: black;
}
h1, h2, h3, h4, h5, h6 {
color: #000000;
}
.fixedLeft, .fixedLeftWide, .fixedLeftWider, .fixedLeftWidest, .floatRight {
color: #000000;
}
.floatRight {
min-width: 15px;
height: 16px;
text-align: center;
background: #565D4B;
border: 1px solid #161616;
padding: 0px 4px 4px 4px;
margin: 0 2px 2px 0;
}
.uiIcon16 {
background-image: none;
float: left;
width: auto;
height: auto;
margin: 0 0 0 0;
}
#uiTitleText, #pdaFooter {
color: #000000;
}
.pmon {
background: black;
}
.itemLabel {
color: black;
}
.statusDisplayRecords .good, .statusDisplay .good {
color: #020;
}
.statusDisplayRecords .average, .statusDisplay .average {
color: #110;
}
</style>
</head>
{{/if}}
{{if data.owner}}
<div class="item">
<div class="floatLeft">
{{if data.idInserted}}
{{:helper.link(data.idLink, 'eject', {'choice' : "Authenticate"}, null, 'pdalink fixedLeftWide')}}
{{/if}}
{{if data.cartridge_name}}
{{:helper.link(data.cartridge_name, 'eject', {'choice' : "Eject"}, null, 'pdalink fixedLeftWidest')}}
{{/if}}
{{:helper.link('Toggle R.E.T.R.O. mode', 'gear', {'choice': "Retro"}, null, 'pdalink fixedLeftWide')}}
</div>
<div class="clock">
{{:data.stationTime}}
</div>
</div>
{{if data.app}}
<h2><i class="fa fa-{{:data.app.icon}}"></i>&nbsp;{{:data.app.name}}</h2>
<div id="uiApp"></div>
<div class="pdaFooterButton disabled">&nbsp;</div>
{{/if}}
<div id="pdaFooter">
{{:helper.link("", 'back', {'choice' : "Back"}, data.app.has_back ? null : 'disabled', 'link pdaFooterButton')}}
{{:helper.link("", 'home', {'choice' : "Home"}, data.app.is_home ? 'disabled' : null, 'link pdaFooterButton')}}
</div>
{{else}}
<div class="wholeScreen">
<br><br><br><br><br><br><br>No Owner information found, please swipe ID
</div>
{{/if}}

View File

@@ -1,60 +0,0 @@
<!--
Title: PDA Atmospheric Scanner UI
Used In File(s): \code\game\objects\items\devices\PDA\cart_apps.dm
-->
<div class="statusDisplay" style="height: 250px; overflow: auto;">
<div class="item">
{{if data.aircontents.reading == 1}}
<div class="itemLabel">
<span class="pdanote">Pressure:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1} kPa</span>', data.aircontents.pressure < 80 || data.aircontents.pressure > 120 ? 'bad' : data.aircontents.pressure < 95 || data.aircontents.pressure > 110 ? 'average' : 'good', helper.smoothRound(data.aircontents.pressure, 1))}}
</div>
<div class="itemLabel">
<span class="pdanote">Temperature:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1} &deg;C</span>', data.aircontents.temp < 5 || data.aircontents.temp > 35 ? 'bad' : data.aircontents.temp < 15 || data.aircontents.temp > 25 ? 'average' : 'good' , helper.smoothRound(data.aircontents.temp, 1))}}
</div>
<br>
<div class="itemLabel">
<span class="pdanote">Oxygen:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1}%</span>', data.aircontents.oxygen < 17 ? 'bad' : data.aircontents.oxygen < 19 ? 'average' : 'good', helper.smoothRound(data.aircontents.oxygen, 1))}}
</div>
<div class="itemLabel">
<span class="pdanote">Nitrogen:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1}%</span>', data.aircontents.nitrogen > 82 ? 'bad' : data.aircontents.nitrogen > 80 ? 'average' : 'good', helper.smoothRound(data.aircontents.nitrogen, 1))}}
</div>
<div class="itemLabel">
<span class="pdanote">Carbon Dioxide:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1}%</span>', data.aircontents.carbon_dioxide > 5 ? 'bad' : 'good', helper.smoothRound(data.aircontents.carbon_dioxide, 1))}}
</div>
<div class="itemLabel">
<span class="pdanote">Plasma:</span>
</div>
<div class = "itemContent">
{{:helper.string('<span class="{0}">{1}%</span>', data.aircontents.plasma > 0 ? 'bad' : 'good', helper.smoothRound(data.aircontents.plasma, 1))}}
</div>
{{if data.aircontents.other > 0}}
<div class="itemLabel">
<span class="pdanote">Unknown:</span>
</div>
<div class = "itemContent">
<span class="bad">{{:helper.smoothRound(data.aircontents.other, 1)}}%</span>
</div>
{{/if}}
{{else}}
<div class="itemContent" style="width: 100%;">
<span class="average"><b>Unable to get air reading</b></span>
</div>
{{/if}}
</div>
</div>

View File

@@ -1,66 +0,0 @@
<div class="statusDisplay">
<div class="item">
<span class="good">Current Location:</span>
{{if data.janitor.user_loc.x == 0}}
<span class="bad">Unknown</span>
{{else}}
<span class="average"> {{:data.janitor.user_loc.x}} / {{:data.janitor.user_loc.y}}</span>
{{/if}}
</div>
<div class="item">
{{if data.janitor.mops}}
<span class="good">Mop Locations:</span>
<ul>
{{for data.janitor.mops}}
<li>
<span class="average">({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}</span>
</li>
{{/for}}
</ul>
{{else}}
<span class="bad">Unable to locate Mops</span>
{{/if}}
</div>
<div class="item">
{{if data.janitor.buckets}}
<span class="good">Mop Bucket Locations:</span>
<ul>
{{for data.janitor.buckets}}
<li>
<span class="average">({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Capacity: {{:value.volume}}/{{:value.max_volume}}</span>
</li>
{{/for}}
</ul>
{{else}}
<span class="bad">Unable to locate Mop Buckets</span>
{{/if}}
</div>
<div class="item">
{{if data.janitor.cleanbots}}
<span class="good">Cleanbot Locations:</span>
<ul>
{{for data.janitor.cleanbots}}
<li>
<span class="average">({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}</span>
</li>
{{/for}}
</ul>
{{else}}
<span class="bad">Unable to locate Cleanbots</span>
{{/if}}
</div>
<div class="item">
{{if data.janitor.carts}}
<span class="good">Janitorial Cart Locations:</span>
<ul>
{{for data.janitor.carts}}
<li>
<span class="average">({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Water Level: {{:value.volume}}/{{:value.max_volume}}</span>
</li>
{{/for}}
</ul>
{{else}}
<span class="bad">Unable to locate Janitorial Carts</span>
{{/if}}
</div>
</div>

View File

@@ -1,76 +0,0 @@
<!--
Title: PDA Home UI
Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
-->
<script>
/* flash notify icons */
var notifications = [];
var noteTimer;
function mm_flashNotify() {
notifications.forEach(function(n) {
if(n.item.hasClass("fa-"+n.icon)) {
n.item.removeClass("fa-"+n.icon).addClass("fa-"+n.notifyIcon);
} else {
n.item.removeClass("fa-"+n.notifyIcon).addClass("fa-"+n.icon);
}
});
}
if(!noteTimer) {
noteTimer = window.setInterval(mm_flashNotify, 1000);
}
</script>
<div class="item">
<div class="itemLabelNarrow">
Owner:
</div>
<div class="itemContent">
<span class="average">{{:data.owner}}, {{:data.ownjob}}</span>
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">
ID:
</div>
<div class="itemContent">
{{:helper.link('Update PDA Info', 'refresh', {'choice' : "UpdateInfo"}, data.idInserted ? null : 'disabled', 'pdalink fixedLeftWide')}}
</div>
</div>
<div class="item">
<H2>Functions</H2>
</div>
{{for data.categories : cat : i}}
<div class="item mainmenu">
<div class="itemLabelNarrow">
<b>{{:cat}}</b>:
</div>
<div class="itemContent">
{{for data.apps[cat]}}
{{if value.ref in data.notifying}}
<div data-notify="{{:value.ref}}">
{{:helper.link(value.name, value.notify_icon, {'choice' : "StartProgram", 'program' : value.ref}, null, 'pdalink fixedLeftWide')}}
</div>
<script>
notifications.push({item: $("[data-notify='{{:value.ref}}'] i"), icon: '{{:value.icon}}', notifyIcon: '{{:value.notify_icon}}'});
</script>
{{else}}
{{:helper.link(value.name, value.icon, {'choice' : "StartProgram", 'program' : value.ref}, null, 'pdalink fixedLeftWide')}}
{{/if}}
{{/for}}
</div>
</div>
{{/for}}
{{if data.pai}}
<div class="item">
<div class = "itemLabelNarrow">
<b>PAI Utilities</b>:
</div>
<div class = "itemContent">
{{:helper.link('Configuration', 'gear', {'choice' : "pai", 'option' : "1"}, null, 'pdalink fixedLeft')}}
{{:helper.link('Eject pAI', 'eject', {'choice' : "pai", 'option' : "2"}, null, 'pdalink fixedLeft')}}
</div>
</div>
{{/if}}

View File

@@ -1,96 +0,0 @@
<!--
Title: PDA Crew Manifest UI
Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
-->
<div class="item">
<center><table class="pmon"><tbody>
{{if data.manifest.heads}}
<tr><th colspan="3" class="command">Command</th></tr>
{{for data.manifest["heads"]}}
{{if value.rank == "Captain"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.sec}}
<tr><th colspan="3" class="sec">Security</th></tr>
{{for data.manifest["sec"]}}
{{if value.rank == "Head of Security"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.eng}}
<tr><th colspan="3" class="eng">Engineering</th></tr>
{{for data.manifest["eng"]}}
{{if value.rank == "Chief Engineer"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.med}}
<tr><th colspan="3" class="med">Medical</th></tr>
{{for data.manifest["med"]}}
{{if value.rank == "Chief Medical Officer"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.sci}}
<tr><th colspan="3" class="sci">Science</th></tr>
{{for data.manifest["sci"]}}
{{if value.rank == "Research Director"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.ser}}
<tr><th colspan="3" class="ser">Service</th></tr>
{{for data.manifest["ser"]}}
{{if value.rank == "Head of Personnel"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.sup}}
<tr><th colspan="3" class="sup">Supply</th></tr>
{{for data.manifest["sup"]}}
{{if value.rank == "Head of Personnel"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else value.rank == "Quartermaster"}}
<tr><td><span class="qm-job">{{:value.name}}</span></td><td><span class="qm-job">{{:value.rank}}</span></td><td><span class="qm-job">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.civ}}
<tr><th colspan="3" class="civ">Civilian</th></tr>
{{for data.manifest["civ"]}}
{{if value.rank == "Head of Personnel"}}
<tr><td><span class="good">{{:value.name}}</span></td><td><span class="good">{{:value.rank}}</span></td><td><span class="good">{{:value.active}}</span></td></tr>
{{else}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/if}}
{{/for}}
{{/if}}
{{if data.manifest.misc}}
<tr><th colspan="3" class="misc">Misc</th></tr>
{{for data.manifest["misc"]}}
<tr><td><span class="average">{{:value.name}}</span></td><td><span class="average">{{:value.rank}}</span></td><td><span class="average">{{:value.active}}</span></td></tr>
{{/for}}
{{/if}}
</tbody></table></center>
</div>

View File

@@ -1,54 +0,0 @@
{{if !data.records}}
<div class="item">
<div class="itemLabel">Select a record:</div>
</div>
{{for data.recordsList}}
<div class="item">
{{:helper.link(value.Name, 'user', {'choice' : "Records", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}}
</div>
{{empty}}
<div class="item">
<span class="average">No records found.</span>
</div>
{{/for}}
{{else}}
<div class="statusDisplayRecords">
<div class="item">
<div class="itemContent" style="width: 100%;">
{{if data.records.general}}
<span class="good">Name: </span> <span class="average">{{:data.records.general.name}} </span><br>
<span class="good">Sex: </span> <span class="average">{{:data.records.general.sex}} </span><br>
<span class="good">Species: </span> <span class="average">{{:data.records.general.species}} </span><br>
<span class="good">Age: </span> <span class="average">{{:data.records.general.age}} </span><br>
<span class="good">Rank: </span> <span class="average">{{:data.records.general.rank}} </span><br>
<span class="good">Fingerprint: </span> <span class="average">{{:data.records.general.fingerprint}} </span><br>
<span class="good">Physical Status: </span> <span class="average">{{:data.records.general.p_stat}} </span><br>
<span class="good">Mental Status: </span> <span class="average">{{:data.records.general.m_stat}} </span><br><br>
{{else}}
<span class="bad">
General Record Lost!<br><br>
</span>
{{/if}}
{{if data.records.medical}}
<div class="item">
<div class="itemLabel">Medical Data:</div>
</div>
<span class="good">Blood Type: </span> <span class="average">{{:data.records.medical.b_type}} </span><br><br>
<span class="good">Minor Disabilities: </span> <span class="average">{{:data.records.medical.mi_dis}} </span><br>
<span class="good">Details: </span> <span class="average">{{:data.records.medical.mi_dis_d}} </span><br><br>
<span class="good">Major Disabilities: </span> <span class="average">{{:data.records.medical.ma_dis}} </span><br>
<span class="good">Details: </span> <span class="average">{{:data.records.medical.ma_dis_d}} </span><br><br>
<span class="good">Allergies: </span> <span class="average">{{:data.records.medical.alg}} </span><br>
<span class="good">Details: </span> <span class="average">{{:data.records.medical.alg_d}} </span><br><br>
<span class="good">Current Disease: </span> <span class="average">{{:data.records.medical.cdi}} </span><br>
<span class="good">Details: </span> <span class="average">{{:data.records.medical.alg_d}} </span><br><br>
<span class="good">Important Notes: </span> <span class="average">{{:data.records.medical.notes}} </span>
{{else}}
<span class="bad">
Medical Record Lost!
</span>
{{/if}}
</div>
</div>
</div>
{{/if}}

View File

@@ -1,90 +0,0 @@
<!--
Title: PDA Messenger UI
Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
-->
{{if data.active_conversation}}
<div class="item">
<div class="itemLabel">
<b>Messenger Functions</b>:
</div>
<div class ="itemContent">
{{:helper.link('Delete Conversation', 'trash', {'choice' : "Clear", 'option' : "Convo"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link(data.auto_scroll ? 'Autoscroll: On' : 'Autoscroll: Off', 'level-down', {'choice' : "Autoscroll"}, null, 'pdalink fixedLeftWide')}}
</div>
</div>
<br>
<br>
<H3>Conversation with:&nbsp;<span class="average">{{:data.convo_name}}&nbsp;({{:data.convo_job}})</span></H3>
<div class="statusDisplay" style="overflow: auto;">
<div class="item">
<div class="itemContent" style="width: 100%;">
{{for data.messages}}
{{if data.active_conversation == value.target}}
{{if value.sent==0}}
<span class="average"><B>Them</B>: {{:value.message}}</span><br>
{{else}}
<span class="good"><B>You</B>: {{:value.message}}</span><br>
{{/if}}
{{/if}}
{{/for}}
</div>
</div>
</div>
{{:helper.link('Reply', 'comment', {'choice' : "Message", 'target': data.active_conversation}, null, 'pdalink fixedLeftWidest')}}
<script>
$(function() {
{{if data.auto_scroll && data.latest_post != data.messages.length}}
var body = document.body;
$('html,body').animate({scrollTop: body.scrollHeight}, "fast");
{{/if}}
});
</script>
{{else}}
<div class="item">
<div class="itemLabelNarrow">
<b>Messenger Functions</b>:
</div>
<div class ="itemContent">
{{:helper.link(data.silent==1 ? 'Ringer: Off' : 'Ringer: On', data.silent==1 ? 'volume-off' : 'volume-up', {'choice' : "Toggle Ringer"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link(data.toff==1 ? 'Messenger: Off' : 'Messenger: On',data.toff==1 ? 'close':'check', {'choice' : "Toggle Messenger"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Set Ringtone', 'bell-o', {'choice' : "Ringtone"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Delete all Conversations', 'trash', {'choice' : "Clear", 'option' : "All"}, null, 'pdalink fixedLeftWider')}}
</div>
</div>
{{if data.toff == 0}}
<br>
{{if data.charges}}
<div class="item">
<b>{{:data.charges}} charges left.</b>
<br><br>
</div>
{{/if}}
{{if !data.convopdas.length && !data.pdas.length}}
<b>No other PDAS located</b>
{{else}}
<H3>Current Conversations</H3>
{{for data.convopdas}}
<div class="item">
{{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Select Conversation", 'convo' : value.Reference } , null, 'pdalink')}}
{{if data.charges}}
{{for data.plugins : plugin : i}}
{{:helper.link(plugin.name, plugin.icon, {'choice' : "Messenger Plugin", 'plugin' : plugin.ref, 'target' : value.Reference}, null, 'pdalink fixedLeft')}}
{{/for}}
{{/if}}
</div>
{{/for}}
<H3>Other PDAs</H3>
{{for data.pdas}}
<div class="item">
{{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Message", 'target' : value.Reference}, null, 'pdalink')}}
{{if data.charges}}
{{for data.plugins : plugin : i}}
{{:helper.link(plugin.name, plugin.icon, {'choice' : "Messenger Plugin", 'plugin' : plugin.ref, 'target' : value.Reference}, null, 'pdalink fixedLeft')}}
{{/for}}
{{/if}}
</div>
{{/for}}
{{/if}}
{{/if}}
{{/if}}

View File

@@ -1,91 +0,0 @@
<div class="item">
<div class="itemLabel">
<table>
<tr>
<td>
Connection Status:
</td>
{{if data.connected}}
<td>
<span class="good">Connected</span>
</td>
<td>
{{:helper.link('Disconnect', 'sign-out', {'choice': 'Disconnect'})}}
</td>
{{else}}
<td>
<span class="bad">No Connection</span>
</td>
<td>
{{:helper.link('Connect', 'sign-in', {'choice': 'Reconnect'})}}
</td>
{{/if}}
</tr>
</table>
</div>
</div>
<hr>
<div class="itemLabel">My Collection:</div>
{{if data.no_collection}}
<div class="statusDisplayRecords">
<div class="item">
<span class="average">Your collection is empty! Go capture some Nano-Mobs!</span>
</div>
</div>
<br>
Wild mobs captured: {{:data.wild_captures}}
{{else}}
<div class="statusDisplayRecords">
<div class="item">
<div class="itemContent" style="width: 100%;">
{{if data.entry}}
{{if data.entry.nickname}}
<span class="good">Name: </span> <span class="average"> {{:data.entry.nickname}}</span><br>
{{/if}}
<span class="good">Species: </span> <span class="average">{{:data.entry.real_name}} </span><br>
<span class="good">Level: </span> <span class="average">{{:data.entry.level}} </span><br>
<span class="good">Primary Type: </span> <span class="average">{{:data.entry.type1}} </span><br>
{{if data.entry.type2}}
<span class="good">Secondary Type: </span> <span class="average">{{:data.entry.type2}} </span><br>
{{/if}}
{{if data.entry.sprite}}
<img src='{{:data.entry.sprite}}'>
{{else}}
<span class="bad">Mob Image Missing!</span>
{{/if}}
{{else}}
<span class="bad">
Mob Data Missing!<br><br>
</span>
{{/if}}
</div>
</div>
</div>
<br>
Wild mobs captured: {{:data.wild_captures}}
<div class="item">
<table>
<tr>
<td>
{{:helper.link('Previous Mob', 'arrow-left', {'choice': 'Prev'})}}
</td>
<td>
{{:helper.link('Transfer Mob', 'exchange', {'choice': 'Transfer'})}}
</td>
<td>
{{:helper.link('Rename Mob', 'pencil', {'choice': 'Rename'})}}
</td>
<td>
{{:helper.link('Release Mob', 'tree', {'choice': 'Release'})}}
</td>
<td>
{{:helper.link('Next Mob', 'arrow-right', {'choice': 'Next'})}}
</td>
</tr>
</table>
{{if data.entry.is_hacked}}
<br>
{{:helper.link('Set Trap', 'bolt', {'choice': 'Set_Trap'})}}
{{/if}}
</div>
{{/if}}

View File

@@ -1,118 +0,0 @@
{{if !data.mulebot.active}}
{{if data.mulebot.count == 0}}
<H1><span class="bad">No bots found.</span></H1>
{{else}}
<div class="item">
Select a MULE:
</div>
<br>
{{for data.mulebot.bots}}
<div class="item">
{{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, 'pdalink fixedLeftWidest')}} (Location: {{:value.Location}})
</div>
{{/for}}
{{/if}}
<br>
{{:helper.link('Scan for Bots','rss', {'radiomenu' : "1", 'op' : "scanbots"}, null, 'pdalink fixedLeftWidest')}}
{{else}}
<H1><span class="average">{{:data.mulebot.active}}</span></H1>
{{if data.mulebot.botstatus.mode == -1}}
<H1><span class="bad">Waiting for response...</span></H1>
{{else}}
<H1><span class="good">Status:</span></H1>
<div class="item">
<div class="itemLabel">
<span class="good">Location:</span>
</div>
<div class="itemContent">
<span class="average">{{:data.mulebot.botstatus.loca}}</span>
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Mode:</span>
</div>
<div class="itemContent">
<span class="average">
{{if data.mulebot.botstatus.mode == 0}}
Ready
{{else data.mulebot.botstatus.mode == 1}}
Loading/Unloading
{{else data.mulebot.botstatus.mode == 2}}
Navigating to Delivery Location
{{else data.mulebot.botstatus.mode == 3}}
Navigating to Home
{{else data.mulebot.botstatus.mode == 4}}
Waiting for Clear Path
{{else data.mulebot.botstatus.mode == 5 || data.mulebot.botstatus.mode == 6}}
Calculating navigation Path
{{else data.mulebot.botstatus.mode == 7}}
Unable to locate destination
{{/if}}
</span>
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Current Load:</span>
</div>
<div class="itemContent">
<span class="average">
{{:helper.link(data.mulebot.botstatus.load == null ? 'None (Unload)' : data.mulebot.botstatus.load + ' (Unload)', 'archive', {'radiomenu' : "1", 'op' : "unload"},data.mulebot.botstatus.load == null ? 'disabled' : null, 'pdalink fixedLeftWidest')}}
</span>
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Power:</span>
</div>
<div class="itemContent">
<span class="average">
{{:data.mulebot.botstatus.powr}}%
</span>
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Destination:</span>
</div>
<div class="itemContent">
{{:helper.link(data.mulebot.botstatus.dest == null || data.mulebot.botstatus.dest == "" ? 'None (Set)' : data.mulebot.botstatus.dest + ' (Set)', 'gear', {'radiomenu' : "1", 'op' : "setdest"}, null, 'pdalink fixedLeftWidest')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Home:</span>
</div>
<div class="itemContent">
{{if data.mulebot.botstatus.home == null}} None {{else}} {{:data.mulebot.botstatus.home}} {{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Auto Return:</span>
</div>
<div class="itemContent">
{{:helper.link(data.mulebot.botstatus.retn == 1 ? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : (data.mulebot.botstatus.retn==1 ? "retoff" : "reton")}, null, 'pdalink fixedLeftWidest')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Auto Pickup:</span>
</div>
<div class="itemContent">
{{:helper.link(data.mulebot.botstatus.pick==1? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : (data.mulebot.botstatus.pick==1 ? "pickoff" : "pickon")}, null, 'pdalink fixedLeftWidest')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Functions:</span>
</div>
<div class="itemContent">
{{:helper.link('Stop', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, 'pdalink fixedLeft')}}
{{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "start"}, null, 'pdalink fixedLeft')}}
{{:helper.link('Return Home', 'gear', {'radiomenu' : "1", 'op' : "home"}, null, 'pdalink fixedLeft')}}
</div>
</div>
{{/if}}
{{/if}}

View File

@@ -1,21 +0,0 @@
<!--
Title: PDA Notekeeper UI
Used In File(s): \code\game\objects\items\devices\PDA\apps.dm
-->
<div class="item">
<div class="itemLabel">
<b>Notes</b>:
</div>
</div>
<div class="statusDisplayRecords">
<div class="item">
<div class="itemContent" style="width: 100%;">
<span class="pdanote">{{:data.note}}</span>
</div>
</div>
</div>
<div class="item">
<div class="itemLabel">
{{:helper.link('Edit Notes', 'pencil-square-o', {'choice': "Edit"}, null, 'pdalink')}}
</div>
</div>

View File

@@ -1,49 +0,0 @@
{{if !data.records.powerconnected}}
<div class="item">
<div class="itemLabel">Select a power monitor:</div>
</div>
{{for data.records.powermonitors}}
<div class="item">
{{:helper.link(value.Name, 'exclamation-circle', {'choice' : "Power Select", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}}
</div>
{{/for}}
{{else}}
<div class="item">
<div class="itemLabelNarrow">
<b>Total Power:</b>
</div>
<div class="itemContent">
<span class="average">{{:data.records.poweravail}} W</span>
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">
<b>Total Load:</b>
</div>
<div class="itemContent">
<span class="average">{{:data.records.powerload}} W</span>
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">
<b>Total Demand:</b>
</div>
<div class="itemContent">
<span class="average">{{:data.records.powerdemand}} W</span>
</div>
</div>
<div class="item">
<table class="curvedEdges" style="text-align: center;"><tbody>
<tr><th>Area</th><th>Equip.</th><th>Lighting</th><th>Environ.</th><th>Cell</th><th>Load</th></tr>
{{for data.records.apcs}}
<tr><td style="text-align: left; font-weight: bold;">{{:value.Name}}</td>
{{:helper.string('<td width="55px" bgcolor="{0}">{1}</td>', value.Equipment == "On" || value.Equipment == "AOn" ? '#4f7529' : '#8f1414', value.Equipment)}}
{{:helper.string('<td width="55px" bgcolor="{0}">{1}</td>', value.Lights == "On" || value.Lights == "AOn" ? '#4f7529' : '#8f1414', value.Lights)}}
{{:helper.string('<td width="55px" bgcolor="{0}">{1}</td>', value.Environment == "On" || value.Environment == "AOn" ? '#4f7529' : '#8f1414', value.Environment)}}
{{:helper.string('<td style="text-align: center;" width="65px" bgcolor="{0}">{1}{2}</td>', value.CellStatus == "F" ? '#4f7529' : value.CellStatus == "C" ? '#cd6500' : '#8f1414', value.CellStatus == "M" ? 'No Cell' : value.CellPct + '%', value.CellStatus == "M" ? '' : ' (' + value.CellStatus + ')')}}
<td width="55px">{{:value.Load}}W</td>
</tr>
{{/for}}
</tbody></table>
</div>
{{/if}}

View File

@@ -1,59 +0,0 @@
{{if !data.beepsky.active}}
{{if data.beepsky.count == 0}}
<H1><span class="bad">No bots found.</span></H1>
{{else}}
<div class="item">
Select a bot:
</div>
<br>
{{for data.beepsky.bots}}
<div class="item">
{{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, 'pdalink fixedLeftWidest')}} (Location: {{:value.Location}})
</div>
{{/for}}
{{/if}}
<br>
{{:helper.link('Scan for Bots','rss', {'radiomenu' : "1", 'op' : "scanbots"}, null, 'pdalink fixedLeftWidest')}}
{{else}}
<H1><span class="average">{{:data.beepsky.active}}</span></H1>
{{if data.beepsky.botstatus.mode == -1}}
<H1><span class="bad">Waiting for response...</span></H1>
{{else}}
<H1><span class="good">Status:</span></H1>
<div class="item">
<div class="itemLabel">
<span class="good">Location:</span>
</div>
<div class="itemContent">
<span class="average">{{:data.beepsky.botstatus.loca}}</span>
</div>
</div>
<div class="item">
<div class="itemLabel">
<span class="good">Mode:</span>
</div>
<div class="itemContent">
<span class="average">
{{if data.beepsky.botstatus.mode ==0}}
Ready
{{else data.beepsky.botstatus.mode == 1}}
Apprehending target
{{else data.beepsky.botstatus.mode ==2 || data.beepsky.botstatus.mode == 3}}
Arresting target
{{else data.beepsky.botstatus.mode ==4}}
Starting patrol
{{else data.beepsky.botstatus.mode ==5}}
On Patrol
{{else data.beepsky.botstatus.mode ==6}}
Responding to summons
{{/if}}
</span>
</div>
</div>
<div class="item">
{{:helper.link('Stop Patrol', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Start Patrol', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Summon Bot', 'gear', {'radiomenu' : "1", 'op' : "summon"}, null, 'pdalink fixedLeftWide')}}
</div>
{{/if}}
{{/if}}

View File

@@ -1,50 +0,0 @@
{{if !data.records}}
<div class="item">
<div class="itemLabel">Select a record:</div>
</div>
{{for data.recordsList}}
<div class="item">
{{:helper.link(value.Name, 'user', {'choice' : "Records", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}}
</div>
{{empty}}
<div class="item">
<span class="average">No records found.</span>
</div>
{{/for}}
{{else}}
<div class="statusDisplayRecords">
<div class="item">
<div class="itemContent" style="width: 100%;">
{{if data.records.general}}
<span class="good">Name: </span> <span class="average"> {{:data.records.general.name}}</span><br>
<span class="good">Sex: </span> <span class="average">{{:data.records.general.sex}} </span><br>
<span class="good">Species: </span> <span class="average">{{:data.records.general.species}} </span><br>
<span class="good">Age: </span> <span class="average">{{:data.records.general.age}} </span><br>
<span class="good">Rank: </span> <span class="average">{{:data.records.general.rank}} </span><br>
<span class="good">Fingerprint: </span> <span class="average">{{:data.records.general.fingerprint}} </span><br>
<span class="good">Physical Status: </span> <span class="average">{{:data.records.general.p_stat}} </span><br>
<span class="good">Mental Status: </span> <span class="average">{{:data.records.general.m_stat}} </span><br><br>
{{else}}
<span class="bad">
General Record Lost!<br><br>
</span>
{{/if}}
{{if data.records.security}}
<div class="item">
<div class="itemLabel">Security Data:</div>
</div>
<span class="good">Criminal Status: </span><span class="average">{{:data.records.security.criminal}} </span><br><br>
<span class="good">Minor Crimes: </span><span class="average">{{:data.records.security.mi_crim}} </span><br>
<span class="good">Details: </span><span class="average">{{:data.records.security.mi_crim_d}} </span><br><br>
<span class="good">Major Crimes: </span><span class="average">{{:data.records.security.ma_crim}} </span><br>
<span class="good">Details: </span><span class="average">{{:data.records.security.ma_crim_d}} </span><br><br>
<span class="good">Important Notes: </span><span class="average">{{:data.records.security.notes}} </span>
{{else}}
<span class="bad">
Security Record Lost!<br><br>
</span>
{{/if}}
</div>
</div>
</div>
{{/if}}

View File

@@ -1,38 +0,0 @@
<!--
Title: PDA Remote Signaller UI
Used In File(s): \code\game\objects\items\devices\PDA\cart_apps.dm
-->
<div class="item">
<div class="itemLabel">
<b>Frequency</b>:
</div>
<div class="itemContent">
{{:data.signal_freq}}
<br>
&nbsp;
{{:helper.link('-1', null, {'choice' : "Signal Frequency", 'sfreq' : "-10"}, null, null)}}&nbsp;
{{:helper.link('-.2', null, {'choice' : "Signal Frequency", 'sfreq' : "-2"}, null, null)}}&nbsp;
{{:helper.link('+.2', null, {'choice' : "Signal Frequency", 'sfreq' : "2"}, null, null)}}&nbsp;
{{:helper.link('+1', null, {'choice' : "Signal Frequency", 'sfreq' : "10"}, null, null)}}
</div>
</div>
<br>
<br>
<div class="item">
<div class="itemLabel">
<b>Code</b>:
</div>
<div class="itemContent">
<span class="average">
{{:data.signal_code}}<br>
</span>
{{:helper.link('-5', null, {'choice' : "Signal Code", 'scode' : "-5"}, null, null)}}
{{:helper.link('-1', null, {'choice' : "Signal Code", 'scode' : "-1"}, null, null)}}
{{:helper.link('+1', null, {'choice' : "Signal Code", 'scode' : "1"}, null, null)}}
{{:helper.link('+5', null, {'choice' : "Signal Code", 'scode' : "5"}, null, null)}}
</div>
</div>
<div class="item">
{{:helper.link('Send Signal', 'exclamation-circle', {'choice' : "Send Signal"}, null, null)}}
</div>

View File

@@ -1,44 +0,0 @@
<!--
Title: PDA Status Display UI
Used In File(s): \code\game\objects\items\devices\PDA\cart_apps.dm
-->
<div class="item">
<div class="itemLabel">
<b>Code</b>:
</div>
<div class="itemContent">
{{:helper.link('Clear', 'trash', {'choice' : "Status", 'statdisp' : "blank"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Shuttle ETA', 'gear', {'cartmenu' : "1", 'choice' : "Status", 'statdisp' : "shuttle"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Message', 'gear', {'choice' : "Status", 'statdisp' : "message"}, null, 'pdalink fixedLeftWide')}}
</div>
</div>
<br>
<div class="item">
<div class="itemLabel">
<b>Message line 1</b>
</div>
<div class="itemContent">
{{:helper.link(data.records.message1 + ' (set)', 'pencil', {'choice' : "Status", 'statdisp' : "setmsg1"}, null, 'pdalink fixedLeftWide')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
<b>Message line 2</b>
</div>
<div class="itemContent">
{{:helper.link(data.records.message2 + ' (set)', 'pencil', {'choice' : "Status", 'statdisp' : "setmsg2"}, null, 'pdalink fixedLeftWide')}}
</div>
</div>
<br>
<div class="item">
<div class="itemLabel">
<b> ALERT!</b>:
</div>
<div class="itemContent">
{{:helper.link('None', 'bell', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "default"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Red Alert', 'bell', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "redalert"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Lockdown', 'exclamation-circle', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "lockdown"}, null, 'pdalink fixedLeftWide')}}
{{:helper.link('Biohazard', 'exclamation-circle', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "biohazard"}, null, 'pdalink fixedLeftWide')}}
</div>
</div>

View File

@@ -1,39 +0,0 @@
<div class="item">
<div class="itemLabelNarrow">
Location:
</div>
<div class="itemContent">
<span class="average">
{{if data.supply.shuttle_moving}}
Moving to {{:data.supply.shuttle_loc}}
{{else}}
Shuttle at {{:data.supply.shuttle_loc}}
{{/if}}
<br>
{{:data.supply.shuttle_time}}
</span>
</div>
</div>
<div class="statusDisplayRecords">
<div class="item">
<div class="itemContent" style="width: 100%;">
<span class="good"><B>Current Approved Orders</B></span><br>
{{if data.supply.approved_count == 0}}
<span class="average pdanote">No current approved orders </span><br><br>
{{else}}
{{for data.supply.approved}}
<span class="average">#{{:value.Number}} - {{:value.Name}} approved by {{:value.OrderedBy}}<br>{{if value.Comment != ""}} {{:value.Comment}} <br>{{/if}}<br></span>
{{/for}}
{{/if}}
<br><br>
<span class="good"><B>Current Requested Orders</B></span><br>
{{if data.supply.requests_count == 0}}
<span class="average pdanote">No current requested orders</span><br><br>
{{else}}
{{for data.supply.requests}}
<span class="average">#{{:value.Number}} - {{:value.Name}} requested by {{:value.OrderedBy}}<br>{{if value.Comment != ""}} {{:value.Comment}} <br>{{/if}}<br></span>
{{/for}}
{{/if}}
</div>
</div>
</div>

View File

@@ -120,10 +120,11 @@ export const decodeHtmlEntities = str => {
if (!str) {
return str;
}
const translate_re = /&(nbsp|amp|quot|lt|gt|apos|trade);/g;
const translate_re = /&(nbsp|amp|deg|quot|lt|gt|apos|trade);/g;
const translate = {
nbsp: ' ',
amp: '&',
deg: '°',
quot: '"',
lt: '<',
gt: '>',

View File

@@ -24,6 +24,7 @@ import './styles/themes/hackerman.scss';
import './styles/themes/malfunction.scss';
import './styles/themes/ntos.scss';
import './styles/themes/paper.scss';
import './styles/themes/pda-retro.scss';
import './styles/themes/retro.scss';
import './styles/themes/syndicate.scss';

View File

@@ -4,14 +4,153 @@ import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
/* This is all basically stolen from routes.js. */
import { routingError } from "../routes";
const requirePdaInterface = require.context('./pda', false, /\.js$/);
const getPdaApp = name => {
let appModule;
try {
appModule = requirePdaInterface(`./${name}.js`);
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
return routingError('notFound', name);
}
throw err;
}
const Component = appModule[name];
if (!Component) {
return routingError('missingExport', name);
}
return Component;
};
export const Pda = (props, context) => {
const { act, data } = useBackend(context);
const {
app,
owner,
useRetro,
} = data;
if (!owner) {
return (
<Window width={580} height={670}>
<Window>
<Window.Content>
<Section stretchContents>
Warning: No ID information found! Please swipe ID!
</Section>
</Window.Content>
</Window>
);
}
let App = getPdaApp(app.template);
return (
<Window width={580} height={670} theme={useRetro ? "pda-retro" : null} resizable>
<Window.Content scrollable>
PDA!
<PDAHeader />
<Section
title={
<Box>
<Icon name={app.icon} mr={1} />
{app.name}
</Box>
}
p={1}>
<App />
</Section>
<Box mb={8} />
<PDAFooter />
</Window.Content>
</Window>
);
};
const PDAHeader = (props, context) => {
const { act, data } = useBackend(context);
const {
idInserted,
idLink,
cartridge_name,
stationTime,
} = data;
return (
<Box mb={1}>
<Flex align="center" justify="space-between" pl={1} pr={1}>
{!!idInserted && (
<Flex.Item>
<Button
color="transparent"
icon="eject"
onClick={() => act("authenticate")}
content={idLink} />
</Flex.Item>
)}
{!!cartridge_name && (
<Flex.Item>
<Button
color="transparent"
icon="eject"
onClick={() => act("eject")}
content={cartridge_name} />
</Flex.Item>
)}
<Flex.Item>
<Button
icon="cog"
color="transparent"
content="Toggle R.E.T.R.O. Mode"
onClick={() => act("Retro")} />
</Flex.Item>
<Flex.Item>
<Box bold>
{stationTime}
</Box>
</Flex.Item>
</Flex>
</Box>
);
};
const PDAFooter = (props, context) => {
const { act, data } = useBackend(context);
const {
app,
} = data;
return (
<Box position="fixed" bottom="0%" left="0%" right="0%">
<Flex>
<Flex.Item basis="33%">
<Button
fluid
color="transparent"
iconColor={app.has_back ? "white" : "disabled"}
textAlign="center"
icon="undo"
mb={0}
fontSize={1.7}
onClick={() => act("Back")} />
</Flex.Item>
<Flex.Item basis="33%">
<Button
fluid
color="transparent"
iconColor={app.is_home ? "disabled" : "white"}
textAlign="center"
icon="home"
mb={0}
fontSize={1.7}
onClick={() => act("Home")} />
</Flex.Item>
</Flex>
</Box>
);
};

View File

@@ -0,0 +1,44 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
const getItemColor = (value, min2, min1, max1, max2) => {
if (value < min2) {
return "bad";
} else if (value < min1) {
return "average";
} else if (value > max1) {
return "average";
} else if (value > max2) {
return "bad";
}
return "good";
};
export const pda_atmos_scan = (props, context) => {
const { act, data } = useBackend(context);
const {
aircontents,
} = data;
return (
<Box>
<LabeledList>
{filter(
i => (i.val !== "0") || i.entry === "Pressure" || i.entry === "Temperature"
)(aircontents)
.map(item => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(item.val, item.bad_low, item.poor_low, item.poor_high, item.bad_high)}>
{item.val}{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
</LabeledList>
</Box>
);
};

View File

@@ -0,0 +1,89 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_janitor = (props, context) => {
const { act, data } = useBackend(context);
const {
janitor,
} = data;
return (
<Box>
<LabeledList>
<LabeledList.Item label="Current Location">
{janitor.user_loc.x === 0 && (
<Box color="bad">Unknown</Box>
) || (
<Box>
{janitor.user_loc.x} / {janitor.user_loc.y}
</Box>
)}
</LabeledList.Item>
</LabeledList>
<Section level={2} title="Mop Locations">
{janitor.mops && (
<ul>
{janitor.mops.map((mop, i) => (
<li key={i}>
{mop.x} / {mop.y} - {mop.dir} - Status: {mop.status}
</li>
))}
</ul>
) || (
<Box color="bad">
No mops detected nearby.
</Box>
)}
</Section>
<Section level={2} title="Mop Bucket Locations">
{janitor.buckets && (
<ul>
{janitor.buckets.map((bucket, i) => (
<li key={i}>
{bucket.x} / {bucket.y} - {bucket.dir} - Capacity: {bucket.volume}/{bucket.max_volume}
</li>
))}
</ul>
) || (
<Box color="bad">
No buckets detected nearby.
</Box>
)}
</Section>
<Section level={2} title="Cleanbot Locations">
{janitor.cleanbots && (
<ul>
{janitor.cleanbots.map((cleanbot, i) => (
<li key={i}>
{cleanbot.x} / {cleanbot.y} - {cleanbot.dir} - Status: {cleanbot.status}
</li>
))}
</ul>
) || (
<Box color="bad">
No cleanbots detected nearby.
</Box>
)}
</Section>
<Section level={2} title="Janitorial Cart Locations">
{janitor.carts && (
<ul>
{janitor.carts.map((cart, i) => (
<li key={i}>
{cart.x} / {cart.y} - {cart.dir} - Water Level: {cart.volume}/{cart.max_volume}
</li>
))}
</ul>
) || (
<Box color="bad">
No janitorial carts detected nearby.
</Box>
)}
</Section>
</Box>
);
};

View File

@@ -1,14 +1,67 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { useBackend } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_main_menu = (props, context) => {
const { act, data } = useBackend(context);
const {
owner,
ownjob,
idInserted,
categories,
pai,
notifying,
} = data;
return (
<Section>
Main Menu
<Fragment>
<Box>
<LabeledList>
<LabeledList.Item label="Owner" color="average">
{owner}, {ownjob}
</LabeledList.Item>
<LabeledList.Item label="ID">
<Button
icon="sync"
content="Update PDA Info"
disabled={!idInserted}
onClick={() => act("UpdateInfo")} />
</LabeledList.Item>
</LabeledList>
</Box>
<Section level={2} title="Functions">
<LabeledList>
{categories.map(name => (
<LabeledList.Item label={name} key={name}>
{data.apps[name].map(app => (
<Button
key={app.ref}
icon={(app.ref in notifying) ? app.notify_icon : app.icon}
iconSpin={(app.ref in notifying)}
color={(app.ref in notifying) ? "red" : "transparent"}
content={app.name}
onClick={() => act("StartProgram", { program: app.ref })} />
))}
</LabeledList.Item>
))}
</LabeledList>
</Section>
{!!pai && (
<Section level={2} title="pAI">
<Button
fluid
icon="gear"
content="Configuration"
onClick={() => act("pai", { option: 1 })} />
<Button
fluid
icon="eject"
content="Eject pAI"
onClick={() => act("pai", { option: 2 })} />
</Section>
)}
</Fragment>
);
};

View File

@@ -0,0 +1,15 @@
import { filter } from 'common/collections';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
import { IdentificationComputerCrewManifest } from '../IdentificationComputer';
export const pda_manifest = (props, context) => {
const { act, data } = useBackend(context);
return (
<Box>
<IdentificationComputerCrewManifest />
</Box>
);
};

View File

@@ -0,0 +1,113 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_medical = (props, context) => {
const { act, data } = useBackend(context);
const {
recordsList,
records,
} = data;
if (records) {
const {
general,
medical,
} = records;
return (
<Box>
<Section level={2} title="General Data">
{general && (
<LabeledList>
<LabeledList.Item label="Name">
{general.name}
</LabeledList.Item>
<LabeledList.Item label="Sex">
{general.sex}
</LabeledList.Item>
<LabeledList.Item label="Species">
{general.species}
</LabeledList.Item>
<LabeledList.Item label="Age">
{general.age}
</LabeledList.Item>
<LabeledList.Item label="Rank">
{general.rank}
</LabeledList.Item>
<LabeledList.Item label="Fingerprint">
{general.fingerprint}
</LabeledList.Item>
<LabeledList.Item label="Physical Status">
{general.p_stat}
</LabeledList.Item>
<LabeledList.Item label="Mental Status">
{general.m_stat}
</LabeledList.Item>
</LabeledList>
) || (
<Box color="bad">
General record lost!
</Box>
)}
</Section>
<Section level={2} title="Medical Data">
{medical && (
<LabeledList>
<LabeledList.Item label="Blood Type">
{medical.b_type}
</LabeledList.Item>
<LabeledList.Item label="Minor Disabilities">
{medical.mi_dis}
</LabeledList.Item>
<LabeledList.Item label="Details">
{medical.mi_dis_d}
</LabeledList.Item>
<LabeledList.Item label="Major Disabilities">
{medical.ma_dis}
</LabeledList.Item>
<LabeledList.Item label="Details">
{medical.ma_dis_d}
</LabeledList.Item>
<LabeledList.Item label="Allergies">
{medical.alg}
</LabeledList.Item>
<LabeledList.Item label="Details">
{medical.alg_d}
</LabeledList.Item>
<LabeledList.Item label="Current Disease">
{medical.cdi}
</LabeledList.Item>
<LabeledList.Item label="Details">
{medical.cdi_d}
</LabeledList.Item>
<LabeledList.Item label="Important Notes">
{medical.notes}
</LabeledList.Item>
</LabeledList>
) || (
<Box color="bad">
Medical record lost!
</Box>
)}
</Section>
</Box>
);
}
return (
<Section level={2} title="Select a record">
{recordsList.map(record => (
<Button
key={record.ref}
icon="eye"
fluid
content={record.Name}
onClick={() => act("Records", { target: record.ref })} />
))}
</Section>
);
};

View File

@@ -0,0 +1,261 @@
import { filter } from 'common/collections';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_messenger = (props, context) => {
const { act, data } = useBackend(context);
const {
auto_scroll,
convo_name,
convo_job,
messages,
active_conversation,
} = data;
if (active_conversation) {
return <ActiveConversation />;
}
return <MessengerList />;
};
const ActiveConversation = (props, context) => {
const { act, data } = useBackend(context);
const {
auto_scroll,
convo_name,
convo_job,
messages,
active_conversation,
useRetro,
} = data;
const [clipboardMode, setClipboardMode] = useLocalState(context, 'clipboardMode', false);
let body = (
<Section
level={2}
title={"Conversation with " + convo_name + " (" + convo_job + ")"}
buttons={
<Button
icon="eye"
selected={clipboardMode}
tooltip="Enter Clipboard Mode"
tooltipPosition="bottom-left"
onClick={() => setClipboardMode(!clipboardMode)} />
}
height="450px"
stretchContents>
<Section style={{
"height": "97%",
"overflow-y": "auto",
}}>
{filter(im => im.target === active_conversation)(messages).map((im, i) => (
<Box
textAlign={im.sent ? "right" : "left"}
position="relative"
mb={1}
key={i}>
<Icon
fontSize={2.5}
color={im.sent ? "#4d9121" : "#cd7a0d"}
position="absolute"
left={im.sent ? null : "0px"}
right={im.sent ? "0px" : null}
bottom="-4px"
style={{
"z-index": "0",
"transform": im.sent ? "scale(-1, 1)" : null,
}}
name="comment" />
<Box
inline
backgroundColor={im.sent ? "#4d9121" : "#cd7a0d"}
p={1}
maxWidth="100%"
position="relative"
textAlign={im.sent ? "left" : "right"}
style={{
"z-index": "1",
"border-radius": "10px",
"word-break": "break-all",
}}>
{im.sent ? "You:" : "Them:"} {im.message}
</Box>
</Box>
))}
</Section>
<Button
icon="comment"
onClick={() => act("Message", { "target": active_conversation })}
content="Reply" />
</Section>
);
if (clipboardMode) {
body = (
<Section
level={2}
title={"Conversation with " + convo_name + " (" + convo_job + ")"}
buttons={
<Button
icon="eye"
selected={clipboardMode}
tooltip="Exit Clipboard Mode"
tooltipPosition="bottom-left"
onClick={() => setClipboardMode(!clipboardMode)} />
}
height="450px"
stretchContents>
<Section style={{
"height": "97%",
"overflow-y": "auto",
}}>
{filter(im => im.target === active_conversation)(messages).map((im, i) => (
<Box
key={i}
color={im.sent ? "#4d9121" : "#cd7a0d"}
style={{
"word-break": "break-all",
}}>
{im.sent ? "You:" : "Them:"} <Box inline color={useRetro ? "black" : null}>{im.message}</Box>
</Box>
))}
</Section>
<Button
icon="comment"
onClick={() => act("Message", { "target": active_conversation })}
content="Reply" />
</Section>
);
}
return (
<Box>
<LabeledList>
<LabeledList.Item label="Messenger Functions">
<Button
icon="trash"
color="bad"
onClick={() => act("Clear", { option: "Convo" })}>
Delete Conversations
</Button>
</LabeledList.Item>
</LabeledList>
{body}
</Box>
);
};
const MessengerList = (props, context) => {
const { act, data } = useBackend(context);
const {
auto_scroll,
convopdas,
pdas,
charges,
plugins,
silent,
toff,
} = data;
return (
<Box>
<LabeledList>
<LabeledList.Item label="Messenger Functions">
<Button
selected={!silent}
icon={silent ? "volume-mute" : "volume-up"}
onClick={() => act("Toggle Ringer")}>
Ringer: {silent ? "Off" : "On"}
</Button>
<Button
selected={!toff}
icon="power-off"
onClick={() => act("Toggle Messenger")}>
Messenger: {toff ? "Off" : "On"}
</Button>
<Button
icon="bell"
onClick={() => act("Ringtone")}>
Set Ringtone
</Button>
<Button
icon="trash"
color="bad"
onClick={() => act("Clear", { option: "All" })}>
Delete All Conversations
</Button>
</LabeledList.Item>
</LabeledList>
{!toff && (
<Box>
{!!charges && (
<Box>
{charges} charges left.
</Box>
)}
{!convopdas.length && !pdas.length && (
<Box>
No other PDAs located.
</Box>
) || (
<Box>
<PDAList title="Current Conversations" pdas={convopdas} msgAct="Select Conversation" />
<PDAList title="Other PDAs" pdas={pdas} msgAct="Message" />
</Box>
)}
</Box>
)}
</Box>
);
};
const PDAList = (props, context) => {
const { act, data } = useBackend(context);
const {
pdas,
title,
msgAct,
} = props;
const {
charges,
plugins,
} = data;
if (!pdas || !pdas.length) {
return (
<Section level={2} title={title}>
No PDAs found.
</Section>
);
}
return (
<Section level={2} title={title}>
{pdas.map(pda => (
<Box key={pda.Reference}>
<Button
icon="arrow-circle-down"
content={pda.Name}
onClick={() => act(msgAct, { target: pda.Reference })} />
{!!charges && plugins.map(plugin => (
<Button
key={plugin.ref}
icon={plugin.icon}
content={plugin.name}
onClick={() => act("Messenger Plugin", {
plugin: plugin.ref,
target: pda.Reference,
})} />
))}
</Box>
))}
</Section>
);
};

View File

@@ -0,0 +1,26 @@
/* eslint react/no-danger: "off" */
import { useBackend } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_notekeeper = (props, context) => {
const { act, data } = useBackend(context);
const {
note,
} = data;
return (
<Box>
<Section>
{ /* As usual with dangerouslySetInnerHTML,
this notekeeper was designed to use HTML injection.
Fix when markdown is easier. */ }
<div dangerouslySetInnerHTML={{ __html: note }} />
</Section>
<Button
icon="pen"
onClick={() => act("Edit")}
content="Edit Notes" />
</Box>
);
};

View File

@@ -0,0 +1,8 @@
import { useBackend } from "../../backend";
import { PowerMonitorContent } from '../PowerMonitor';
export const pda_power = (props, context) => {
const { act, data } = useBackend(context);
return <PowerMonitorContent />;
};

View File

@@ -0,0 +1,101 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_security = (props, context) => {
const { act, data } = useBackend(context);
const {
recordsList,
records,
} = data;
if (records) {
const {
general,
security,
} = records;
return (
<Box>
<Section level={2} title="General Data">
{general && (
<LabeledList>
<LabeledList.Item label="Name">
{general.name}
</LabeledList.Item>
<LabeledList.Item label="Sex">
{general.sex}
</LabeledList.Item>
<LabeledList.Item label="Species">
{general.species}
</LabeledList.Item>
<LabeledList.Item label="Age">
{general.age}
</LabeledList.Item>
<LabeledList.Item label="Rank">
{general.rank}
</LabeledList.Item>
<LabeledList.Item label="Fingerprint">
{general.fingerprint}
</LabeledList.Item>
<LabeledList.Item label="Physical Status">
{general.p_stat}
</LabeledList.Item>
<LabeledList.Item label="Mental Status">
{general.m_stat}
</LabeledList.Item>
</LabeledList>
) || (
<Box color="bad">
General record lost!
</Box>
)}
</Section>
<Section level={2} title="Security Data">
{security && (
<LabeledList>
<LabeledList.Item label="Criminal Status">
{security.criminal}
</LabeledList.Item>
<LabeledList.Item label="Minor Crimes">
{security.mi_crim}
</LabeledList.Item>
<LabeledList.Item label="Details">
{security.mi_crim_d}
</LabeledList.Item>
<LabeledList.Item label="Major Crimes">
{security.ma_crim}
</LabeledList.Item>
<LabeledList.Item label="Details">
{security.ma_crim_d}
</LabeledList.Item>
<LabeledList.Item label="Important Notes:">
{security.notes}
</LabeledList.Item>
</LabeledList>
) || (
<Box color="bad">
Security record lost!
</Box>
)}
</Section>
</Box>
);
}
return (
<Section level={2} title="Select a record">
{recordsList.map(record => (
<Button
key={record.ref}
icon="eye"
fluid
content={record.Name}
onClick={() => act("Records", { target: record.ref })} />
))}
</Section>
);
};

View File

@@ -0,0 +1,54 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_status_display = (props, context) => {
const { act, data } = useBackend(context);
const {
records,
} = data;
return (
<Box>
<LabeledList>
<LabeledList.Item label="Code">
<Button
color="transparent"
icon="trash"
content="Clear"
onClick={() => act("Status", { statdisp: "blank" })} />
<Button
color="transparent"
icon="cog"
content="Evac ETA"
onClick={() => act("Status", { statdisp: "shuttle" })} />
<Button
color="transparent"
icon="cog"
content="Message"
onClick={() => act("Status", { statdisp: "message" })} />
<Button
color="transparent"
icon="exclamation-triangle"
content="ALERT"
onClick={() => act("Status", { statdisp: "alert" })} />
</LabeledList.Item>
<LabeledList.Item label="Message line 1">
<Button
content={records.message1 + " (set)"}
icon="pen"
onClick={() => act("Status", { statdisp: "setmsg1" })} />
</LabeledList.Item>
<LabeledList.Item label="Message line 2">
<Button
content={records.message2 + " (set)"}
icon="pen"
onClick={() => act("Status", { statdisp: "setmsg2" })} />
</LabeledList.Item>
</LabeledList>
</Box>
);
};

View File

@@ -0,0 +1,53 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
export const pda_supply = (props, context) => {
const { act, data } = useBackend(context);
const {
supply,
} = data;
return (
<Box>
<LabeledList>
<LabeledList.Item label="Location">
{supply.shuttle_moving
? "Moving to station " + supply.shuttle_eta
: "Shuttle at " + supply.shuttle_loc}
</LabeledList.Item>
</LabeledList>
<Section>
<Box color="good" bold>Current Approved Orders</Box>
{supply.approved.length && supply.approved.map(crate => (
<Box
key={crate.Number}
color="average">
#{crate.Number} - {crate.Name} approved by {crate.OrderedBy}<br />
{crate.Comment}
</Box>
)) || (
<Box>
None!
</Box>
)}
<Box color="good" bold>Current Requested Orders</Box>
{supply.requests.length && supply.requests.map(crate => (
<Box
key={crate.Number}
color="average">
#{crate.Number} - {crate.Name} requested by {crate.OrderedBy}<br />
{crate.Comment}
</Box>
)) || (
<Box>
None!
</Box>
)}
</Section>
</Box>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,7 @@ import { Window } from './layouts';
const requireInterface = require.context('./interfaces', false, /\.js$/);
const routingError = (type, name) => () => {
export const routingError = (type, name) => () => {
return (
<Window resizable>
<Window.Content scrollable>

View File

@@ -0,0 +1,61 @@
@use 'sass:color';
@use 'sass:meta';
@use '../colors.scss' with (
$primary: #000000,
$label: #000000,
$average: #000000,
);
@use '../base.scss' with (
$color-bg: #6f7961,
$color-bg-grad-spread: 0%,
$color-fg: #000,
$border-radius: 0,
);
// A fat warning to anyone who wants to use this: this only half works.
// It was made almost purely for the pda ui, and requires a good amount of manual hacks to get it working as intended.
.theme-pda-retro {
// Atomic classes
@include meta.load-css('../atomic/color.scss');
// Components
@include meta.load-css('../components/Button.scss', $with: (
'color-default': #E8E4C9,
'color-disabled': #505050,
'color-selected': #9d0808,
'color-caution': #be6209,
'color-danger': #9a9d00,
));
@include meta.load-css('../components/ProgressBar.scss', $with: (
'color-background': rgba(0, 0, 0, 0.5),
));
@include meta.load-css('../components/Section.scss', $with: (
'color-background': rgba(0, 0, 0, 0.1),
));
// Layouts
@include meta.load-css('../layouts/Layout.scss');
@include meta.load-css('../layouts/Window.scss');
@include meta.load-css('../layouts/TitleBar.scss', $with: (
'color-background': #363636,
));
.Button {
color: #161613;
background-color: #565d4b;
border: 1px solid #000000;
}
.Layout__content {
background-image: none;
}
.LabeledList__label {
font-weight: bold;
}
.Tooltip::after {
color: #ffffff;
}
}

View File

@@ -9,6 +9,7 @@
@use '../base.scss' with (
$color-bg: #E8E4C9,
$color-bg-grad-spread: 0%,
$color-fg: #000,
$border-radius: 0,
);

View File

@@ -3066,6 +3066,7 @@
#include "code\modules\paperwork\photography.dm"
#include "code\modules\paperwork\silicon_photography.dm"
#include "code\modules\paperwork\stamps.dm"
#include "code\modules\pda\ai.dm"
#include "code\modules\pda\app.dm"
#include "code\modules\pda\cart.dm"
#include "code\modules\pda\cart_apps.dm"
@@ -3075,6 +3076,7 @@
#include "code\modules\pda\messenger.dm"
#include "code\modules\pda\messenger_plugins.dm"
#include "code\modules\pda\pda.dm"
#include "code\modules\pda\pda_subtypes.dm"
#include "code\modules\pda\pda_tgui.dm"
#include "code\modules\pda\pda_vr.dm"
#include "code\modules\pda\radio.dm"