diff --git a/baystation12.dme b/baystation12.dme
index e4719049f3..cd0685ffb0 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -133,6 +133,13 @@
#define FILE_DIR "code/modules/projectiles/projectile"
#define FILE_DIR "code/modules/recycling"
#define FILE_DIR "code/modules/research"
+#define FILE_DIR "code/modules/scripting"
+#define FILE_DIR "code/modules/scripting/AST"
+#define FILE_DIR "code/modules/scripting/AST/Operators"
+#define FILE_DIR "code/modules/scripting/Implementations"
+#define FILE_DIR "code/modules/scripting/Interpreter"
+#define FILE_DIR "code/modules/scripting/Parser"
+#define FILE_DIR "code/modules/scripting/Scanner"
#define FILE_DIR "code/modules/security levels"
#define FILE_DIR "code/unused"
#define FILE_DIR "code/unused/beast"
@@ -549,6 +556,7 @@
#include "code\game\machinery\telecomms\machine_interactions.dm"
#include "code\game\machinery\telecomms\telecommunications.dm"
#include "code\game\machinery\telecomms\telemonitor.dm"
+#include "code\game\machinery\telecomms\traffic_control.dm"
#include "code\game\magic\archived_book.dm"
#include "code\game\magic\library.dm"
#include "code\game\magic\musician.dm"
@@ -702,6 +710,7 @@
#include "code\game\objects\items\weapons\implants\implantpad.dm"
#include "code\game\objects\radio\beacon.dm"
#include "code\game\objects\radio\electropack.dm"
+#include "code\game\objects\radio\encryptionkey.dm"
#include "code\game\objects\radio\headset.dm"
#include "code\game\objects\radio\intercom.dm"
#include "code\game\objects\radio\radio.dm"
@@ -1025,6 +1034,26 @@
#include "code\modules\research\rdmachines.dm"
#include "code\modules\research\research.dm"
#include "code\modules\research\server.dm"
+#include "code\modules\scripting\Errors.dm"
+#include "code\modules\scripting\IDE.dm"
+#include "code\modules\scripting\Options.dm"
+#include "code\modules\scripting\stack.dm"
+#include "code\modules\scripting\AST\AST Nodes.dm"
+#include "code\modules\scripting\AST\Blocks.dm"
+#include "code\modules\scripting\AST\Statements.dm"
+#include "code\modules\scripting\AST\Operators\Binary Operators.dm"
+#include "code\modules\scripting\AST\Operators\Unary Operators.dm"
+#include "code\modules\scripting\Implementations\_Logic.dm"
+#include "code\modules\scripting\Implementations\Telecomms.dm"
+#include "code\modules\scripting\Interpreter\Evaluation.dm"
+#include "code\modules\scripting\Interpreter\Interaction.dm"
+#include "code\modules\scripting\Interpreter\Interpreter.dm"
+#include "code\modules\scripting\Interpreter\Scope.dm"
+#include "code\modules\scripting\Parser\Expressions.dm"
+#include "code\modules\scripting\Parser\Keywords.dm"
+#include "code\modules\scripting\Parser\Parser.dm"
+#include "code\modules\scripting\Scanner\Scanner.dm"
+#include "code\modules\scripting\Scanner\Tokens.dm"
#include "code\modules\security levels\keycard authentication.dm"
#include "code\modules\security levels\security levels.dm"
#include "code\WorkInProgress\AI_Visibility.dm"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index df605dd7d0..d6fce9d1d9 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -45,6 +45,8 @@ Stealth and Camouflage Items;
/obj/item/clothing/mask/gas/voice:4:Voice Changer;
/obj/item/clothing/glasses/thermal:4:Thermal Imaging Glasses;
/obj/item/device/chameleon:4:Chameleon-Projector;
+/obj/item/device/encryptionkey/traitor:3:Traitor Radio Key;
+/obj/item/device/encryptionkey/binary:3:Binary Translator Key;
/obj/item/weapon/stamperaser:1:Stamp Remover;
Whitespace:Seperator;
Devices and Tools;
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index e058b35984..2eb032eaca 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -218,10 +218,7 @@
return tempfreq
/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob,radio_freq)
- var/obj/item/device/radio/R = new /obj/item/device/radio/headset(synd_mob)
- R.freerange = 1
- R.listening = 0
- R.config(list("Nuclear" = 1))
+ var/obj/item/device/radio/R = new /obj/item/device/radio/headset/nuclear(synd_mob)
synd_mob.equip_if_possible(R, synd_mob.slot_ears)
synd_mob.equip_if_possible(new /obj/item/clothing/under/syndicate(synd_mob), synd_mob.slot_w_uniform)
synd_mob.equip_if_possible(new /obj/item/clothing/shoes/black(synd_mob), synd_mob.slot_shoes)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index dcc30eceec..7a60d10ecd 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -46,12 +46,12 @@
if (src.yes_code)
dat += text("\nStatus: []-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: --- [] +++
\n
\nSafety: [] Toggle
\nAnchor: [] Toggle
\n", (src.timing ? "Func/Set" : "Functional"), (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), src, src, src, src, time_left, src, src, src, (src.safety ? "On" : "Off"), src, (src.anchored ? "Engaged" : "Off"), src)
else
- dat += text("\nStatus: Auth. S2-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: - - [] + +
\n
\n[] Safety: Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
+ dat += text("\nStatus: Auth. S2-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: --- [] +++
\n
\n[] Safety: Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
else
if (src.timing)
- dat += text("\nStatus: Set-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: - - [] + +
\n
\nSafety: [] Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
+ dat += text("\nStatus: Set-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: --- [] +++
\n
\nSafety: [] Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
else
- dat += text("\nStatus: Auth. S1-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: - - [] + +
\n
\nSafety: [] Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
+ dat += text("\nStatus: Auth. S1-[]
\nTimer: []
\n
\nTimer: [] Toggle
\nTime: --- [] +++
\n
\nSafety: [] Toggle
\nAnchor: [] Toggle
\n", (src.safety ? "Safe" : "Engaged"), time_left, (src.timing ? "On" : "Off"), time_left, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off"))
var/message = "AUTH"
if (src.auth)
message = text("[]", src.code)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index dca6d7b4b4..0a0b60d236 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -5,7 +5,7 @@
/datum/game_mode/traitor
name = "traitor"
config_tag = "traitor"
- restricted_jobs = list("Cyborg")//Approved by headmins for a week test, if you see this it would be nice if you didn't spread it everywhere
+ restricted_jobs = list("Cyborg", "AI")//Approved by headmins for a week test, if you see this it would be nice if you didn't spread it everywhere
required_players = 0
required_enemies = 1
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index c3ac2943d8..0a923bf110 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -8,6 +8,7 @@
var
list/recentmessages = list() // global list of recent messages broadcasted : used to circumvent massive radio spam
+
/obj/machinery/telecomms/broadcaster
name = "Subspace Broadcaster"
icon = 'stationobjs.dmi'
@@ -21,16 +22,21 @@ var
heatgen = 60
delay = 7
circuitboard = "/obj/item/weapon/circuitboard/telecomms/broadcaster"
+
receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
+ // Don't broadcast rejected signals
+ if(signal.data["reject"])
+ return
if(signal.data["message"])
- // Kind of lame way to prevent MASSIVE RADIO SPAM but it works
+ // Prevents massive radio spam
if("[signal.data["message"]]:[signal.data["realname"]]" in recentmessages)
return
recentmessages.Add( "[signal.data["message"]]:[signal.data["realname"]]" )
+
signal.data["done"] = 1 // mark the signal as being broadcasted
// Search for the original signal and mark it as done as well
@@ -41,19 +47,48 @@ var
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
- /* ###### Broadcast a message using signal.data ###### */
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"],, signal.data["compression"])
- /* --- Do a snazzy animation! --- */
- flick("broadcaster_send", src)
+ /** #### - Normal Broadcast - #### **/
+
+ if(signal.data["type"] == 0)
+
+ /* ###### Broadcast a message using signal.data ###### */
+ Broadcast_Message(signal.data["connection"], signal.data["mob"],
+ signal.data["vmask"], signal.data["vmessage"],
+ signal.data["radio"], signal.data["message"],
+ signal.data["name"], signal.data["job"],
+ signal.data["realname"], signal.data["vname"],, signal.data["compression"])
+
+
+ /** #### - Simple Broadcast - #### **/
+
+ if(signal.data["type"] == 1)
+
+ /* ###### Broadcast a message using signal.data ###### */
+ Broadcast_SimpleMessage(signal.data["name"], signal.frequency,
+ signal.data["message"],null, null,
+ signal.data["compression"])
+
+
+ /** #### - Artificial Broadcast - #### **/
+ // (Imitates a mob)
+
+ if(signal.data["type"] == 2)
+
+ /* ###### Broadcast a message using signal.data ###### */
+ // Parameter "data" as 4: AI can't track this person/mob
+
+ Broadcast_Message(signal.data["connection"], signal.data["mob"],
+ signal.data["vmask"], signal.data["vmessage"],
+ signal.data["radio"], signal.data["message"],
+ signal.data["name"], signal.data["job"],
+ signal.data["realname"], signal.data["vname"], 4, signal.data["compression"])
spawn(1)
recentmessages = list()
+ /* --- Do a snazzy animation! --- */
+ flick("broadcaster_send", src)
/*
Basically just an empty shell for receiving and broadcasting radio messages. Not
@@ -72,8 +107,8 @@ var
machinetype = 6
heatgen = 0
var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
- var/frequency = 1439
var/nuke = 0
+ var/frequency = 1439
receive_signal(datum/signal/signal)
@@ -169,6 +204,7 @@ var
1 -- Will only broadcast to intercoms
2 -- Will only broadcast to intercoms and station-bounced radios
3 -- Broadcast to syndicate frequency
+ 4 -- AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob
@param compression:
If 0, the signal is audible
@@ -211,22 +247,21 @@ var
// --- Broadcast to syndicate radio! ---
else if(data == 3)
- var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(NUKE_FREQ)
+ var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(SYND_FREQ)
for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
- receive |= R.send_hear(NUKE_FREQ)
+ receive |= R.send_hear(SYND_FREQ)
// --- Broadcast to response team radio! ---
- else if(data == 4)
+ else if(data == 5)
var/datum/radio_frequency/interceptconnection = radio_controller.return_frequency(intercept_frequency)
for (var/obj/item/device/radio/R in interceptconnection.devices["[RADIO_CHAT]"])
receive |= R.send_hear(intercept_frequency)
-
// --- Broadcast to ALL radio devices ---
else
@@ -281,7 +316,6 @@ var
// - Just display a garbled message -
else
heard_garbled += R
-
for(var/obj/item/weapon/implant/imp in R)
imp.hear(message,M)
@@ -312,8 +346,6 @@ var
freq_text = "Mining"
if(1347)
freq_text = "Cargo"
- if(1439)
- freq_text = "Response Team"
if(connection.frequency == NUKE_FREQ)
freq_text = "Agent"
@@ -335,12 +367,12 @@ var
if (display_freq==SYND_FREQ)
part_a = ""
- else if (display_freq==NUKE_FREQ)
- part_a = ""
else if (display_freq==COMM_FREQ)
part_a = ""
else if (display_freq in DEPT_FREQS)
part_a = ""
+ else if (display_freq==NUKE_FREQ)
+ part_a = ""
// --- Filter the message; place it in quotes apply a verb ---
@@ -384,6 +416,8 @@ var
//End of research and feedback code.
+ var/aitrack = ""
+
/* ###### Send the message ###### */
@@ -394,19 +428,27 @@ var
var/J = job
var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_masked)
+ aitrack = ""
+ if(data == 4)
+ aitrack = ""
+
if(istype(R, /mob/living/silicon/ai) && job != "Automated Announcement")
- R.show_message("[part_a][N] ([J]) [part_b][quotedmsg][part_c]", 2)
+ R.show_message("[part_a][aitrack][N] ([J]) [part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
/* --- Process all the mobs that heard the voice normally (understood) --- */
if (length(heard_normal))
- var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
+ var/rendered = "[part_a][realname][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_normal)
+ aitrack = ""
+ if(data == 4)
+ aitrack = ""
+
if(istype(R, /mob/living/silicon/ai) && job != "Automated Announcement")
- R.show_message("[part_a][realname] ([job]) [part_b][quotedmsg][part_c]", 2)
+ R.show_message("[part_a][aitrack][realname] ([job]) [part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
@@ -414,13 +456,16 @@ var
// Does not display message; displayes the mob's voice_message (ie "chimpers")
if (length(heard_voice))
- var/rendered = ""
- if(M)
- rendered = "[part_a][vname][part_b][M.voice_message][part_c]"
+ var/rendered = "[part_a][vname][part_b][M.voice_message][part_c]"
for (var/mob/R in heard_voice)
+ aitrack = ""
+ if(data == 4)
+ aitrack = ""
+
+
if(istype(R, /mob/living/silicon/ai) && job != "Automated Announcement")
- R.show_message("[part_a][vname] ([job]) [part_b][vmessage]][part_c]", 2)
+ R.show_message("[part_a][aitrack][vname] ([job]) [part_b][vmessage]][part_c]", 2)
else
R.show_message(rendered, 2)
@@ -428,15 +473,17 @@ var
// Displays garbled message (ie "f*c* **u, **i*er!")
if (length(heard_garbled))
- if(M)
- quotedmsg = M.say_quote(stars(message))
- else
- quotedmsg = "\"" + stars(message) + "\""
+ quotedmsg = M.say_quote(stars(message))
var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_garbled)
+ aitrack = ""
+ if(data == 4)
+ aitrack = ""
+
+
if(istype(R, /mob/living/silicon/ai) && job != "Automated Announcement")
- R.show_message("[part_a][vname][part_b][quotedmsg][part_c]", 2)
+ R.show_message("[part_a][aitrack][vname][part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
@@ -444,16 +491,239 @@ var
/* --- Complete gibberish. Usually happens when there's a compressed message --- */
if (length(heard_gibberish))
- if(M)
- quotedmsg = M.say_quote(Gibberish(message, compression + 50))
- else
- quotedmsg = "\"" + Gibberish(message, compression + 50) + "\""
+ quotedmsg = M.say_quote(Gibberish(message, compression + 50))
var/rendered = "[part_a][Gibberish(M.real_name, compression + 50)][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_gibberish)
- if(istype(R, /mob/living/silicon/ai))
- R.show_message("[part_a][Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) [part_b][quotedmsg][part_c]", 2)
+ aitrack = ""
+ if(data == 4)
+ aitrack = ""
+
+
+ if(istype(R, /mob/living/silicon/ai) && job != "Automated Announcement")
+ R.show_message("[part_a][aitrack][Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) [part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
+
+/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression)
+
+
+ /* ###### Prepare the radio connection ###### */
+
+ if(!M)
+ var/mob/living/carbon/human/H = new
+ M = H
+
+ var/datum/radio_frequency/connection = radio_controller.return_frequency(frequency)
+
+ var/display_freq = connection.frequency
+
+ var/list/receive = list()
+
+
+ // --- Broadcast only to intercom devices ---
+
+ if(data == 1)
+ for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
+
+ receive |= R.send_hear(display_freq)
+
+
+ // --- Broadcast only to intercoms and station-bounced radios ---
+
+ else if(data == 2)
+ for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
+
+ if(istype(R, /obj/item/device/radio/headset))
+ continue
+
+ receive |= R.send_hear(display_freq)
+
+
+ // --- Broadcast to syndicate radio! ---
+
+ else if(data == 3)
+ var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(SYND_FREQ)
+
+ for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
+
+ receive |= R.send_hear(SYND_FREQ)
+
+
+ // --- Broadcast to ALL radio devices ---
+
+ else
+ for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
+
+ receive |= R.send_hear(display_freq)
+
+
+ /* ###### Organize the receivers into categories for displaying the message ###### */
+
+ // Understood the message:
+ var/list/heard_normal = list() // normal message
+
+ // Did not understand the message:
+ var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
+ var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
+
+ for (var/mob/R in receive)
+
+ /* --- Loop through the receivers and categorize them --- */
+
+ if (R.client && R.client.STFU_radio) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
+ continue
+
+
+ // --- Check for compression ---
+ if(compression > 0)
+
+ heard_gibberish += R
+ continue
+
+ // --- Can understand the speech ---
+
+ if (R.say_understands(M))
+
+ heard_normal += R
+
+ // --- Can't understand the speech ---
+
+ else
+ // - Just display a garbled message -
+
+ heard_garbled += R
+ for(var/obj/item/weapon/implant/imp in R)
+ imp.hear(text,M)
+
+
+ /* ###### Begin formatting and sending the message ###### */
+ if (length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
+
+ /* --- Some miscellaneous variables to format the string output --- */
+ var/part_a = "" // goes in the actual output
+ var/freq_text // the name of the channel
+
+ // --- Set the name of the channel ---
+ switch(display_freq)
+
+ if(SYND_FREQ)
+ freq_text = "#unkn"
+ if(COMM_FREQ)
+ freq_text = "Command"
+ if(1351)
+ freq_text = "Science"
+ if(1355)
+ freq_text = "Medical"
+ if(1357)
+ freq_text = "Engineering"
+ if(1359)
+ freq_text = "Security"
+ if(1349)
+ freq_text = "Mining"
+ if(1347)
+ freq_text = "Cargo"
+
+ if(connection.frequency == NUKE_FREQ)
+ freq_text = "Agent"
+ //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
+
+
+ // --- If the frequency has not been assigned a name, just use the frequency as the name ---
+
+ if(!freq_text)
+ freq_text = format_frequency(display_freq)
+
+ // --- Some more pre-message formatting ---
+
+ var/part_b_extra = ""
+ if(data == 3) // intercepted radio message
+ part_b_extra = " (Intercepted)"
+
+ // Create a radio headset for the sole purpose of using its icon
+ var/obj/item/device/radio/headset/radio = new
+
+ var/part_b = " \icon[radio]\[[freq_text]\][part_b_extra] " // Tweaked for security headsets -- TLE
+ var/part_c = ""
+
+ if (display_freq==SYND_FREQ)
+ part_a = ""
+ else if (display_freq==COMM_FREQ)
+ part_a = ""
+ else if (display_freq in DEPT_FREQS)
+ part_a = ""
+ else if (display_freq==NUKE_FREQ)
+ part_a = ""
+
+ // --- This following recording is intended for research and feedback in the use of department radio channels ---
+
+ var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE
+ var/blackbox_msg = "[part_a][source][part_blackbox_b]\"[text]\"[part_c]"
+ //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
+ for (var/obj/machinery/blackbox_recorder/BR in world)
+ //BR.messages_admin += blackbox_admin_msg
+ switch(display_freq)
+ if(1459)
+ BR.msg_common += blackbox_msg
+ if(1351)
+ BR.msg_science += blackbox_msg
+ if(1353)
+ BR.msg_command += blackbox_msg
+ if(1355)
+ BR.msg_medical += blackbox_msg
+ if(1357)
+ BR.msg_engineering += blackbox_msg
+ if(1359)
+ BR.msg_security += blackbox_msg
+ if(1441)
+ BR.msg_deathsquad += blackbox_msg
+ if(1213)
+ BR.msg_syndicate += blackbox_msg
+ if(1349)
+ BR.msg_mining += blackbox_msg
+ if(1347)
+ BR.msg_cargo += blackbox_msg
+ else
+ BR.messages += blackbox_msg
+
+ //End of research and feedback code.
+
+ /* ###### Send the message ###### */
+
+ /* --- Process all the mobs that heard the voice normally (understood) --- */
+
+ if (length(heard_normal))
+ var/rendered = "[part_a][source][part_b]\"[text]\"[part_c]"
+ if(M.job == "Automated Announcement")
+ rendered = "[part_a][source][part_b][text][part_c]"
+
+ for (var/mob/R in heard_normal)
+ R.show_message(rendered, 2)
+
+ /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
+ // Displays garbled message (ie "f*c* **u, **i*er!")
+
+ if (length(heard_garbled))
+ var/quotedmsg = "\"[stars(text)]\""
+ if(M.job == "Automated Announcement")
+ quotedmsg = "[stars(text)]"
+ var/rendered = "[part_a][source][part_b][quotedmsg][part_c]"
+
+ for (var/mob/R in heard_garbled)
+ R.show_message(rendered, 2)
+
+
+ /* --- Complete gibberish. Usually happens when there's a compressed message --- */
+
+ if (length(heard_gibberish))
+ var/quotedmsg = "\"[Gibberish(text, compression + 50)]\""
+ if(M.job == "Automated Announcement")
+ quotedmsg = "[Gibberish(text, compression + 50)]"
+ var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]"
+
+ for (var/mob/R in heard_gibberish)
+ R.show_message(rendered, 2)
+
+
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
index 03665dda37..a9934dd7b7 100644
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ b/code/game/machinery/telecomms/logbrowser.dm
@@ -27,7 +27,7 @@
if(0)
dat += "
[temp]
"
- dat += "
Current Network: [network]
"
+ dat += "
Current Network: [network]
"
if(servers.len)
dat += "
Detected Telecommunication Servers:"
for(var/obj/machinery/telecomms/T in servers)
@@ -60,56 +60,64 @@
dat += "- [C.name] \[X\]
"
- // -- Determine race of orator --
+ // If the log is a speech file
+ if(C.input_type == "Speech File")
+ // -- Determine race of orator --
- var/race // The actual race of the mob
- var/language = "Human" // MMIs, pAIs, Cyborgs and humans all speak Human
- var/mobtype = C.parameters["mobtype"]
- var/mob/M = new mobtype
+ var/race // The actual race of the mob
+ var/language = "Human" // MMIs, pAIs, Cyborgs and humans all speak Human
+ var/mobtype = C.parameters["mobtype"]
+ var/mob/M = new mobtype
- if(ishuman(M) || isbrain(M))
- race = "Human"
+ if(ishuman(M) || isbrain(M))
+ race = "Human"
- else if(ismonkey(M))
- race = "Monkey"
- language = race
+ else if(ismonkey(M))
+ race = "Monkey"
+ language = race
- else if(issilicon(M) || C.parameters["job"] == "AI") // sometimes M gets deleted prematurely for AIs... just check the job
- race = "Artificial Life"
+ else if(issilicon(M) || C.parameters["job"] == "AI") // sometimes M gets deleted prematurely for AIs... just check the job
+ race = "Artificial Life"
- else if(ismetroid(M)) // NT knows a lot about metroids, but not aliens. Can identify metroids
- race = "Metroid"
- language = race
+ else if(ismetroid(M)) // NT knows a lot about metroids, but not aliens. Can identify metroids
+ race = "Metroid"
+ language = race
- else if(isanimal(M))
- race = "Domestic Animal"
- language = race
+ else if(isanimal(M))
+ race = "Domestic Animal"
+ language = race
- else
- race = "Unidentifiable"
- language = race
+ else
+ race = "Unidentifiable"
+ language = race
- del(M)
+ del(M)
- // -- If the orator is a human, or universal translate is active, OR mob has universal speech on --
+ // -- If the orator is a human, or universal translate is active, OR mob has universal speech on --
- if(language == "Human" || universal_translate || C.parameters["uspeech"])
+ if(language == "Human" || universal_translate || C.parameters["uspeech"])
+ dat += "Data type: [C.input_type]
"
+ dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
"
+ dat += "Class: [race]
"
+ dat += "Contents: \"[C.parameters["message"]]\"
"
+
+
+ // -- Orator is not human and universal translate not active --
+
+ else
+ dat += "Data type: Audio File
"
+ dat += "Source: Unidentifiable
"
+ dat += "Class: [race]
"
+ dat += "Contents: Unintelligble
"
+
+ dat += "
"
+
+ else if(C.input_type == "Execution Error")
dat += "Data type: [C.input_type]
"
- dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
"
- dat += "Class: [race]
"
+ dat += "Source: Internal server code
"
dat += "Contents: \"[C.parameters["message"]]\"
"
- // -- Orator is not human and universal translate not active --
-
- else
- dat += "Data type: Audio File
"
- dat += "Source: Unidentifiable
"
- dat += "Class: [race]
"
- dat += "Contents: Unintelligble
"
-
- dat += "
"
-
dat += ""
@@ -128,9 +136,6 @@
add_fingerprint(usr)
usr.machine = src
- if(!src.allowed(usr) && !emagged)
- usr << "\red ACCESS DENIED."
- return
if(href_list["viewserver"])
screen = 1
@@ -166,6 +171,11 @@
screen = 0
if(href_list["delete"])
+
+ if(!src.allowed(usr) && !emagged)
+ usr << "\red ACCESS DENIED."
+ return
+
if(SelectedServer)
var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])]
@@ -178,11 +188,11 @@
else
temp = "- FAILED: NO SELECTED MACHINE -"
- if(href_list["input"])
+ if(href_list["network"])
var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text
- if(newnet && usr in range(1, src) && newnet != network)
+ if(newnet && usr in range(1, src))
if(length(newnet) > 15)
temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -"
@@ -224,11 +234,6 @@
A.anchored = 1
del(src)
else if(istype(D, /obj/item/weapon/card/emag) && !emagged)
- var/obj/item/weapon/card/emag/E = D
- if(E.uses)
- E.uses--
- else
- return
playsound(src.loc, 'sparks4.ogg', 75, 1)
emagged = 1
user << "\blue You you disable the security protocols"
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index 2fc5a6c975..2ead66f3eb 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -139,13 +139,13 @@
dat += "
\[Add Filter\]"
dat += "
"
if(P.buffer)
- dat += "
MULTITOOL BUFFER: \ref[P.buffer] [P.buffer] \[Link\] \[Flush\]"
+ dat += "
MULTITOOL BUFFER: [P.buffer] ([P.buffer.id]) \[Link\] \[Flush\]"
else
dat += "
MULTITOOL BUFFER: \[Add Machine\]"
dat += ""
temp = ""
- user << browse(dat, "window=[src.name];size=520x500;can_resize=0")
+ user << browse(dat, "window=tcommachine;size=520x500;can_resize=0")
onclose(user, "dormitory")
Topic(href, href_list)
diff --git a/code/game/machinery/telecomms/telecommunications.dm b/code/game/machinery/telecomms/telecommunications.dm
index e1a8bab184..a84aff8bed 100644
--- a/code/game/machinery/telecomms/telecommunications.dm
+++ b/code/game/machinery/telecomms/telecommunications.dm
@@ -83,7 +83,10 @@
"connection" = signal.data["connection"],
"radio" = signal.data["radio"],
"slow" = signal.data["slow"],
- "traffic" = signal.data["traffic"]
+ "traffic" = signal.data["traffic"],
+ "type" = signal.data["type"],
+ "server" = signal.data["server"],
+ "reject" = signal.data["reject"]
)
// Keep the "original" signal constant
@@ -137,6 +140,11 @@
if(!(T in links) && machinetype != T.machinetype)
links.Add(T)
+ if(istype(src, /obj/machinery/telecomms/server))
+ var/obj/machinery/telecomms/server/S = src
+ S.Compiler = new()
+ S.Compiler.Holder = src
+
update_icon()
if(on)
@@ -355,8 +363,21 @@
circuitboard = "/obj/item/weapon/circuitboard/telecomms/server"
var
list/log_entries = list()
+ list/stored_names = list()
+ list/TrafficActions = list()
+ logs = 0 // number of logs
totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes)
+ list/memory = list() // stored memory
+ rawcode = "" // the code to compile (raw text)
+ datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code
+ autoruncode = 0 // 1 if the code is set to run every time a signal is picked up
+
+ encryption = "null" // encryption key: ie "password"
+ salt = "null" // encryption salt: ie "123comsat"
+ // would add up to md5("password123comsat")
+ language = "human"
+
receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(signal.data["message"])
@@ -382,10 +403,7 @@
log.parameters["message"] = signal.data["message"]
log.parameters["name"] = signal.data["name"]
log.parameters["realname"] = signal.data["realname"]
- if(M)
- log.parameters["uspeech"] = M.universal_speak
- else
- log.parameters["uspeech"] = 0
+ log.parameters["uspeech"] = M.universal_speak
// If the signal is still compressed, make the log entry gibberish
if(signal.data["compression"] > 0)
@@ -396,25 +414,50 @@
log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50)
log.input_type = "Corrupt File"
+ // Log and store everything that needs to be logged
log_entries.Add(log)
+ if(!(signal.data["name"] in stored_names))
+ stored_names.Add(signal.data["name"])
+ logs++
+ signal.data["server"] = src
+ // Give the log a name
var/identifier = num2text( rand(-1000,1000) + world.time )
log.name = "data packet ([md5(identifier)])"
- relay_information(signal, "/obj/machinery/telecomms/broadcaster") // send to all broadcasters
+ if(Compiler && autoruncode)
+ Compiler.Run(signal) // execute the code
+
+ relay_information(signal, "/obj/machinery/telecomms/broadcaster")
+
+
+ proc/setcode(var/t)
+ if(t)
+ if(istext(t))
+ rawcode = t
+
+ proc/compile()
+ if(Compiler)
+ return Compiler.Compile(rawcode)
proc/update_logs()
- // deletes all logs when there are 100
- if(log_entries.len >= 100)
- var/list/restore = list()
- for(var/datum/comm_log_entry/log in log_entries)
- if(log.garbage_collector) // if garbage collector is set to 1, delete
- del(log)
- else
- restore.Add(log)
+ // start deleting the very first log entry
+ if(logs >= 400)
+ for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it
+ var/datum/comm_log_entry/L = log_entries[i]
+ if(L.garbage_collector)
+ log_entries.Remove(L)
+ logs--
+ break
+
+ proc/add_entry(var/content, var/input)
+ var/datum/comm_log_entry/log = new
+ var/identifier = num2text( rand(-1000,1000) + world.time )
+ log.name = "data packet ([md5(identifier)])"
+ log.input_type = input
+ log.parameters["message"] = content
+
- log_entries.len = 0
- log_entries.Add(restore)
// Simple log entry datum
@@ -493,42 +536,42 @@
network = "tcommsat"
science
- id = "science server"
+ id = "Science Server"
freq_listening = list(1351)
autolinkers = list("science", "broadcasterA")
medical
- id = "medical server"
+ id = "Medical Server"
freq_listening = list(1355)
autolinkers = list("medical", "broadcasterA")
cargo
- id = "cargo server"
+ id = "Cargo Server"
freq_listening = list(1347)
autolinkers = list("cargo", "broadcasterA")
mining
- id = "mining server"
+ id = "Mining Server"
freq_listening = list(1349)
autolinkers = list("mining", "broadcasterA")
common
- id = "common server"
+ id = "Common Server"
freq_listening = list(1459)
autolinkers = list("common", "broadcasterB")
command
- id = "command server"
+ id = "Command Server"
freq_listening = list(1353)
autolinkers = list("command", "broadcasterB")
engineering
- id = "engineering server"
+ id = "Engineering Server"
freq_listening = list(1357)
autolinkers = list("engineering", "broadcasterB")
security
- id = "security server"
+ id = "Security Server"
freq_listening = list(1359)
autolinkers = list("security", "broadcasterB")
diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm
index a7ee7e827e..1866477d7a 100644
--- a/code/game/machinery/telecomms/telemonitor.dm
+++ b/code/game/machinery/telecomms/telemonitor.dm
@@ -18,8 +18,6 @@
temp = "" // temporary feedback messages
- req_access = list(access_tcomsat)
-
attack_hand(mob/user as mob)
if(stat & (BROKEN|NOPOWER))
return
@@ -33,7 +31,7 @@
if(0)
dat += "
[temp]
"
- dat += "
Current Network: [network]
"
+ dat += "
Current Network: [network]
"
if(machines.len)
dat += "
Detected Network Entities:"
for(var/obj/machinery/telecomms/T in machines)
@@ -72,9 +70,6 @@
add_fingerprint(usr)
usr.machine = src
- if(!src.allowed(usr) && !emagged)
- usr << "\red ACCESS DENIED."
- return
if(href_list["viewmachine"])
screen = 1
@@ -110,10 +105,10 @@
screen = 0
- if(href_list["input"])
+ if(href_list["network"])
var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text
- if(newnet && usr in range(1, src) && newnet != network)
+ if(newnet && usr in range(1, src))
if(length(newnet) > 15)
temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -"
@@ -154,11 +149,6 @@
A.anchored = 1
del(src)
else if(istype(D, /obj/item/weapon/card/emag) && !emagged)
- var/obj/item/weapon/card/emag/E = D
- if(E.uses)
- E.uses--
- else
- return
playsound(src.loc, 'sparks4.ogg', 75, 1)
emagged = 1
user << "\blue You you disable the security protocols"
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
new file mode 100644
index 0000000000..5f0ede226a
--- /dev/null
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -0,0 +1,233 @@
+
+
+
+
+/obj/machinery/computer/telecomms/traffic
+ name = "Telecommunications Traffic Control"
+ icon_state = "computer_generic"
+
+ var
+ screen = 0 // the screen number:
+ list/servers = list() // the servers located by the computer
+ mob/editingcode
+ list/viewingcode = list()
+ obj/machinery/telecomms/server/SelectedServer
+
+ network = "NULL" // the network to probe
+ temp = "" // temporary feedback messages
+
+ storedcode = "" // code stored
+
+
+ proc/update_ide()
+
+ // loop if there's someone manning the keyboard
+ while(editingcode)
+ if(!editingcode.client)
+ editingcode = null
+ break
+
+ // For the typer, the input is enabled. Buffer the typed text
+ if(editingcode)
+ storedcode = "[winget(editingcode, "tcscode", "text")]"
+ if(editingcode) // double if's to work around a runtime error
+ winset(editingcode, "tcscode", "is-disabled=false")
+
+ // If the player's not manning the keyboard anymore, adjust everything
+ if(!(editingcode in range(1, src)) || editingcode.machine != src)
+ if(editingcode)
+ winshow(editingcode, "Telecomms IDE", 0) // hide the window!
+ editingcode = null
+ break
+
+ // For other people viewing the typer type code, the input is disabled and they can only view the code
+ // (this is put in place so that there's not any magical shenanigans with 50 people inputting different code all at once)
+
+ if(length(viewingcode))
+ // This piece of code is very important - it escapes quotation marks so string aren't cut off by the input element
+ var/showcode = dd_replacetext(storedcode, "\\\"", "\\\\\"")
+ showcode = dd_replacetext(storedcode, "\"", "\\\"")
+
+ for(var/mob/M in viewingcode)
+ if(M.machine == src && M in view(1, src))
+ winset(M, "tcscode", "is-disabled=true")
+ winset(M, "tcscode", "text=\"[showcode]\"")
+ else
+ if(!issilicon(M))
+ viewingcode.Remove(M)
+ winshow(M, "Telecomms IDE", 0) // hide the window!
+
+ sleep(5)
+
+ if(length(viewingcode) > 0)
+ editingcode = pick(viewingcode)
+ viewingcode.Remove(editingcode)
+ update_ide()
+
+
+
+ req_access = list(access_tcomsat)
+
+ attack_hand(mob/user as mob)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ user.machine = src
+ var/dat = "Telecommunication Traffic ControlTelecommunications Traffic Control"
+
+ switch(screen)
+
+
+ // --- Main Menu ---
+
+ if(0)
+ dat += "
[temp]
"
+ dat += "
Current Network: [network]
"
+ if(servers.len)
+ dat += "
Detected Telecommunication Servers:"
+ for(var/obj/machinery/telecomms/T in servers)
+ dat += "- \ref[T] [T.name] ([T.id])
"
+ dat += "
"
+ dat += "
\[Flush Buffer\]"
+
+ else
+ dat += "
No servers detected. Scan for servers: \[Scan\]"
+
+
+ // --- Viewing Server ---
+
+ if(1)
+ dat += "
[temp]
"
+ dat += "\[Main Menu\] \[Refresh\]"
+ dat += "
Current Network: [network]"
+ dat += "
Selected Server: [SelectedServer.id]
"
+ dat += "
\[Edit Code\]"
+ dat += "
Signal Execution: "
+ if(SelectedServer.autoruncode)
+ dat += "ALWAYS"
+ else
+ dat += "NEVER"
+
+
+ user << browse(dat, "window=traffic_control;size=575x400")
+ onclose(user, "server_control")
+
+ temp = ""
+ return
+
+
+ Topic(href, href_list)
+ if(..())
+ return
+
+
+ add_fingerprint(usr)
+ usr.machine = src
+ if(!src.allowed(usr) && !emagged)
+ usr << "\red ACCESS DENIED."
+ return
+
+ if(href_list["viewserver"])
+ screen = 1
+ for(var/obj/machinery/telecomms/T in servers)
+ if(T.id == href_list["viewserver"])
+ SelectedServer = T
+ break
+
+ if(href_list["operation"])
+ switch(href_list["operation"])
+
+ if("release")
+ servers = list()
+ screen = 0
+
+ if("mainmenu")
+ screen = 0
+
+ if("scan")
+ if(servers.len > 0)
+ temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -"
+
+ else
+ for(var/obj/machinery/telecomms/server/T in range(25, src))
+ if(T.network == network)
+ servers.Add(T)
+
+ if(!servers.len)
+ temp = "- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -"
+ else
+ temp = "- [servers.len] SERVERS PROBED & BUFFERED -"
+
+ screen = 0
+
+ if("editcode")
+ if(!editingcode)
+ editingcode = usr
+ winshow(editingcode, "Telecomms IDE", 1) // show the IDE
+ winset(editingcode, "tcscode", "is-disabled=false")
+ var/showcode = dd_replacetext(storedcode, "\\\"", "\\\\\"")
+ showcode = dd_replacetext(storedcode, "\"", "\\\"")
+ winset(editingcode, "tcscode", "text=\"[showcode]\"")
+ spawn()
+ update_ide()
+
+ else
+ viewingcode.Add(usr)
+ winshow(usr, "Telecomms IDE", 1) // show the IDE
+ winset(usr, "tcscode", "is-disabled=true")
+ var/showcode = dd_replacetext(storedcode, "\"", "\\\"")
+ winset(usr, "tcscode", "text=\"[showcode]\"")
+
+ if("togglerun")
+ SelectedServer.autoruncode = !(SelectedServer.autoruncode)
+
+ if(href_list["network"])
+
+ var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text
+
+ if(newnet && usr in range(1, src))
+ if(length(newnet) > 15)
+ temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -"
+
+ else
+
+ network = newnet
+ screen = 0
+ machines = list()
+ temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -"
+
+ updateUsrDialog()
+ return
+
+ attackby(var/obj/item/weapon/D as obj, var/mob/user as mob)
+ if(istype(D, /obj/item/weapon/screwdriver))
+ playsound(src.loc, 'Screwdriver.ogg', 50, 1)
+ if(do_after(user, 20))
+ if (src.stat & BROKEN)
+ user << "\blue The broken glass falls out."
+ var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
+ new /obj/item/weapon/shard( src.loc )
+ var/obj/item/weapon/circuitboard/comm_server/M = new /obj/item/weapon/circuitboard/comm_server( A )
+ for (var/obj/C in src)
+ C.loc = src.loc
+ A.circuit = M
+ A.state = 3
+ A.icon_state = "3"
+ A.anchored = 1
+ del(src)
+ else
+ user << "\blue You disconnect the monitor."
+ var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
+ var/obj/item/weapon/circuitboard/comm_server/M = new /obj/item/weapon/circuitboard/comm_server( A )
+ for (var/obj/C in src)
+ C.loc = src.loc
+ A.circuit = M
+ A.state = 4
+ A.icon_state = "4"
+ A.anchored = 1
+ del(src)
+ else if(istype(D, /obj/item/weapon/card/emag) && !emagged)
+ playsound(src.loc, 'sparks4.ogg', 75, 1)
+ emagged = 1
+ user << "\blue You you disable the security protocols"
+ src.updateUsrDialog()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 7f35b5c268..1b0503a40a 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -213,13 +213,14 @@
return output
proc/remove_resources(var/obj/item/mecha_parts/part)
- for(var/resource in part.construction_cost)
- if(resource in src.resources)
- src.resources[resource] -= get_resource_cost_w_coeff(part,resource)
+ if(istype(part, /obj/item/mecha_parts/part))
+ for(var/resource in part.construction_cost)
+ if(resource in src.resources)
+ src.resources[resource] -= get_resource_cost_w_coeff(part,resource)
return
proc/check_resources(var/obj/item/mecha_parts/part)
- if(istype(part, /obj/item))
+ if(istype(part, /obj/item/mecha_parts/part))
for(var/resource in part.construction_cost)
if(resource in src.resources)
if(src.resources[resource] < get_resource_cost_w_coeff(part,resource))
diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm
index 340d32c847..4470eae3ad 100755
--- a/code/game/objects/devices/PDA/PDA.dm
+++ b/code/game/objects/devices/PDA/PDA.dm
@@ -176,12 +176,11 @@
dat += ""
@@ -577,7 +576,6 @@
difficulty += P.cartridge.access_engine
difficulty += P.cartridge.access_clown
difficulty += P.cartridge.access_janitor
- difficulty += P.cartridge.access_manifest * 2
else
difficulty += 2
diff --git a/code/game/objects/devices/PDA/cart.dm b/code/game/objects/devices/PDA/cart.dm
index b3e9698f6d..b356371dae 100644
--- a/code/game/objects/devices/PDA/cart.dm
+++ b/code/game/objects/devices/PDA/cart.dm
@@ -10,7 +10,6 @@
var/access_security = 0
var/access_engine = 0
var/access_medical = 0
- var/access_manifest = 1
var/access_clown = 0
var/access_mime = 0
var/access_janitor = 0
@@ -167,7 +166,6 @@
name = "Detomatix Cartridge"
icon_state = "cart"
access_remote_door = 1
- access_manifest = 0
remote_door_id = "syndicate" //Make sure this matches the syndicate shuttle's shield/door id!!
var/shock_charges = 4
diff --git a/code/game/objects/items/food.dm b/code/game/objects/items/food.dm
index 37d0b54cf0..8639893257 100644
--- a/code/game/objects/items/food.dm
+++ b/code/game/objects/items/food.dm
@@ -36,16 +36,17 @@ MONKEY CUBE BOX
/obj/item/kitchen/donut_box/MouseDrop(mob/user as mob)
if ((user == usr && (!( usr.restrained() ) && (!( usr.stat ) && (usr.contents.Find(src) || in_range(src, usr))))))
- if (usr.hand)
- if (!( usr.l_hand ))
- spawn( 0 )
- src.attack_hand(usr, 1, 1)
- return
- else
- if (!( usr.r_hand ))
- spawn( 0 )
- src.attack_hand(usr, 0, 1)
- return
+ if(ishuman(user))
+ if (usr.hand)
+ if (!( usr.l_hand ))
+ spawn( 0 )
+ src.attack_hand(usr, 1, 1)
+ return
+ else
+ if (!( usr.r_hand ))
+ spawn( 0 )
+ src.attack_hand(usr, 0, 1)
+ return
return
/obj/item/kitchen/donut_box/attack_paw(mob/user as mob)
diff --git a/code/game/objects/radio/electropack.dm b/code/game/objects/radio/electropack.dm
index 4f5b5d0763..512a8cd478 100644
--- a/code/game/objects/radio/electropack.dm
+++ b/code/game/objects/radio/electropack.dm
@@ -3,7 +3,6 @@
desc = "Dance my monkeys! DANCE!!!"
icon_state = "electropack0"
var/code = 2
- var/on = 0
var/e_pads = 0.0
g_amt = 2500
m_amt = 10000
diff --git a/code/game/objects/radio/encryptionkey.dm b/code/game/objects/radio/encryptionkey.dm
new file mode 100644
index 0000000000..2758ddf909
--- /dev/null
+++ b/code/game/objects/radio/encryptionkey.dm
@@ -0,0 +1,110 @@
+/obj/item/device/encryptionkey/
+ name = "Standard Encrpytion Key"
+ desc = "An encyption key for a radio headset. Has no special codes in it. WHY DOES IT EXIST? ASK NANOTRASEN."
+ icon = 'radio.dmi'
+ icon_state = "cypherkey"
+ item_state = ""
+ var/channels = list()
+ var/translate_hive = 0
+ var/translate_binary = 0
+
+/obj/item/device/encryptionkey/New()
+
+/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
+
+/obj/item/device/encryptionkey/traitor
+ channels = list("Syndicate" = 1)
+ origin_tech = "syndicate=3"
+
+/obj/item/device/encryptionkey/nuclear
+ channels = list("Nuclear" = 1)
+ origin_tech = "syndicate=3"
+
+/obj/item/device/encryptionkey/ert
+ name = "NanoTrasen ERT Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Mining" = 1, "Cargo" = 1,)
+
+/obj/item/device/encryptionkey/binary
+ translate_binary = 1
+ origin_tech = "syndicate=3"
+
+/obj/item/device/encryptionkey/headset_sec
+ name = "Security Radio Encryption Key"
+
+ channels = list("Security" = 1)
+
+/obj/item/device/encryptionkey/headset_eng
+ name = "Engineering Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Engineering" = 1)
+
+/obj/item/device/encryptionkey/headset_rob
+ name = "Robotics Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Engineering" = 1, "Science" = 1)
+
+/obj/item/device/encryptionkey/headset_med
+ name = "Medical Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Medical" = 1)
+
+/obj/item/device/encryptionkey/headset_sci
+ name = "Science Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Science" = 1)
+
+/obj/item/device/encryptionkey/headset_medsci
+ name = "Medical Research Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Medical" = 1, "Science" = 1)
+
+/obj/item/device/encryptionkey/headset_com
+ name = "Command Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Command" = 1)
+
+/obj/item/device/encryptionkey/heads/captain
+ name = "Captain's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Command" = 1, "Science" = 0, "Medical" = 0, "Security" = 1, "Engineering" = 0, "Mining" = 0, "Cargo" = 0)
+
+/obj/item/device/encryptionkey/heads/rd
+ name = "Research Director's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Science" = 1, "Command" = 1)
+
+/obj/item/device/encryptionkey/heads/hos
+ name = "Head of Security's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Security" = 1, "Command" = 1)
+
+/obj/item/device/encryptionkey/heads/ce
+ name = "Chief Engineer's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Engineering" = 1, "Command" = 1)
+
+/obj/item/device/encryptionkey/heads/cmo
+ name = "Chief Medical Officer's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Medical" = 1, "Command" = 1)
+
+/obj/item/device/encryptionkey/heads/hop
+ name = "Head of Personnel's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Command" = 1, "Security" = 0, "Cargo" = 1, "Mining" = 0)
+
+/obj/item/device/encryptionkey/headset_mine
+ name = "Mining Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Mining" = 1)
+
+/obj/item/device/encryptionkey/heads/qm
+ name = "Quartermaster's Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Cargo" = 1, "Mining" = 1)
+
+/obj/item/device/encryptionkey/headset_cargo
+ name = "Cargo Radio Encryption Key"
+ desc = "An encyption key for a radio headset. Contains cypherkeys."
+ channels = list("Cargo" = 1)
\ No newline at end of file
diff --git a/code/game/objects/radio/headset.dm b/code/game/objects/radio/headset.dm
index 233c256bb7..dfd8fd0869 100644
--- a/code/game/objects/radio/headset.dm
+++ b/code/game/objects/radio/headset.dm
@@ -6,127 +6,231 @@
g_amt = 0
m_amt = 75
subspace_transmission = 1
+ protective_temperature = 0
+ canhear_range = 1
var
translate_binary = 0
translate_hive = 0
+ obj/item/device/encryptionkey/keyslot1 = null
+ obj/item/device/encryptionkey/keyslot2 = null
+
+/obj/item/device/radio/headset/New()
+ ..()
+ keyslot1 = new /obj/item/device/encryptionkey
+ recalculateChannels()
/obj/item/device/radio/headset/traitor
- translate_binary = 1
- channels = list("Syndicate" = 1)
origin_tech = "syndicate=3"
+ canhear_range = 0
+
+ New()
+ ..()
+ del(keyslot1)
+ keyslot1 = new /obj/item/device/encryptionkey/traitor
+
+/obj/item/device/radio/headset/binary
+ origin_tech = "syndicate=3"
+ canhear_range = 0
+
+ New()
+ ..()
+ del(keyslot1)
+ keyslot1 = new /obj/item/device/encryptionkey/binary
/obj/item/device/radio/headset/headset_sec
name = "Security Radio Headset"
desc = "This is used by your elite security force. To access the security channel, use :s."
icon_state = "sec_headset"
item_state = "headset"
- channels = list("Security" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_sec
/obj/item/device/radio/headset/headset_eng
name = "Engineering Radio Headset"
desc = "When the engineers wish to chat like girls. To access the engineering channel, use :e. "
icon_state = "eng_headset"
item_state = "headset"
- channels = list("Engineering" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_rob
name = "Robotics Radio Headset"
desc = "Made specifically for the roboticists who cannot decide between departments. To access the engineering channel, use :e. For research, use :n."
icon_state = "rob_headset"
item_state = "headset"
- channels = list("Engineering" = 1, "Science" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_rob
/obj/item/device/radio/headset/headset_med
name = "Medical Radio Headset"
desc = "A headset for the trained staff of the medbay. To access the medical channel, use :m."
icon_state = "med_headset"
item_state = "headset"
- channels = list("Medical" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sci
name = "Science Radio Headset"
desc = "A sciency headset. Like usual. To access the science channel, use :n."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Science" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_sci
/obj/item/device/radio/headset/headset_medsci
name = "Medical Research Radio Headset"
desc = "A headset that is a result of the mating between medical and science. To access the medical channel, use :m. For science, use :n."
icon_state = "med_headset"
item_state = "headset"
- channels = list("Medical" = 1, "Science" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_medsci
/obj/item/device/radio/headset/headset_com
name = "Command Radio Headset"
desc = "A headset with a commanding channel. To access the command channel, use :c."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Command" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/headset_com
/obj/item/device/radio/headset/heads/captain
name = "Captain's Headset"
desc = "The headset of the boss. Channels are as follows: :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Command" = 1, "Science" = 0, "Medical" = 0, "Security" = 1, "Engineering" = 0, "Mining" = 0, "Cargo" = 0)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/rd
name = "Research Director's Headset"
desc = "Headset of the researching God. To access the science channel, use :n. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Science" = 1, "Command" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/rd
/obj/item/device/radio/headset/heads/hos
name = "Head of Security's Headset"
desc = "The headset of the man who protects your worthless lifes. To access the security channel, use :s. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Security" = 1, "Command" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/heads/ce
name = "Chief Engineer's Headset"
desc = "The headset of the guy who is in charge of morons. To access the engineering channel, use :e. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Engineering" = 1, "Command" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/ce
/obj/item/device/radio/headset/heads/cmo
name = "Chief Medical Officer's Headset"
desc = "The headset of the highly trained medical chief. To access the medical channel, use :m. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Medical" = 1, "Command" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/cmo
/obj/item/device/radio/headset/heads/hop
name = "Head of Personnel's Headset"
desc = "The headset of the guy who will one day be captain. Channels are as follows: :c - command, :s - security, :q - cargo, :d - mining."
icon_state = "com_headset"
item_state = "headset"
- channels = list("Command" = 1, "Security" = 0, "Cargo" = 1, "Mining" = 0)
-
+ keyslot2 = new /obj/item/device/encryptionkey/heads/hop
/obj/item/device/radio/headset/headset_mine
name = "Mining Radio Headset"
desc = "Headset used by miners. How useless. To access the mining channel, use :d."
icon_state = "mine_headset"
item_state = "headset"
- channels = list("Mining" = 1)
-
-
+ keyslot2 = new /obj/item/device/encryptionkey/headset_mine
/obj/item/device/radio/headset/heads/qm
name = "Quartermaster's Headset"
desc = "The headset of the man who control your toiletpaper supply. To access the cargo channel, use :q. For mining, use :d."
icon_state = "cargo_headset"
item_state = "headset"
- channels = list("Cargo" = 1, "Mining" = 1)
+ keyslot2 = new /obj/item/device/encryptionkey/heads/qm
+/obj/item/device/radio/headset/nuclear
+ freerange = 1
+ listening = 0
+ keyslot2 = new /obj/item/device/encryptionkey/nuclear
+
+/obj/item/device/radio/headset/ert
+ name = "CentCom Response Team headset"
+ desc = "The headset of the boss's boss. Channels are as follows: :h - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
+ freerange = 1
+ keyslot2 = new /obj/item/device/encryptionkey/ert
/obj/item/device/radio/headset/headset_cargo
name = "Cargo Radio Headset"
desc = "Headset used by the QM's slaves. To access the cargo channel, use :q."
icon_state = "cargo_headset"
item_state = "headset"
- channels = list("Cargo" = 1)
\ No newline at end of file
+ keyslot2 = new /obj/item/device/encryptionkey/headset_cargo
+
+/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
+// ..()
+ user.machine = src
+ if (!istype(W, /obj/item/weapon/screwdriver) && !istype(W, /obj/item/device/encryptionkey/))
+ return
+
+ if(istype(W, /obj/item/weapon/screwdriver))
+ if(keyslot1 || keyslot2)
+
+ if(keyslot1)
+ user.put_in_hands(keyslot1)
+
+ if(keyslot2)
+ user.put_in_hands(keyslot2)
+
+ recalculateChannels()
+ user << "You pop out the encryption keys in the headset!"
+
+ else
+ user << "This headset doesn't have any encryption keys! How useless..."
+
+ if(istype(W, /obj/item/device/encryptionkey/))
+ if(keyslot1 && keyslot2)
+ user << "The headset can't hold another key!"
+ return
+
+ if(!keyslot1)
+ user.drop_item()
+ W.loc = src
+ keyslot1 = W
+
+ else
+ user.drop_item()
+ W.loc = src
+ keyslot2 = W
+
+ recalculateChannels()
+ return
+
+
+/obj/item/device/radio/headset/proc/recalculateChannels()
+ src.channels = list()
+ src.translate_binary = 0
+ src.translate_hive = 0
+ var/temp_channels = list()
+
+ if(keyslot1)
+ temp_channels += keyslot1.channels
+
+ if(keyslot1.translate_binary)
+ src.translate_binary = 1
+
+ if(keyslot1.translate_hive)
+ src.translate_hive = 1
+
+ if(keyslot2)
+ temp_channels += keyslot2.channels
+
+ if(keyslot2.translate_binary)
+ src.translate_binary = 1
+
+ if(keyslot2.translate_hive)
+ src.translate_hive = 1
+
+ config(temp_channels)
+
+ for (var/ch_name in channels)
+ if(!radio_controller)
+ sleep(30) // Waiting for the radio_controller to be created.
+ if(!radio_controller)
+ src.name = "Broken Radio Headset"
+ return
+
+ return
\ No newline at end of file
diff --git a/code/game/objects/radio/radio.dm b/code/game/objects/radio/radio.dm
index ed3bbe0d64..e183ff2d46 100644
--- a/code/game/objects/radio/radio.dm
+++ b/code/game/objects/radio/radio.dm
@@ -10,9 +10,11 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
icon_state = "walkietalkie"
item_state = "walkietalkie"
var
+ on = 1 // 0 for off
last_transmission
frequency = 1459 //common chat
traitor_frequency = 0 //tune to frequency to unlock traitor supplies
+ canhear_range = 3
obj/item/device/radio/patch_link = null
obj/item/device/uplink/radio/traitorradio = null
wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT
@@ -55,6 +57,11 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if(radio_controller)
initialize()
+ // If intercom: do a local power check loop
+ if(istype(src, /obj/item/device/radio/intercom))
+ spawn(5)
+ checkpower()
+
/obj/item/device/radio/initialize()
if(freerange)
if(frequency < 1200 || frequency > 1600)
@@ -74,6 +81,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
interact(user)
/obj/item/device/radio/proc/interact(mob/user as mob)
+ if(!on)
+ return
+
var/dat = {"
[src]
Microphone: [broadcasting ? "Engaged" : "Disengaged"]
@@ -111,9 +121,29 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
Speaker: [list ? "Engaged" : "Disengaged"]
"}
+/obj/item/device/radio/proc/checkpower()
+
+ // Simple loop, checks for power. Strictly for intercoms
+ while(src)
+
+ if(!src.loc)
+ on = 0
+ var/area/A = src.loc.loc
+ if(!A || !isarea(A) || !A.master)
+ on = 0
+ else
+ on = A.master.powered(EQUIP) // set "on" to the power status
+
+ if(!on)
+ icon_state = "intercom-p"
+ else
+ icon_state = "intercom"
+
+ sleep(30)
+
/obj/item/device/radio/Topic(href, href_list)
//..()
- if (usr.stat)
+ if (usr.stat || !on)
return
if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
usr << browse(null, "window=radio")
@@ -125,6 +155,21 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if(A && target)
A.ai_actual_track(target)
return
+ else if (href_list["faketrack"])
+ var/mob/target = locate(href_list["track"])
+ var/mob/living/silicon/ai/A = locate(href_list["track2"])
+ if(A && target)
+
+ A:cameraFollow = target
+ A << text("Now tracking [] on camera.", target.name)
+ if (usr.machine == null)
+ usr.machine = usr
+
+ while (usr:cameraFollow == target)
+ usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
+ sleep(40)
+ continue
+ return
else if (href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if (!freerange || (frequency < 1200 || frequency > 1600))
@@ -195,6 +240,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
channel = null
if (!istype(connection))
return
+ if (!connection)
+ return
if(subspace_transmission)
// First, we want to generate a new radio signal
@@ -299,6 +346,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
return
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
+ if(!on) return // the device has to be on
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
@@ -325,6 +373,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
channel = null
if (!istype(connection))
return
+ if (!connection)
+ return
@@ -407,7 +457,10 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
"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
+ "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
)
signal.frequency = connection.frequency // Quick frequency set
@@ -455,7 +508,10 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0,
- "traffic" = 0
+ "traffic" = 0,
+ "type" = 0,
+ "server" = null,
+ "reject" = 0
)
signal.frequency = connection.frequency // Quick frequency set
@@ -466,7 +522,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
sleep(rand(10,25)) // wait a little...
if(signal.data["done"])
- del(signal) // delete the signal - we're done here.
+ //we're done here.
return
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
@@ -491,6 +547,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
channel = null
if (!istype(connection))
return
+ if (!connection)
+ return
var/display_freq = connection.frequency
//world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
@@ -681,6 +739,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
*/
if (!(wires & WIRE_RECEIVE))
return
+ if (!on)
+ return
if (!freq) //recieved on main frequency
if (!listening)
return
@@ -714,7 +774,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
/* Instead, let's individually search potential containers for mobs! More verbose but a LOT more efficient and less laggy */
// Check gamehelpers.dm for the proc definition:
- return get_mobs_in_view(1, src)
+ return get_mobs_in_view(canhear_range, src)
/obj/item/device/radio/examine()
set src in view()
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index f9238d5f67..b6dfc498cc 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -194,12 +194,7 @@ proc/trigger_armed_response_team()
/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0)
//Special radio setup
- var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src)
- R.name = "CentCom Response Team headset"
- R.desc = "The headset of the boss's boss. Channels are as follows: :h - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
- R.freerange = 1
- R.config(list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Mining" = 1, "Cargo" = 1,))
- equip_if_possible(R, slot_ears)
+ equip_if_possible(new /obj/item/device/radio/headset/ert, slot_ears)
//Adding Camera Network
var/obj/machinery/camera/camera = new /obj/machinery/camera(src) //Gives all the commandos internals cameras.
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 9a67475901..41c9033eae 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -63,9 +63,9 @@ client/verb/Toggle_Soundscape()
set name = "Toggle Ambience"
usr:client:no_ambi = !usr:client:no_ambi
if(usr:client:no_ambi)
- usr << sound('shipambience.ogg', repeat = 0, wait = 0, volume = 0, channel = 2)
+ usr << sound(pick('shipambience.ogg'), repeat = 0, wait = 0, volume = 0, channel = 2)
else
- usr << sound('shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
+ usr << sound(pick('shipambience.ogg'), repeat = 1, wait = 0, volume = 35, channel = 2)
usr << "Toggled ambience sound."
return
diff --git a/code/game/turf.dm b/code/game/turf.dm
index 73e2545a90..cbc7ced6b5 100644
--- a/code/game/turf.dm
+++ b/code/game/turf.dm
@@ -457,6 +457,9 @@
usr << "\red You don't have the dexterity to do this!"
return
+ if(!istype(src, /turf/simulated/wall/r_wall))
+ return // this may seem stupid and redundant but apparently floors can call this attackby() proc, it was spamming shit up. -- Doohl
+
if (istype(W, /obj/item/weapon/weldingtool) && W:welding)
W:eyecheck(user)
var/turf/T = user.loc
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 8ba9a6c4bc..81c9f08185 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -2556,6 +2556,7 @@
if (!M.mind)
usr << "Sorry, this mob has no mind!"
+ return
M.mind.edit_memory()
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 3ccc5ff58b..879502d8d3 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -92,8 +92,7 @@
PP |
VV |
SM |
- JMP |
- CA
+ JMP
[muting]
Warn | Boot | Ban | Jobban
"}
diff --git a/code/modules/chemical/Chemistry-Tools.dm b/code/modules/chemical/Chemistry-Tools.dm
index 72e929e5bf..c3534158bb 100644
--- a/code/modules/chemical/Chemistry-Tools.dm
+++ b/code/modules/chemical/Chemistry-Tools.dm
@@ -534,15 +534,16 @@
if(D.loc == trg) break
step_towards(D,trg)
- for(var/mob/living/carbon/M in D.loc)
- if(!istype(M,/mob/living/carbon)) continue
- if(M == user) continue
- D.reagents.trans_to(M, 15)
- M.take_organ_damage(5)
- for(var/mob/O in viewers(world.view, D))
- O.show_message(text("\red [] was hit by the syringe!", M), 1)
+ if(D)
+ for(var/mob/living/carbon/M in D.loc)
+ if(!istype(M,/mob/living/carbon)) continue
+ if(M == user) continue
+ D.reagents.trans_to(M, 15)
+ M.take_organ_damage(5)
+ for(var/mob/O in viewers(world.view, D))
+ O.show_message(text("\red [] was hit by the syringe!", M), 1)
- del(D)
+ del(D)
if(D)
for(var/atom/A in D.loc)
if(A == user) continue
diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm
index 682b11dd7b..06407c5f56 100755
--- a/code/modules/mob/living/silicon/ai/laws.dm
+++ b/code/modules/mob/living/silicon/ai/laws.dm
@@ -108,10 +108,11 @@
var/law = src.laws.supplied[index]
if (length(law) > 0)
- if (src.lawcheck[number+1] == "Yes")
- src.say("[number]. [law]")
- sleep(10)
- number++
+ if(src.lawcheck.len >= number+1)
+ if (src.lawcheck[number+1] == "Yes")
+ src.say("[number]. [law]")
+ sleep(10)
+ number++
/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index 53577373c0..fa8ae87b1f 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -85,9 +85,8 @@
var/rendered = "Robotic Talk, [name] [message_a]"
for (var/mob/living/S in world)
if(!S.stat)
- if(S.robot_talk_understand)
- if(S.robot_talk_understand == robot_talk_understand)
- S.show_message(rendered, 2)
+ if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand))
+ S.show_message(rendered, 2)
else if (S.binarycheck())
S.show_message(rendered, 2)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index fb62e404f0..91d67ca4fd 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -614,7 +614,7 @@
//This should have a check to prevent the player to player chat but I am too tired atm to add it.
var/t = input("Message:", text("Private message to [recipient_name]")) as text|null
- if (!t || !usr || !M)
+ if (!t || !usr || !usr.client)
return
if (usr.client && usr.client.holder)
M << "\red Admin PM from-[key_name(usr, M, 0)]: [t]"
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 57338de3d7..dd5b75e323 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -321,3 +321,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return 0
+/mob/proc/put_in_hands(var/obj/item/I)
+ if(!r_hand)
+ I.loc = src
+ r_hand = I
+ I.layer = 20
+ else if(!l_hand)
+ I.loc = src
+ l_hand = I
+ I.layer = 20
+ else
+ I.loc = get_turf(src)
+ update_clothing()
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index cf605048c7..9c0ea592f2 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -55,8 +55,8 @@
if(istype(I, /obj/item/weapon/trashbag))
user << "\blue You empty the bag."
for(var/obj/item/O in I.contents)
- I.contents -= O
O.loc = src
+ I.contents -= O
I.update_icon()
update()
return
@@ -101,8 +101,9 @@
return // No idea why, but somehow I gets nulled before it goes into the else, and that leads to a lot of spam with runtime errors.
user.drop_item()
+ if(I)
+ I.loc = src
- I.loc = src
user << "You place \the [I] into the [src]."
for(var/mob/M in viewers(src))
if(M == user)
@@ -305,6 +306,7 @@
for(var/atom/movable/AM in src)
AM.loc = src.loc
AM.pipe_eject(0)
+ islarge = 0
update()
// update the icon & overlays to reflect mode & status
diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm
index fac5a52f29..d9f6e2ee85 100644
--- a/code/modules/scripting/Implementations/Telecomms.dm
+++ b/code/modules/scripting/Implementations/Telecomms.dm
@@ -41,8 +41,8 @@
program.SetVar("PI" , 3.141592653) // value of pi
program.SetVar("E" , 2.718281828) // value of e
program.SetVar("SQURT2" , 1.414213562) // value of the square root of 2
- program.SetVar("false" , 0) // boolean shortcut to 0
- program.SetVar("true" , 1) // boolean shortcut to 1
+ program.SetVar("FALSE" , 0) // boolean shortcut to 0
+ program.SetVar("TRUE" , 1) // boolean shortcut to 1
program.SetVar("NORTH" , NORTH) // NORTH (1)
program.SetVar("SOUTH" , SOUTH) // SOUTH (2)
@@ -63,8 +63,6 @@
if(!ready)
return
- world << "sucessful run!"
-
interpreter.SetVar("$content", signal.data["message"])
interpreter.SetVar("$freq" , signal.frequency)
interpreter.SetVar("$source" , signal.data["name"])
@@ -148,14 +146,13 @@
interpreter.SetProc("pick", /proc/n_pick)
interpreter.SetProc("prob", /proc/prob_chance)
+ interpreter.SetProc("substr", /proc/docopytext)
// Run the compiled code
interpreter.Run()
- world << "interpreter.Run() complete."
-
// Backwards-apply variables onto signal data
/* html_encode() EVERYTHING. fucking players can't be trusted with SHIT */
@@ -175,13 +172,6 @@
signal.data["job"] = html_encode(interpreter.GetVar("$job"))
signal.data["reject"] = !(interpreter.GetVar("$pass")) // set reject to the opposite of $pass
- world << "message: [interpreter.GetVar("$content")]"
- world << "freq: [interpreter.GetVar("$freq")]"
- world << "name: [setname]"
- world << "job: [interpreter.GetVar("$job")]"
- world << "pass: [interpreter.GetVar("$pass")]"
-
-
/* -- Actual language proc code -- */
@@ -201,10 +191,6 @@ datum/signal
proc/tcombroadcast(var/message, var/freq, var/source, var/job)
- world << message
- world << freq
- world << source
- world << job
var/mob/living/carbon/human/H = new
var/datum/signal/newsign = new
var/obj/machinery/telecomms/server/S = data["server"]
@@ -238,16 +224,10 @@ datum/signal
var/datum/radio_frequency/connection = radio_controller.return_frequency(freq)
newsign.data["connection"] = connection
- // This is a really hacky way of finding a source radio - but it works, i suppose.
+ // The radio is a radio headset!
if(!hradio)
- for(var/obj/item/device/radio/headset/r in world)
- hradio = r
- break
-
- // There are no radios in the world! Oh no! Just make a new one and pray to baby jesus
- if(!hradio)
- hradio = new
+ hradio = new /obj/item/device/radio/headset
newsign.data["radio"] = hradio
newsign.data["vmessage"] = H.voice_message
diff --git a/code/modules/scripting/Implementations/_Logic.dm b/code/modules/scripting/Implementations/_Logic.dm
index aca6ed2110..e6ae13fded 100644
--- a/code/modules/scripting/Implementations/_Logic.dm
+++ b/code/modules/scripting/Implementations/_Logic.dm
@@ -78,7 +78,8 @@
// Clone of list.Swap()
/proc/n_listswap(var/list/L, var/firstindex, var/secondindex)
if(!istype(L, /list)) return
- return L.Swap(firstindex, secondindex)
+ if(L.len >= secondindex && L.len >= firstindex)
+ return L.Swap(firstindex, secondindex)
// Clone of list.Insert()
/proc/n_listinsert(var/list/L, var/index, var/element)
@@ -100,12 +101,20 @@
if(haystack && needle)
if(isobject(haystack))
if(istype(haystack, /list))
- var/list/listhaystack = haystack
- return listhaystack.Find(needle, start, end)
+ if(length(haystack) >= end && start > 0)
+ var/list/listhaystack = haystack
+ return listhaystack.Find(needle, start, end)
else
if(istext(haystack))
- return findtext(haystack, needle, start, end)
+ if(length(haystack) >= end && start > 0)
+ return findtext(haystack, needle, start, end)
+
+// Clone of copytext()
+/proc/docopytext(var/string, var/start = 1, var/end = 0)
+ if(istext(string) && isnum(start) && isnum(end))
+ if(length(string) >= end && start > 0)
+ return copytext(string, start, end)
// Clone of length()
/proc/smartlength(var/container)
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index ac9864fe2d..857fe21d01 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/obj/radio.dmi b/icons/obj/radio.dmi
index d066b144ab..69180436a7 100644
Binary files a/icons/obj/radio.dmi and b/icons/obj/radio.dmi differ
diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi
index 3095c50375..913295eaf6 100755
Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 0a20c2a156..adab69791f 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -136,6 +136,8 @@ macro "macro"
command = "asay"
is-disabled = false
+macro "tcside"
+
macro "vending"
elem
name = "NORTHEAST"
@@ -290,6 +292,208 @@ menu "menu"
is-disabled = false
saved-params = "is-checked"
+window "Telecomms IDE"
+ elem "Telecomms IDE"
+ type = MAIN
+ pos = 281,0
+ size = 652x582
+ anchor1 = none
+ anchor2 = none
+ font-family = ""
+ font-size = 0
+ font-style = ""
+ text-color = #000000
+ background-color = #ffffff
+ is-visible = false
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "pos;size;is-minimized;is-maximized"
+ on-size = ""
+ title = "TCS IDE"
+ titlebar = true
+ statusbar = false
+ can-close = true
+ can-minimize = true
+ can-resize = true
+ is-pane = false
+ is-minimized = false
+ is-maximized = false
+ can-scroll = none
+ icon = ""
+ image = ""
+ image-mode = stretch
+ keep-aspect = false
+ transparent-color = none
+ alpha = 255
+ macro = ""
+ menu = ""
+ on-close = "exittcs"
+ elem "button4"
+ type = BUTTON
+ pos = 180,464
+ size = 60x20
+ anchor1 = none
+ anchor2 = none
+ font-family = ""
+ font-size = 0
+ font-style = ""
+ text-color = #000000
+ background-color = none
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "is-checked"
+ on-size = ""
+ text = "Revert"
+ image = ""
+ command = "tcsrevert"
+ is-flat = false
+ stretch = false
+ is-checked = false
+ group = ""
+ button-type = pushbutton
+ elem "button3"
+ type = BUTTON
+ pos = 120,464
+ size = 60x20
+ anchor1 = none
+ anchor2 = none
+ font-family = ""
+ font-size = 0
+ font-style = ""
+ text-color = #000000
+ background-color = none
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "is-checked"
+ on-size = ""
+ text = "Execute"
+ image = ""
+ command = "tcsrun"
+ is-flat = false
+ stretch = false
+ is-checked = false
+ group = ""
+ button-type = pushbutton
+ elem "tcserror"
+ type = OUTPUT
+ pos = 0,488
+ size = 648x94
+ anchor1 = none
+ anchor2 = none
+ font-family = "sans-serif"
+ font-size = 9
+ font-style = ""
+ text-color = #000000
+ background-color = #ffffff
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "max-lines"
+ on-size = ""
+ link-color = #0000ff
+ visited-color = #ff00ff
+ style = ""
+ enable-http-images = false
+ max-lines = 1000
+ image = ""
+ elem "button2"
+ type = BUTTON
+ pos = 60,464
+ size = 60x20
+ anchor1 = none
+ anchor2 = none
+ font-family = ""
+ font-size = 0
+ font-style = ""
+ text-color = #000000
+ background-color = none
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "is-checked"
+ on-size = ""
+ text = "Compile"
+ image = ""
+ command = "tcscompile"
+ is-flat = false
+ stretch = false
+ is-checked = false
+ group = ""
+ button-type = pushbutton
+ elem "button1"
+ type = BUTTON
+ pos = 0,464
+ size = 60x20
+ anchor1 = none
+ anchor2 = none
+ font-family = ""
+ font-size = 0
+ font-style = ""
+ text-color = #000000
+ background-color = none
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = "is-checked"
+ on-size = ""
+ text = "Apply"
+ image = ""
+ command = "tcssave"
+ is-flat = false
+ stretch = false
+ is-checked = false
+ group = ""
+ button-type = pushbutton
+ elem "tcscode"
+ type = INPUT
+ pos = 0,0
+ size = 652x464
+ anchor1 = none
+ anchor2 = none
+ font-family = "Courier"
+ font-size = 10
+ font-style = ""
+ text-color = #000000
+ background-color = #ffffff
+ is-visible = true
+ is-disabled = false
+ is-transparent = false
+ is-default = false
+ border = none
+ drop-zone = false
+ right-click = false
+ saved-params = ""
+ on-size = ""
+ command = "cancel"
+ multi-line = true
+ is-password = false
+ no-command = true
window "chemdispenser"
elem "chemdispenser"
diff --git a/maps/tgstation.2.0.8.dmm b/maps/tgstation.2.0.8.dmm
index e728b7f120..8e0ce36ac4 100755
--- a/maps/tgstation.2.0.8.dmm
+++ b/maps/tgstation.2.0.8.dmm
@@ -3966,7 +3966,7 @@
"byn" = (/obj/structure/reagent_dispensers/watertank,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor/plating,/area/maintenance/asmaint)
"byo" = (/obj/machinery/atmospherics/pipe/manifold{color = "blue"; icon_state = "manifold-b-f"; level = 1; name = "pipe manifold"},/turf/simulated/wall,/area/maintenance/asmaint)
"byp" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor/plating,/area/maintenance/asmaint)
-"byq" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 10},/obj/structure/disposalpipe/segment,/obj/effect/decal/cleanable/blood/splatter{icon_state = "floor2"},/turf/simulated/floor/plating,/area/maintenance/asmaint)
+"byq" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 10},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/asmaint)
"byr" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/structure/disposalpipe/segment{dir = 1},/turf/simulated/floor/plating,/area/maintenance/maintcentral)
"bys" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/wall,/area/medical/cryo)
"byt" = (/turf/simulated/wall,/area/medical/cryo)