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 Control
      Telecommunications 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)