"
- if(equipment.len)
- for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
- output += "[selected==MT?"
":""][MT.get_equip_info()][selected==MT?"":""]
"
+ output += "
Cargo Compartment Contents:"
+ if(src.cargo.len)
+ for(var/obj/O in src.cargo)
+ output += "
Unload : [O]
"
else
- output += "None"
+ output += "Nothing"
output += "
"
return output
-*/
\ No newline at end of file
+
+/obj/mecha/working/range_action(atom/target as obj|mob|turf)
+ return
\ No newline at end of file
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm
index 9983eff1ac..0ee04f0230 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/effects/aliens.dm
@@ -109,6 +109,17 @@
O.show_message("\red [usr] destroys the [name]!", 1)
health = 0
else
+
+ // Aliens can get straight through these.
+ if(istype(usr,/mob/living/carbon))
+ var/mob/living/carbon/M = usr
+ if(locate(/datum/organ/internal/xenos/hivenode) in M.internal_organs)
+ for(var/mob/O in oviewers(src))
+ O.show_message("\red [usr] strokes the [name] and it melts away!", 1)
+ health = 0
+ healthcheck()
+ return
+
usr << "\blue You claw at the [name]."
for(var/mob/O in oviewers(src))
O.show_message("\red [usr] claws at the [name]!", 1)
diff --git a/code/game/objects/effects/barsign.dm b/code/game/objects/effects/barsign.dm
deleted file mode 100644
index fd66f8028d..0000000000
--- a/code/game/objects/effects/barsign.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/obj/effect/sign/double/barsign
- icon = 'icons/obj/barsigns.dmi'
- icon_state = "empty"
- anchored = 1
-
- New()
- var/list/valid_states = list("pinkflamingo", "magmasea", "limbo", "rustyaxe", "armokbar", "brokendrum", "meadbay", "thedamnwall", "thecavern", "cindikate", "theorchard", "thesaucyclown", "theclownshead", "whiskeyimplant", "carpecarp", "robustroadhouse", "greytide", "theredshirt")
- src.icon_state = "[pick(valid_states)]"
diff --git a/code/game/objects/effects/decals/posters/tgposters.dm b/code/game/objects/effects/decals/posters/tgposters.dm
index 3dff589c3a..5fb94396d5 100644
--- a/code/game/objects/effects/decals/posters/tgposters.dm
+++ b/code/game/objects/effects/decals/posters/tgposters.dm
@@ -20,7 +20,7 @@
icon_state="poster4"
/datum/poster/tg_5
- name = "Syndicate Recruitment Poster"
+ name = "Mercenary Recruitment Poster"
desc = "See the galaxy! Shatter corrupt megacorporations! Join today!"
icon_state="poster5"
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 0da251e1ee..ee82396788 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -11,14 +11,13 @@ would spawn and follow the beaker, even if it is carried or thrown.
icon = 'icons/effects/effects.dmi'
mouse_opacity = 0
unacidable = 1//So effect are not targeted by alien acid.
- flags = TABLEPASS
+ pass_flags = PASSTABLE | PASSGRILLE
/obj/effect/effect/water
name = "water"
icon = 'icons/effects/effects.dmi'
icon_state = "extinguish"
var/life = 15.0
- flags = TABLEPASS
mouse_opacity = 0
/obj/effect/proc/delete()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 80f1fcb8e5..5ef7686e42 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -260,8 +260,11 @@
if(ishuman(M))
//START HUMAN
var/mob/living/carbon/human/H = M
+ var/list/mob_equip = list()
+ if(H.species.hud && H.species.hud.equip_slots)
+ mob_equip = H.species.hud.equip_slots
- if(H.species && !(slot in H.species.hud.equip_slots))
+ if(H.species && !(slot in mob_equip))
return 0
switch(slot)
@@ -306,7 +309,7 @@
if(slot_belt)
if(H.belt)
return 0
- if(!H.w_uniform)
+ if(!H.w_uniform && (slot_w_uniform in mob_equip))
if(!disable_warning)
H << "\red You need a jumpsuit before you can attach this [name]."
return 0
@@ -354,7 +357,7 @@
if(slot_wear_id)
if(H.wear_id)
return 0
- if(!H.w_uniform)
+ if(!H.w_uniform && (slot_w_uniform in mob_equip))
if(!disable_warning)
H << "\red You need a jumpsuit before you can attach this [name]."
return 0
@@ -364,7 +367,7 @@
if(slot_l_store)
if(H.l_store)
return 0
- if(!H.w_uniform)
+ if(!H.w_uniform && (slot_w_uniform in mob_equip))
if(!disable_warning)
H << "\red You need a jumpsuit before you can attach this [name]."
return 0
@@ -375,7 +378,7 @@
if(slot_r_store)
if(H.r_store)
return 0
- if(!H.w_uniform)
+ if(!H.w_uniform && (slot_w_uniform in mob_equip))
if(!disable_warning)
H << "\red You need a jumpsuit before you can attach this [name]."
return 0
@@ -387,7 +390,7 @@
if(slot_s_store)
if(H.s_store)
return 0
- if(!H.wear_suit)
+ if(!H.wear_suit && (slot_wear_suit in mob_equip))
if(!disable_warning)
H << "\red You need a suit before you can attach this [name]."
return 0
@@ -681,7 +684,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
usr.client.pixel_x = -viewoffset
usr.client.pixel_y = 0
- usr.visible_message("[usr] peers through the [devicename].")
+ usr.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].")
/*
if(istype(usr,/mob/living/carbon/human/))
@@ -701,6 +704,6 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
usr.client.pixel_y = 0
if(!cannotzoom)
- usr.visible_message("[usr] lowers the [devicename].")
+ usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].")
return
\ No newline at end of file
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index ea1254d4ad..574bfd1905 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -35,6 +35,8 @@
icon_state = "bodybag_closed"
icon_closed = "bodybag_closed"
icon_opened = "bodybag_open"
+ open_sound = 'sound/items/zip.ogg'
+ close_sound = 'sound/items/zip.ogg'
var/item_path = /obj/item/bodybag
density = 0
storage_capacity = (mob_size * 2) - 1
@@ -106,8 +108,6 @@
desc = "A non-reusable plastic bag designed to prevent additional damage to an occupant at the cost of genetic damage."
icon = 'icons/obj/cryobag.dmi'
item_path = /obj/item/bodybag/cryobag
- open_sound = 'sound/items/zip.ogg'
- close_sound = 'sound/items/zip.ogg'
store_misc = 0
store_items = 0
var/used = 0
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index d3a907a40a..20c5425bc8 100755
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -21,17 +21,20 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/lastmode = 0
var/ui_tick = 0
+ var/nanoUI[0]
//Secondary variables
var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner.
var/fon = 0 //Is the flashlight function on?
var/f_lum = 2 //Luminosity for the flashlight function
- var/silent = 0 //To beep or not to beep, that is the question
+ var/message_silent = 0 //To beep or not to beep, that is the question
+ var/news_silent = 0 //To beep or not to beep, that is the question
var/toff = 0 //If 1, messenger disabled
var/tnote[0] //Current Texts
var/last_text //No text spamming
var/last_honk //Also no honk spamming that's bad too
- var/ttone = "beep" //The ringtone!
+ var/ttone = "beep" //The PDA ringtone!
+ var/newstone = "beep, beep" //The news ringtone!
var/lock_code = "" // Lockcode to unlock uplink
var/honkamt = 0 //How many honks left when infected with honk.exe
var/mimeamt = 0 //How many silence left when infected with mime.exe
@@ -42,7 +45,13 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/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/newmessage = 0 //To remove hackish overlay check
+ var/new_message = 0 //To remove hackish overlay check
+ var/new_news = 0
+
+ var/active_feed // The selected feed
+ var/list/warrant // The warrant as we last knew it
+ var/list/feeds = list() // The list of feeds as we last knew them
+ var/list/feed_info = list() // The data and contents of each feed as we last knew them
var/list/cartmodes = list(40, 42, 43, 433, 44, 441, 45, 451, 46, 48, 47, 49) // If you add more cartridge modes add them to this list as well.
var/list/no_auto_update = list(1, 40, 43, 44, 441, 45, 451) // These modes we turn off autoupdate
@@ -101,8 +110,10 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/mime
default_cartridge = /obj/item/weapon/cartridge/mime
icon_state = "pda-mime"
- silent = 1
+ message_silent = 1
+ news_silent = 1
ttone = "silence"
+ newstone = "silence"
/obj/item/device/pda/heads
default_cartridge = /obj/item/weapon/cartridge/head
@@ -172,7 +183,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
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!"
- silent = 1 //Quiet in the library!
+ message_silent = 1 //Quiet in the library!
+ news_silent = 1
/obj/item/device/pda/clear
icon_state = "pda-transp"
@@ -202,6 +214,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/ai
icon_state = "NONE"
ttone = "data"
+ newstone = "news"
detonate = 0
@@ -225,7 +238,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
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)
+ create_message(usr, selected, 0)
/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver()
@@ -246,8 +259,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(usr.stat == 2)
usr << "You can't do that because you are dead!"
return
- silent=!silent
- usr << "
PDA ringer toggled [(silent ? "Off" : "On")]!"
+ message_silent=!message_silent
+ usr << "
PDA ringer toggled [(message_silent ? "Off" : "On")]!"
/obj/item/device/pda/ai/verb/cmd_show_message_log()
@@ -260,9 +273,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/HTML = "
AI PDA Message Log"
for(var/index in tnote)
if(index["sent"])
- HTML += addtext("
→ To ", index["owner"],":", index["message"], "
")
+ HTML += addtext("
→ To ", index["owner"],":", index["message"], "
")
else
- HTML += addtext("
← From ", index["owner"],":", index["message"], "
")
+ HTML += addtext("
← From ", index["owner"],":", index["message"], "
")
HTML +=""
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
@@ -347,7 +360,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
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?
@@ -356,7 +368,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
data["fon"] = fon // Flashlight on?
data["pai"] = (isnull(pai) ? 0 : 1) // pAI inserted?
data["note"] = note // current pda notes
- data["silent"] = silent // does the pda make noise when it receives a message?
+ data["message_silent"] = message_silent // does the pda make noise when it receives a message?
+ data["news_silent"] = news_silent // does the pda make noise when it receives news?
data["toff"] = toff // is the messenger function turned off?
data["active_conversation"] = active_conversation // Which conversation are we following right now?
@@ -403,7 +416,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
data["cartridge"] = cartdata
data["stationTime"] = worldtime2text()
- data["newMessage"] = newmessage
+ data["new_Message"] = new_message
+ data["new_News"] = new_news
if(mode==2)
var/convopdas[0]
@@ -464,7 +478,45 @@ var/global/list/obj/item/device/pda/PDAs = list()
)
if(isnull(data["aircontents"]))
data["aircontents"] = list("reading" = 0)
+ if(mode==6)
+ if(news_network.network_channels.len != feeds.len)
+ var/datum/reception/reception = get_reception(src)
+ if(reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER)
+ feeds.Cut()
+ for(var/datum/feed_channel/channel in news_network.network_channels)
+ feeds[++feeds.len] = list("name" = channel.channel_name, "censored" = channel.censored)
+ data["feedChannels"] = feeds
+ if(mode==61)
+ var/list/feed = feed_info[active_feed]
+ if(!feed)
+ feed = list()
+ feed["updated"] = -1
+ feed_info[active_feed] = feed
+ var/datum/feed_channel/FC
+ for(FC in news_network.network_channels)
+ if(FC.channel_name == active_feed["name"])
+ break
+ if(FC.updated > feed["updated"])
+ var/datum/reception/reception = get_reception(src)
+ if(reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER)
+ feed["channel"] = FC.channel_name
+ feed["author"] = FC.author
+ feed["updated"] = FC.updated
+ feed["censored"] = FC.censored
+
+ var/list/messages = list()
+ if(!FC.censored)
+ var/index = 0
+ for(var/datum/feed_message/FM in FC.messages)
+ index++
+ if(FM.img)
+ usr << browse_rsc(FM.img, "pda_news_tmp_photo_[feed["channel"]]_[index].png")
+ messages[++messages.len] = list("author" = FM.author, "body" = FM.body, "message_type" = FM.message_type, "has_image" = (FM.img != null), "index" = index)
+ feed["messages"] = messages
+ data["feed"] = feed
+
+ nanoUI = data
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -623,7 +675,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
if("Toggle Messenger")
toff = !toff
if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
- silent = !silent
+ message_silent = !message_silent
+ if("Toggle News")
+ news_silent = !news_silent
if("Clear")//Clears messages
if(href_list["option"] == "All")
tnote.Cut()
@@ -653,10 +707,19 @@ var/global/list/obj/item/device/pda/PDAs = list()
else
ui.close()
return 0
+ if("Newstone")
+ var/t = input(U, "Please enter new news tone", name, newstone) as text
+ if (in_range(src, U) && loc == U)
+ if (t)
+ t = copytext(sanitize(t), 1, 20)
+ newstone = t
+ else
+ ui.close()
+ return 0
if("Message")
var/obj/item/device/pda/P = locate(href_list["target"])
- src.create_message(U, P)
+ src.create_message(U, P, !("notap" in href_list))
if(mode == 2)
if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp.
active_conversation = href_list["target"]
@@ -668,8 +731,14 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(P == n)
active_conversation=P
mode=21
+ if("Select Feed")
+ var/n = href_list["name"]
+ for(var/f in feeds)
+ if(f["name"] == n)
+ active_feed = f
+ mode=61
if("Send Honk")//Honk virus
- if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch.
+ if(cartridge && cartridge.access_clown)//Cartridge checks are kind of unnecessary since everything is done through switch.
var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess.
if(!isnull(P))
if (!P.toff && cartridge.charges > 0)
@@ -682,14 +751,16 @@ var/global/list/obj/item/device/pda/PDAs = list()
ui.close()
return 0
if("Send Silence")//Silent virus
- if(istype(cartridge, /obj/item/weapon/cartridge/mime))
+ if(cartridge && cartridge.access_mime)
var/obj/item/device/pda/P = locate(href_list["target"])
if(!isnull(P))
if (!P.toff && cartridge.charges > 0)
cartridge.charges--
U.show_message("\blue Virus sent!", 1)
- P.silent = 1
+ P.message_silent = 1
+ P.news_silent = 1
P.ttone = "silence"
+ P.newstone = "silence"
else
U << "PDA not found."
else
@@ -709,34 +780,15 @@ var/global/list/obj/item/device/pda/PDAs = list()
M.close()
if("Detonate")//Detonate PDA... maybe
- // check if telecomms I/O route 1459 is stable
- //var/telecomms_intact = telecomms_process(P.owner, owner, t)
- var/obj/machinery/message_server/useMS = null
- if(message_servers)
- for (var/obj/machinery/message_server/MS in message_servers)
- //PDAs are now dependant on the Message Server.
- if(MS.active)
- useMS = MS
- break
-
- var/datum/signal/signal = src.telecomms_process()
-
- var/useTC = 0
- if(signal)
- if(signal.data["done"])
- useTC = 1
- var/turf/pos = get_turf(src)
- if(pos.z in signal.data["level"])
- useTC = 2
-
- if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
- if(!(useMS && useTC))
+ if(cartridge && cartridge.access_detonate_pda)
+ var/obj/item/device/pda/P = locate(href_list["target"])
+ var/datum/reception/reception = get_reception(src, P, "") // get_reception calls sleep further down the line
+ if(!(reception.message_server && reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER))
U.show_message("\red An error flashes on your [src]: Connection unavailable", 1)
return
- if(useTC != 2) // Does our recepient have a broadcaster on their level?
+ if(reception.telecomms_reception & TELECOMMS_RECEPTION_RECEIVER == 0) // Does our recepient have a broadcaster on their level?
U.show_message("\red An error flashes on your [src]: Recipient unavailable", 1)
return
- var/obj/item/device/pda/P = locate(href_list["target"])
if(!isnull(P))
if (!P.toff && cartridge.charges > 0)
cartridge.charges--
@@ -796,8 +848,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
//EXTRA FUNCTIONS===================================
if (mode == 2||mode == 21)//To clear message overlays.
- overlays.Cut()
- newmessage = 0
+ new_message = 0
+ update_icon()
+
+ if (mode == 6||mode == 61)//To clear news overlays.
+ new_news = 0
+ update_icon()
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
@@ -805,6 +861,13 @@ var/global/list/obj/item/device/pda/PDAs = list()
return 1 // return 1 tells it to refresh the UI in NanoUI
+/obj/item/device/pda/update_icon()
+ ..()
+
+ overlays.Cut()
+ if(new_message || new_news)
+ overlays += image('icons/obj/pda.dmi', "pda-r")
+
/obj/item/device/pda/proc/detonate_act(var/obj/item/device/pda/P)
//TODO: sometimes these attacks show up on the message server
var/i = rand(1,100)
@@ -879,11 +942,11 @@ var/global/list/obj/item/device/pda/PDAs = list()
id.loc = get_turf(src)
id = null
-/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P)
-
- U.visible_message("
[U] taps on \his PDA's screen.")
+/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P, var/tap = 1)
+ if(tap)
+ U.visible_message("
[U] taps on \his PDA's screen.")
U.last_target_click = world.time
- var/t = input(U, "Please enter message", name, null) as text
+ var/t = input(U, "Please enter message", P.name, null) as text
t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
if (!t || !istype(P))
return
@@ -900,34 +963,14 @@ var/global/list/obj/item/device/pda/PDAs = list()
return
last_text = world.time
- // check if telecomms I/O route 1459 is stable
- //var/telecomms_intact = telecomms_process(P.owner, owner, t)
- var/obj/machinery/message_server/useMS = null
- if(message_servers)
- for (var/obj/machinery/message_server/MS in message_servers)
- //PDAs are now dependent on the Message Server.
- if(MS.active)
- useMS = MS
- break
+ var/datum/reception/reception = get_reception(src, P, t)
+ t = reception.message
- var/datum/signal/signal = src.telecomms_process()
-
- var/useTC = 0
- if(signal)
- if(signal.data["done"])
- useTC = 1
- var/turf/pos = get_turf(P)
- if(pos.z in signal.data["level"])
- useTC = 2
- //Let's make this barely readable
- if(signal.data["compression"] > 0)
- t = Gibberish(t, signal.data["compression"] + 50)
-
- if(useMS && useTC) // only send the message if it's stable
- if(useTC != 2) // Does our recipient have a broadcaster on their level?
+ 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?
U << "ERROR: Cannot reach recipient."
return
- var/send_result = useMS.send_pda_message("[P.owner]","[owner]","[t]")
+ var/send_result = reception.message_server.send_pda_message("[P.owner]","[owner]","[t]")
if (send_result)
U << "ERROR: Messaging server rejected your message. Reason: contains '[send_result]'."
return
@@ -955,33 +998,48 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(ai.aiPDA != P && ai.aiPDA != src)
ai.show_message("
Intercepted message from [who]: [t]")
-
- if (!P.silent)
- playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(3, P.loc))
- if(!P.silent) O.show_message(text("\icon[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)
- L << "\icon[P]
Message from [src.owner] ([ownjob]), \"[t]\" (
Reply)"
- nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message
-
- nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message
-
- log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]")
- P.overlays.Cut()
- P.overlays += image('icons/obj/pda.dmi', "pda-r")
- P.newmessage = 1
+ P.new_message_from_pda(src, t)
+ nanomanager.update_user_uis(U, src) // Update the sending user's PDA UI so that they can see the new message
else
U << "
ERROR: Messaging server is not responding."
+/obj/item/device/pda/proc/new_info(var/beep_silent, var/message_tone, var/reception_message)
+ if (!beep_silent)
+ playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(3, loc))
+ O.show_message(text("\icon[src] *[message_tone]*"))
+ //Search for holder of the PDA.
+ var/mob/living/L = null
+ if(loc && isliving(loc))
+ L = loc
+ //Maybe they are a pAI!
+ else
+ L = get(src, /mob/living/silicon)
+
+ if(L)
+ if(reception_message)
+ L << reception_message
+ nanomanager.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 ? "" : "\icon[src]
[message]")
+
+ 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)
+ new_message(sending_device.name, sending_device.owner, sending_device.ownjob, message)
+
+/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
+ var/reception_message = "\icon[src]
Message from [sender] ([sender_job]), \"[message]\" (
Reply)"
+ new_info(news_silent, newstone, reception_message)
+
+ log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
+ new_message = 1
+ update_icon()
/obj/item/device/pda/verb/verb_remove_id()
set category = "Object"
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 019422b617..72e39b7063 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -97,10 +97,7 @@
SetLuminosity(12)
// found a powernet, so drain up to max power from it
-
- var/drained = min ( drain_rate, PN.avail )
- PN.newload += drained
- power_drained += drained
+ var/drained = PN.draw_power(drain_rate)
// if tried to drain more than available on powernet
// now look for APCs and drain their cells
diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm
index 287e827249..e10e963b5f 100644
--- a/code/game/objects/items/devices/radio/encryptionkey.dm
+++ b/code/game/objects/items/devices/radio/encryptionkey.dm
@@ -5,6 +5,7 @@
icon = 'icons/obj/radio.dmi'
icon_state = "cypherkey"
item_state = ""
+ w_class = 1
var/translate_binary = 0
var/translate_hive = 0
var/syndie = 0
@@ -17,7 +18,7 @@
/obj/item/device/encryptionkey/syndicate
icon_state = "cypherkey"
- channels = list("Syndicate" = 1)
+ channels = list("Mercenary" = 1)
origin_tech = "syndicate=3"
syndie = 1//Signifies that it de-crypts Syndicate transmissions
@@ -78,7 +79,7 @@
name = "AI Integrated Encryption Key"
desc = "Integrated encryption key"
icon_state = "cap_cypherkey"
- channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1)
+ channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "AI Private" = 1)
/obj/item/device/encryptionkey/heads/rd
name = "Research Director's Encryption Key"
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index e7b7043266..1e7eecb9a7 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -19,6 +19,18 @@
keyslot1 = new /obj/item/device/encryptionkey/
recalculateChannels()
+/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, message, channel)
+ if (channel == "special")
+ if (translate_binary)
+ var/datum/language/binary = all_languages["Robot Talk"]
+ binary.broadcast(M, message)
+ if (translate_hive)
+ var/datum/language/hivemind = all_languages["Hivemind"]
+ hivemind.broadcast(M, message)
+ return null
+
+ return ..()
+
/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0)
if (aiOverride)
return ..(freq, level)
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 843ce25b29..98ac645196 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -1,6 +1,3 @@
-var/GLOBAL_RADIO_TYPE = 1 // radio type to use
- // 0 = old radios
- // 1 = new radios (subspace technology)
/obj/item/device/radio
@@ -219,6 +216,23 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
del(A)
return
+// Interprets the message mode when talking into a radio, possibly returning a connection datum
+/obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, message, message_mode)
+ // If a channel isn't specified, send to common.
+ if(!message_mode || message_mode == "headset")
+ return radio_connection
+
+ // Otherwise, if a channel is specified, look for it.
+ if(channels)
+ if (message_mode == "department") // Department radio shortcut
+ message_mode = channels[1]
+
+ if (channels[message_mode]) // only broadcast if the channel is set on
+ return secure_radio_connections[message_mode]
+
+ // If we were to send to a channel we don't have, drop it.
+ return null
+
/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel, var/verb = "says", var/datum/language/speaking = null)
if(!on) return // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them.
@@ -231,161 +245,85 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
M.last_target_click = world.time
- if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
+ /* Quick introduction:
+ This new radio system uses a very robust FTL signaling technology unoriginally
+ dubbed "subspace" which is somewhat similar to 'blue-space' but can't
+ actually transmit large mass. Headsets are the only radio devices capable
+ of sending subspace transmissions to the Communications Satellite.
- /* Quick introduction:
- This new radio system uses a very robust FTL signaling technology unoriginally
- dubbed "subspace" which is somewhat similar to 'blue-space' but can't
- actually transmit large mass. Headsets are the only radio devices capable
- of sending subspace transmissions to the Communications Satellite.
+ A headset sends a signal to a subspace listener/reciever elsewhere in space,
+ the signal gets processed and logged, and an audible transmission gets sent
+ to each individual headset.
+ */
- A headset sends a signal to a subspace listener/reciever elsewhere in space,
- the signal gets processed and logged, and an audible transmission gets sent
- to each individual headset.
- */
+ //#### Grab the connection datum ####//
+ var/datum/radio_frequency/connection = handle_message_mode(M, message, channel)
+ if (!istype(connection))
+ return
+ if (!connection)
+ return
- //#### Grab the connection datum ####//
- var/datum/radio_frequency/connection = null
- if(channel == "headset")
- channel = null
- if(channel) // If a channel is specified, look for it.
- if(channels && channels.len > 0)
- if (channel == "department")
- //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
- channel = channels[1]
- connection = secure_radio_connections[channel]
- if (!channels[channel]) // if the channel is turned off, don't broadcast
- return
- else
- // If we were to send to a channel we don't have, drop it.
- else // If a channel isn't specified, send to common.
- connection = radio_connection
- channel = null
- if (!istype(connection))
- return
- if (!connection)
- return
+ var/turf/position = get_turf(src)
- var/turf/position = get_turf(src)
+ //#### Tagging the signal with all appropriate identity values ####//
- //#### Tagging the signal with all appropriate identity values ####//
-
- // ||-- The mob's name identity --||
- var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
- var/real_name = M.real_name // mob's real name
- var/mobkey = "none" // player key associated with mob
- var/voicemask = 0 // the speaker is wearing a voice mask
- if(M.client)
- mobkey = M.key // assign the mob's key
+ // ||-- The mob's name identity --||
+ var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
+ var/real_name = M.real_name // mob's real name
+ var/mobkey = "none" // player key associated with mob
+ var/voicemask = 0 // the speaker is wearing a voice mask
+ if(M.client)
+ mobkey = M.key // assign the mob's key
- var/jobname // the mob's "job"
+ var/jobname // the mob's "job"
- // --- Human: use their actual job ---
- if (ishuman(M))
- jobname = M:get_assignment()
+ // --- Human: use their actual job ---
+ if (ishuman(M))
+ jobname = M:get_assignment()
- // --- Carbon Nonhuman ---
- else if (iscarbon(M)) // Nonhuman carbon mob
- jobname = "No id"
+ // --- Carbon Nonhuman ---
+ else if (iscarbon(M)) // Nonhuman carbon mob
+ jobname = "No id"
- // --- AI ---
- else if (isAI(M))
- jobname = "AI"
+ // --- AI ---
+ else if (isAI(M))
+ jobname = "AI"
- // --- Cyborg ---
- else if (isrobot(M))
- jobname = "Cyborg"
+ // --- Cyborg ---
+ else if (isrobot(M))
+ jobname = "Cyborg"
- // --- Personal AI (pAI) ---
- else if (istype(M, /mob/living/silicon/pai))
- jobname = "Personal AI"
+ // --- Personal AI (pAI) ---
+ else if (istype(M, /mob/living/silicon/pai))
+ jobname = "Personal AI"
- // --- Unidentifiable mob ---
- else
- jobname = "Unknown"
+ // --- Unidentifiable mob ---
+ else
+ jobname = "Unknown"
- // --- Modifications to the mob's identity ---
+ // --- Modifications to the mob's identity ---
- // The mob is disguising their identity:
- if (ishuman(M) && M.GetVoice() != real_name)
- displayname = M.GetVoice()
- jobname = "Unknown"
- voicemask = 1
+ // The mob is disguising their identity:
+ if (ishuman(M) && M.GetVoice() != real_name)
+ displayname = M.GetVoice()
+ jobname = "Unknown"
+ voicemask = 1
- /* ###### Radio headsets can only broadcast through subspace ###### */
-
- if(subspace_transmission)
- // First, we want to generate a new radio signal
- var/datum/signal/signal = new
- signal.transmission_method = 2 // 2 would be a subspace transmission.
- // transmission_method could probably be enumerated through #define. Would be neater.
-
- // --- Finally, tag the actual signal with the appropriate values ---
- signal.data = list(
- // Identity-associated tags:
- "mob" = M, // store a reference to the mob
- "mobtype" = M.type, // the mob's type
- "realname" = real_name, // the mob's real name
- "name" = displayname, // the mob's display name
- "job" = jobname, // the mob's job
- "key" = mobkey, // the mob's key
- "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
- "vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mask
-
- // We store things that would otherwise be kept in the actual mob
- // so that they can be logged even AFTER the mob is deleted or something
-
- // Other tags:
- "compression" = rand(45,50), // compressed radio signal
- "message" = message, // the actual sent message
- "connection" = connection, // the radio connection to use
- "radio" = src, // stores the radio used for transmission
- "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
- "traffic" = 0, // dictates the total traffic sum that the signal went through
- "type" = 0, // determines what type of radio input it is: normal broadcast
- "server" = null, // the last server to log this signal
- "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
- "level" = position.z, // The source's z level
- "language" = speaking,
- "verb" = verb
- )
- signal.frequency = connection.frequency // Quick frequency set
-
- //#### Sending the signal to all subspace receivers ####//
-
- for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
- R.receive_signal(signal)
-
- // Allinone can act as receivers.
- for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
- R.receive_signal(signal)
-
- // Receiving code can be located in Telecommunications.dm
- return
-
-
- /* ###### Intercoms and station-bounced radios ###### */
-
- var/filter_type = 2
-
- /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
- if(istype(src, /obj/item/device/radio/intercom))
- filter_type = 1
-
+ /* ###### Radio headsets can only broadcast through subspace ###### */
+ if(subspace_transmission)
+ // First, we want to generate a new radio signal
var/datum/signal/signal = new
- signal.transmission_method = 2
-
-
- /* --- Try to send a normal subspace broadcast first */
+ signal.transmission_method = 2 // 2 would be a subspace transmission.
+ // transmission_method could probably be enumerated through #define. Would be neater.
+ // --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
-
+ // Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
@@ -394,192 +332,102 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
"key" = mobkey, // the mob's key
"vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mas
+ "vmask" = voicemask, // 1 if the mob is using a voice gas mask
- "compression" = 0, // uncompressed radio signal
+ // We store things that would otherwise be kept in the actual mob
+ // so that they can be logged even AFTER the mob is deleted or something
+
+ // Other tags:
+ "compression" = rand(45,50), // compressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
- "slow" = 0,
- "traffic" = 0,
- "type" = 0,
- "server" = null,
- "reject" = 0,
- "level" = position.z,
+ "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
+ "traffic" = 0, // dictates the total traffic sum that the signal went through
+ "type" = 0, // determines what type of radio input it is: normal broadcast
+ "server" = null, // the last server to log this signal
+ "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
+ "level" = position.z, // The source's z level
"language" = speaking,
"verb" = verb
)
signal.frequency = connection.frequency // Quick frequency set
+ //#### Sending the signal to all subspace receivers ####//
+
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
+ // Allinone can act as receivers.
+ for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
+ R.receive_signal(signal)
- sleep(rand(10,25)) // wait a little...
-
- if(signal.data["done"] && position.z in signal.data["level"])
- // we're done here.
- return
-
- // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
- // Send a mundane broadcast with limited targets:
-
- //THIS IS TEMPORARY.
- if(!connection) return //~Carn
-
- Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
- src, message, displayname, jobname, real_name, M.voice_name,
- filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking)
+ // Receiving code can be located in Telecommunications.dm
+ return
+ /* ###### Intercoms and station-bounced radios ###### */
- else // OLD RADIO SYSTEMS: By Goons?
+ var/filter_type = 2
- var/datum/radio_frequency/connection = null
- if(channel && channels && channels.len > 0)
- if (channel == "department")
- //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
- channel = channels[1]
- connection = secure_radio_connections[channel]
- else
- connection = radio_connection
- channel = null
- if (!istype(connection))
- return
- var/display_freq = connection.frequency
+ /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
+ if(istype(src, /obj/item/device/radio/intercom))
+ filter_type = 1
- //world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
- var/eqjobname
+ var/datum/signal/signal = new
+ signal.transmission_method = 2
- if (ishuman(M))
- eqjobname = M:get_assignment()
- else if (iscarbon(M))
- eqjobname = "No id" //only humans can wear ID
- else if (isAI(M))
- eqjobname = "AI"
- else if (isrobot(M))
- eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion.
- else if (istype(M, /mob/living/silicon/pai))
- eqjobname = "Personal AI"
- else
- eqjobname = "Unknown"
- if (!(wires & WIRE_TRANSMIT))
- return
+ /* --- Try to send a normal subspace broadcast first */
- var/list/receive = list()
+ signal.data = list(
- //for (var/obj/item/device/radio/R in radio_connection.devices)
- for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE
- //if(R.accept_rad(src, message))
- receive |= R.send_hear(display_freq, 0)
+ "mob" = M, // store a reference to the mob
+ "mobtype" = M.type, // the mob's type
+ "realname" = real_name, // the mob's real name
+ "name" = displayname, // the mob's display name
+ "job" = jobname, // the mob's job
+ "key" = mobkey, // the mob's key
+ "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
+ "vname" = M.voice_name, // the name to display if the voice wasn't understood
+ "vmask" = voicemask, // 1 if the mob is using a voice gas mas
- //world << "DEBUG: receive.len=[receive.len]"
- var/list/heard_masked = list() // masked name or no real name
- var/list/heard_normal = list() // normal message
- var/list/heard_voice = list() // voice message
- var/list/heard_garbled = list() // garbled message
+ "compression" = 0, // uncompressed radio signal
+ "message" = message, // the actual sent message
+ "connection" = connection, // the radio connection to use
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0,
+ "traffic" = 0,
+ "type" = 0,
+ "server" = null,
+ "reject" = 0,
+ "level" = position.z,
+ "language" = speaking,
+ "verb" = verb
+ )
+ signal.frequency = connection.frequency // Quick frequency set
- for (var/mob/R in receive)
- if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
- if (R.say_understands(M))
- if (ishuman(M) && M.GetVoice() != M.real_name)
- heard_masked += R
- else
- heard_normal += R
- else
- heard_voice += R
+ for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
+ R.receive_signal(signal)
- if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
- var/part_a = "
"
- //var/part_b = " \icon[src]\[[format_frequency(frequency)]\] "
- var/freq_text= get_frequency_name(display_freq)
- var/part_b = " \icon[src]\[[freq_text]\] " // Tweaked for security headsets -- TLE
- var/part_c = ""
+ sleep(rand(10,25)) // wait a little...
- if (display_freq in ANTAG_FREQS)
- part_a = "
"
- else if (display_freq==COMM_FREQ)
- part_a = ""
- else if (display_freq in DEPT_FREQS)
- part_a = ""
+ if(signal.data["done"] && position.z in signal.data["level"])
+ // we're done here.
+ return
- var/quotedmsg = M.say_quote(message)
+ // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
+ // Send a mundane broadcast with limited targets:
- //This following recording is intended for research and feedback in the use of department radio channels.
+ //THIS IS TEMPORARY. YEAH RIGHT
+ if(!connection) return //~Carn
- var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE
- var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]"
- //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
- if(istype(blackbox))
- //BR.messages_admin += blackbox_admin_msg
- switch(display_freq)
- if(PUB_FREQ)
- blackbox.msg_common += blackbox_msg
- if(SCI_FREQ)
- blackbox.msg_science += blackbox_msg
- if(COMM_FREQ)
- blackbox.msg_command += blackbox_msg
- if(MED_FREQ)
- blackbox.msg_medical += blackbox_msg
- if(ENG_FREQ)
- blackbox.msg_engineering += blackbox_msg
- if(SEC_FREQ)
- blackbox.msg_security += blackbox_msg
- if(DTH_FREQ)
- blackbox.msg_deathsquad += blackbox_msg
- if(SYND_FREQ)
- blackbox.msg_syndicate += blackbox_msg
- if(SUP_FREQ)
- blackbox.msg_cargo += blackbox_msg
- else
- blackbox.messages += blackbox_msg
+ Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
+ src, message, displayname, jobname, real_name, M.voice_name,
+ filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking)
- //End of research and feedback code.
-
- if (length(heard_masked))
- var/N = M.name
- var/J = eqjobname
- if(ishuman(M) && M.GetVoice() != M.real_name)
- N = M.GetVoice()
- J = "Unknown"
- var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
- for (var/mob/R in heard_masked)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][N] ([J]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_normal))
- var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_normal)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.real_name] ([eqjobname]) [part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_voice))
- var/rendered = "[part_a][M.voice_name][part_b][pick(M.speak_emote)][part_c]"
-
- for (var/mob/R in heard_voice)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.voice_name] ([eqjobname]) [part_b][pick(M.speak_emote)][part_c]", 2)
- else
- R.show_message(rendered, 2)
-
- if (length(heard_garbled))
- quotedmsg = M.say_quote(stars(message))
- var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]"
-
- for (var/mob/R in heard_voice)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][M.voice_name][part_b][quotedmsg][part_c]", 2)
- else
- R.show_message(rendered, 2)
/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null)
@@ -689,6 +537,13 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
icon_state = "radio"
canhear_range = 3
+/obj/item/device/radio/borg/talk_into()
+ ..()
+ if (isrobot(src.loc))
+ var/mob/living/silicon/robot/R = src.loc
+ var/datum/robot_component/C = R.components["radio"]
+ R.cell_use_power(C.active_usage)
+
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.set_machine(src)
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 0d74cb57c7..51a7a97e15 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -31,7 +31,12 @@ datum/nano_item_lists
var/nanoui_menu = 0 // The current menu we are in
var/list/nanoui_data = new // Additional data for NanoUI use
+ var/list/purchase_log = new
+ var/uplink_owner = null//text-only
+ var/used_TC = 0
+
/obj/item/device/uplink/New()
+ ..()
welcome = ticker.mode.uplink_welcome
uses = ticker.mode.uplink_uses
ItemsCategory = ticker.mode.uplink_items
@@ -40,6 +45,12 @@ datum/nano_item_lists
nanoui_items = IL.items_nano
ItemsReference = IL.items_reference
+ world_uplinks += src
+
+/obj/item/device/uplink/Del()
+ world_uplinks -= src
+ ..()
+
// BS12 no longer use this menu but there are forks that do, hency why we keep it
/obj/item/device/uplink/proc/generate_menu()
var/dat = "[src.welcome]
"
@@ -98,18 +109,32 @@ datum/nano_item_lists
/obj/item/device/uplink/Topic(href, href_list)
if(href_list["buy_item"] == "random")
- var/datum/uplink_item/boughtItem = chooseRandomItem()
- if(boughtItem && boughtItem.cost <= uses)
- uses -= boughtItem.cost
- href_list["buy_item"] = boughtItem.reference
- feedback_add_details("traitor_uplink_items_bought","RN")
- return 1
+ var/datum/uplink_item/UI = chooseRandomItem()
+ href_list["buy_item"] = UI.reference
+ return buy(UI, "RN")
else
var/datum/uplink_item/UI = ItemsReference[href_list["buy_item"]]
- if(UI && UI.cost <= uses)
- uses -= UI.cost
- feedback_add_details("traitor_uplink_items_bought", UI.reference)
- return 1
+ return buy(UI, UI ? UI.reference : "")
+ return 0
+
+/obj/item/device/uplink/proc/buy(var/datum/uplink_item/UI, var/reference)
+ if(UI && UI.cost <= uses)
+ uses -= UI.cost
+ used_TC += UI.cost
+ feedback_add_details("traitor_uplink_items_bought", reference)
+
+ var/obj/I = new UI.path(get_turf(usr))
+ if(ishuman(usr))
+ var/mob/living/carbon/human/A = usr
+ A.put_in_any_hand_if_possible(I)
+
+ if(istype(I ,/obj/item/weapon/storage/box/) && I.contents.len>0)
+ for(var/atom/o in I)
+ purchase_log += "\icon[o]"
+ else
+ purchase_log += "\icon[I]"
+
+ return 1
return 0
// HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it.
@@ -128,7 +153,6 @@ datum/nano_item_lists
name = "Hidden Uplink."
desc = "There is something wrong if you're examining this."
var/active = 0
- var/list/purchase_log = list()
// The hidden uplink MUST be inside an obj/item's contents.
/obj/item/device/uplink/hidden/New()
@@ -160,7 +184,7 @@ datum/nano_item_lists
NANO UI FOR UPLINK WOOP WOOP
*/
/obj/item/device/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- var/title = "Syndicate Uplink"
+ var/title = "Remote Uplink"
var/data[0]
data["welcome"] = welcome
@@ -195,7 +219,9 @@ datum/nano_item_lists
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
if ((usr.contents.Find(src.loc) || (in_range(src.loc, usr) && istype(src.loc.loc, /turf))))
usr.set_machine(src)
- if(href_list["lock"])
+ if(..(href, href_list))
+ return 1
+ else if(href_list["lock"])
toggle()
ui.close()
return 1
@@ -205,16 +231,7 @@ datum/nano_item_lists
if(href_list["menu"])
nanoui_menu = text2num(href_list["menu"])
update_nano_data(href_list["id"])
- else if(..(href, href_list) == 1)
- var/datum/uplink_item/UI = ItemsReference[href_list["buy_item"]]
- if(!UI)
- return
- var/obj/I = new UI.path(get_turf(usr))
- if(ishuman(usr))
- var/mob/living/carbon/human/A = usr
- A.put_in_any_hand_if_possible(I)
- purchase_log += "[usr] ([usr.ckey]) bought [I]."
interact(usr)
return 1
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 28fa0f46db..4fa42ad71c 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -88,7 +88,7 @@
item_state = "balloon-empty"
/obj/item/toy/syndicateballoon
- name = "syndicate balloon"
+ name = "criminal balloon"
desc = "There is a tag on the back that reads \"FUK NT!11!\"."
throwforce = 0
throw_speed = 4
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index b301a77e76..99c4f960b0 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -1060,7 +1060,7 @@
- Or: What the fuck does a "passive gate" do?
+ Or: What the fuck does a "pressure regulator" do?
Alright. It has come to my attention that a variety of people are unsure of what a "pipe" is and what it does.
Apparently, there is an unnatural fear of these arcane devices and their "gases." Spooky, spooky. So,
@@ -1085,6 +1085,9 @@
Manual T-valve: Like a manual valve, but at the center of a manifold instead of a straight pipe.
+ An important note here is that pipes are now done in three distinct lines - general, supply, and scrubber. You can move gases between these with a universal adapter. Use the correct position for the correct location.
+ Connecting scrubbers to a supply position pipe makes you an idiot who gives everyone a difficult job. Insulated and HE pipes don't go through these positions.
+
Bent pipes: Pipes with a 90 degree bend at the half-meter mark. My goodness.
Pipe manifolds: Pipes that are essentially a "T" shape, allowing you to connect three things at one point.
@@ -1103,22 +1106,19 @@
Stop it. It's unbecoming. Most of these are fairly straightforward.
- - Gas pump: Take a wild guess. It moves gas in the direction it's pointing (marked by the red line on one end). It moves it based on pressure, the maximum output being 4500 kPa (kilopascals).
+
- Gas pump: Take a wild guess. It moves gas in the direction it's pointing (marked by the red line on one end). It moves it based on pressure, the maximum output being 15000 kPa (kilopascals).
Ordinary atmospheric pressure, for comparison, is 101.3 kPa, and the minimum pressure of room-temperature pure oxygen needed to not suffocate in a matter of minutes is 16 kPa
- (though 18 kPa is preferred using internals, for various reasons).
- - Volume pump: This pump goes based on volume, instead of pressure, and the possible maximum pressure it can create in the pipe on the receiving end is double the gas pump because of this,
- clocking in at an incredible 9000 kPa. If a pipe with this is destroyed or damaged, and this pressure of gas escapes, it can be incredibly dangerous depending on the size of the pipe filled.
- Don't hook this to the distribution loop, or you will make babies cry and the Chief Engineer brutally beat you.
- - Passive gate: This is essentially a cap on the pressure of gas allowed to flow in a specific direction.
- When turned on, instead of actively pumping gas, it measures the pressure flowing through it, and whatever pressure you set is the maximum: it'll cap after that.
- In addition, it only lets gas flow one way. The direction the gas flows is opposite the red handle on it, which is confusing to people used to the red stripe on pumps pointing the way.
+ (though 18 kPa is preferred when using internals with pure oxygen, for various reasons). A high-powered variant will move gas more quickly at the expense of consuming more power. Do not turn the distribution loop up to 15000 kPa.
+ You will make engiborgs cry and the Chief Engineer will beat you.
+ - Pressure regulator: These replaced the old passive gates. You can choose to regulate pressure by input or output, and regulate flow rate. Regulating by input means that when input pressure is above the limit, gas will flow.
+ Regulating by output means that when pressure is below the limit, gas will flow. Flow rate can be controlled.
- Unary vent: The basic vent used in rooms. It pumps gas into the room, but can't suck it back out. Controlled by the room's air alarm system.
- Scrubber: The other half of room equipment. Filters air, and can suck it in entirely in what's called a "panic siphon." Activating a panic siphon without very good reason will kill someone. Don't do it.
- Meter: A little box with some gauges and numbers. Fasten it to any pipe or manifold and it'll read you the pressure in it. Very useful.
- - Gas mixer: Two sides are input, one side is output. Mixes the gases pumped into it at the ratio defined. The side perpendicular to the other two is "node 2," for reference.
- Can output this gas at pressures from 0-4500 kPa.
+ - Gas mixer: Two sides are input, one side is output. Mixes the gases pumped into it at the ratio defined. The side perpendicular to the other two is "node 2," for reference, on non-mirrored mixers..
+ Output is controlled by flow rate. There is also an "omni" variant that allows you to set input and output sections freely..
- Gas filter: Essentially the opposite of a gas mixer. One side is input. The other two sides are output. One gas type will be filtered into the perpendicular output pipe,
- the rest will continue out the other side. Can also output from 0-4500 kPa.
+ the rest will continue out the other side. Can also output from 0-4500 kPa. The "omni" vairant allows you to set input and output sections freely.
@@ -1130,10 +1130,11 @@
Bent pipe: Take a wild guess.
Junction: The point where you connect your normal pipes to heat exchange pipes. Not necessary for heat exchangers, but necessary for H/E pipes/bent pipes.
Heat exchanger: These funky-looking bits attach to an open pipe end. Put another heat exchanger directly across from it, and you can transfer heat across two pipes without having to have the gases touch.
- This normally shouldn't exchange with the ambient air, despite being totally exposed. Just don't ask questions...
+ This normally shouldn't exchange with the ambient air, despite being totally exposed. Just don't ask questions.
That's about it for pipes. Go forth, armed with this knowledge, and try not to break, burn down, or kill anything. Please.
+