From d9b8b146c8fd4447c0a3bc36f0c28f05122cc0de Mon Sep 17 00:00:00 2001 From: kingofkosmos Date: Fri, 24 Apr 2015 21:52:36 +0300 Subject: [PATCH] Tried to fix merge conflicts, hopefully worked. --- code/game/machinery/telecomms/broadcaster.dm | 572 +++++++++++ code/game/machinery/telecomms/logbrowser.dm | 232 +++++ code/game/machinery/telecomms/presets.dm | 187 ++++ code/game/machinery/telecomms/telemonitor.dm | 136 +++ .../machinery/telecomms/traffic_control.dm | 290 ++++++ code/game/objects/items/toys.dm | 33 +- .../closets/secure/secure_closets.dm | 7 - .../reagents/Chemistry-Goon-420BlazeIt.dm | 373 +++++++ .../reagents/Chemistry-Goon-Medicine.dm | 831 +++++++++++++++ code/modules/reagents/Chemistry-Goon-Other.dm | 286 ++++++ .../reagents/Chemistry-Goon-Pyrotechnics.dm | 486 +++++++++ .../modules/reagents/Chemistry-Goon-Readme.dm | 34 + .../modules/reagents/Chemistry-Goon-Toxins.dm | 369 +++++++ .../Chemistry-Reagents/Chemistry-Reagents.dm | 956 ++++++++++++++++++ .../Chemistry-Reagents/Drug-Reagents.dm | 1 - code/modules/reagents/grenade_launcher.dm | 61 ++ code/modules/reagents/syringe_gun.dm | 77 ++ 17 files changed, 4905 insertions(+), 26 deletions(-) create mode 100644 code/game/machinery/telecomms/broadcaster.dm create mode 100644 code/game/machinery/telecomms/logbrowser.dm create mode 100644 code/game/machinery/telecomms/presets.dm create mode 100644 code/game/machinery/telecomms/telemonitor.dm create mode 100644 code/game/machinery/telecomms/traffic_control.dm create mode 100644 code/modules/reagents/Chemistry-Goon-420BlazeIt.dm create mode 100644 code/modules/reagents/Chemistry-Goon-Medicine.dm create mode 100644 code/modules/reagents/Chemistry-Goon-Other.dm create mode 100644 code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm create mode 100644 code/modules/reagents/Chemistry-Goon-Readme.dm create mode 100644 code/modules/reagents/Chemistry-Goon-Toxins.dm create mode 100644 code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents.dm create mode 100644 code/modules/reagents/grenade_launcher.dm create mode 100644 code/modules/reagents/syringe_gun.dm diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm new file mode 100644 index 00000000000..064361f2614 --- /dev/null +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -0,0 +1,572 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/* + The broadcaster sends processed messages to all radio devices in the game. They + do not have to be headsets; intercoms and station-bounced radios suffice. + + They receive their message from a server after the message has been logged. +*/ + +var/list/recentmessages = list() // global list of recent messages broadcasted : used to circumvent massive radio spam +var/message_delay = 0 // To make sure restarting the recentmessages list is kept in sync + +/obj/machinery/telecomms/broadcaster + name = "subspace broadcaster" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "broadcaster" + desc = "A dish-shaped machine used to broadcast processed subspace signals." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 25 + machinetype = 5 + /*heatgen = 0 + delay = 7*/ + circuitboard = "/obj/item/weapon/circuitboard/telecomms/broadcaster" + +/obj/machinery/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"]) + + + // Prevents massive radio spam + signal.data["done"] = 1 // mark the signal as being broadcasted + // Search for the original signal and mark it as done as well + var/datum/signal/original = signal.data["original"] + if(original) + original.data["done"] = 1 + original.data["compression"] = signal.data["compression"] + original.data["level"] = signal.data["level"] + + var/signal_message = "[signal.frequency]:[signal.data["message"]]:[signal.data["realname"]]" + if(signal_message in recentmessages) + return + recentmessages.Add(signal_message) + + if(signal.data["slow"] > 0) + sleep(signal.data["slow"]) // simulate the network lag if necessary + + signal.data["level"] |= listening_level + + /** #### - Normal Broadcast - #### **/ + + if(signal.data["type"] == 0) + + /* ###### Broadcast a message using signal.data ###### */ + Broadcast_Message(signal.data["mob"], + signal.data["vmask"], signal.data["radio"], + signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], + 0, signal.data["compression"], signal.data["level"], signal.frequency, signal.data["spans"], + signal.data["verb_say"], signal.data["verb_ask"], signal.data["verb_exclaim"], signal.data["verb_yell"]) + + + /** #### - 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"], listening_level) + + + /** #### - 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["mob"], + signal.data["vmask"], + signal.data["radio"], signal.data["message"], + signal.data["name"], signal.data["job"], + signal.data["realname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, signal.data["spans"], + signal.data["verb_say"], signal.data["verb_ask"], signal.data["verb_exclaim"], signal.data["verb_yell"]) + + if(!message_delay) + message_delay = 1 + spawn(10) + message_delay = 0 + recentmessages = list() + + /* --- Do a snazzy animation! --- */ + flick("broadcaster_send", src) + +/obj/machinery/telecomms/broadcaster/Destroy() + // In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore. + if(message_delay) + message_delay = 0 + ..() + + +/* + Basically just an empty shell for receiving and broadcasting radio messages. Not + very flexible, but it gets the job done. +*/ + +/obj/machinery/telecomms/allinone + name = "telecommunications mainframe" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "comm_server" + desc = "A compact machine used for portable subspace telecommuniations processing." + density = 1 + anchored = 1 + use_power = 0 + idle_power_usage = 0 + machinetype = 6 + //heatgen = 0 + var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel + +/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal) + + if(!on) // has to be on to receive messages + return + + if(is_freq_listening(signal)) // detect subspace signals + + signal.data["done"] = 1 // mark the signal as being broadcasted + signal.data["compression"] = 0 + + // Search for the original signal and mark it as done as well + var/datum/signal/original = signal.data["original"] + if(original) + original.data["done"] = 1 + + if(signal.data["slow"] > 0) + sleep(signal.data["slow"]) // simulate the network lag if necessary + + /* ###### Broadcast a message using signal.data ###### */ + if(signal.frequency == SYND_FREQ) // if syndicate broadcast, just + Broadcast_Message(signal.data["mob"], + signal.data["vmask"], + signal.data["radio"], signal.data["message"], + signal.data["name"], signal.data["job"], + signal.data["realname"],, signal.data["compression"], list(0, z), signal.frequency, signal.data["spans"], + signal.data["verb_say"], signal.data["verb_ask"], signal.data["verb_exclaim"], signal.data["verb_yell"]) + + +/** + + Here is the big, bad function that broadcasts a message given the appropriate + parameters. + + @param M: + Reference to the mob/speaker, stored in signal.data["mob"] + + @param vmask: + Boolean value if the mob is "hiding" its identity via voice mask, stored in + signal.data["vmask"] + + @param vmessage: + If specified, will display this as the message; such as "chimpering" + for monkeys if the mob is not understood. Stored in signal.data["vmessage"]. + + @param radio: + Reference to the radio broadcasting the message, stored in signal.data["radio"] + + @param message: + The actual string message to display to mobs who understood mob M. Stored in + signal.data["message"] + + @param name: + The name to display when a mob receives the message. signal.data["name"] + + @param job: + The name job to display for the AI when it receives the message. signal.data["job"] + + @param realname: + The "real" name associated with the mob. signal.data["realname"] + + @param vname: + If specified, will use this name when mob M is not understood. signal.data["vname"] + + @param data: + If specified: + 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 + If nonzero, the signal may be partially inaudible or just complete gibberish. + + @param level: + The list of Z levels that the sending radio is broadcasting to. Having 0 in the list broadcasts on all levels + + @param freq + The frequency of the signal + +**/ + + +/proc/Broadcast_Message(var/atom/movable/AM, + var/vmask, var/obj/item/device/radio/radio, + var/message, var/name, var/job, var/realname, + var/data, var/compression, var/list/level, var/freq, var/list/spans, + var/verb_say, var/verb_ask, var/verb_exclaim, var/verb_yell) + + message = copytext(message, 1, MAX_BROADCAST_LEN) + + if(!message) + return + + var/list/radios = list() + + var/atom/movable/virtualspeaker/virt = PoolOrNew(/atom/movable/virtualspeaker,null) + virt.name = name + virt.job = job + virt.languages = AM.languages + virt.source = AM + virt.faketrack = data == 4 ? 1 : 0 + virt.radio = radio + virt.verb_say = verb_say + virt.verb_ask = verb_ask + virt.verb_exclaim = verb_exclaim + virt.verb_yell = verb_yell + + if(compression > 0) + message = Gibberish(message, compression + 40) + + // --- Broadcast only to intercom devices --- + + if(data == 1) + for(var/obj/item/device/radio/intercom/R in all_radios["[freq]"]) + if(R.receive_range(freq, level) > -1) + radios += R + + // --- Broadcast only to intercoms and station-bounced radios --- + + else if(data == 2) + + for(var/obj/item/device/radio/R in all_radios["[freq]"]) + if(istype(R, /obj/item/device/radio/headset)) + continue + + if(R.receive_range(freq, level) > -1) + radios += R + + // --- Broadcast to ALL radio devices --- + + else + for(var/obj/item/device/radio/R in all_radios["[freq]"]) + if(R.receive_range(freq, level) > -1) + radios += R + + var/freqtext = num2text(freq) + for(var/obj/item/device/radio/R in all_radios["[SYND_FREQ]"]) //syndicate radios use magic that allows them to hear everything. this was already the case, now it just doesn't need the allinone anymore. solves annoying bugs that aren't worth solving. + if(R.receive_range(SYND_FREQ, list(R.z)) > -1 && freqtext in radiochannelsreverse) + radios |= R + + // Get a list of mobs who can hear from the radios we collected. + var/list/receive = get_mobs_in_radio_ranges(radios) //this includes all hearers. + + for(var/mob/R in receive) //Filter receiver list. + if (R.client && R.client.holder && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + receive -= R + + for(var/mob/M in player_list) + if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO)) + receive |= M + + var/rendered = virt.compose_message(virt, virt.languages, message, freq, spans) //Always call this on the virtualspeaker to advoid issues. + for(var/atom/movable/hearer in receive) + hearer.Hear(rendered, virt, AM.languages, message, freq, spans) + + if(length(receive)) + // --- This following recording is intended for research and feedback in the use of department radio channels --- + + var/blackbox_msg = "[AM] [AM.say_quote(message, spans)]" + if(istype(blackbox)) + switch(freq) + if(1459) + blackbox.msg_common += blackbox_msg + if(1351) + blackbox.msg_science += blackbox_msg + if(1353) + blackbox.msg_command += blackbox_msg + if(1355) + blackbox.msg_medical += blackbox_msg + if(1357) + blackbox.msg_engineering += blackbox_msg + if(1359) + blackbox.msg_security += blackbox_msg + if(1441) + blackbox.msg_deathsquad += blackbox_msg + if(1213) + blackbox.msg_syndicate += blackbox_msg + if(1349) + blackbox.msg_service += blackbox_msg + if(1347) + blackbox.msg_cargo += blackbox_msg + else + blackbox.messages += blackbox_msg + + spawn(50) + PlaceInPool(virt) + +/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level) + + /* ###### 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]"]) + var/turf/position = get_turf(R) + if(position && position.z == level) + receive |= R.send_hear(display_freq, level) + + + // --- 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 + var/turf/position = get_turf(R) + if(position && position.z == level) + 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]"]) + var/turf/position = get_turf(R) + if(position && position.z == level) + receive |= R.send_hear(SYND_FREQ) + + + // --- Broadcast to ALL radio devices --- + + else + for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + var/turf/position = get_turf(R) + if(position && position.z == level) + 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.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + continue + + + // --- Check for compression --- + if(compression > 0) + + heard_gibberish += R + continue + + // --- Can understand the speech --- + + if (R.languages & M.languages) + + heard_normal += R + + // --- Can't understand the speech --- + + else + // - Just display a garbled message - + + heard_garbled += R + + + /* ###### 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(SCI_FREQ) + freq_text = "Science" + if(MED_FREQ) + freq_text = "Medical" + if(ENG_FREQ) + freq_text = "Engineering" + if(SEC_FREQ) + freq_text = "Security" + if(SERV_FREQ) + freq_text = "Service" + if(SUPP_FREQ) + freq_text = "Supply" + if(AIPRIV_FREQ) + freq_text = "AI Private" + //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] " + var/part_c = "" + + if (display_freq==SYND_FREQ) + part_a = "" + else if (display_freq==COMM_FREQ) + part_a = "" + else if (display_freq==SCI_FREQ) + part_a = "" + else if (display_freq==MED_FREQ) + part_a = "" + else if (display_freq==ENG_FREQ) + part_a = "" + else if (display_freq==SEC_FREQ) + part_a = "" + else if (display_freq==SERV_FREQ) + part_a = "" + else if (display_freq==SUPP_FREQ) + part_a = "" + else if (display_freq==CENTCOM_FREQ) + part_a = "" + else if (display_freq==AIPRIV_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]\] " + 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]" + + //BR.messages_admin += blackbox_admin_msg + if(istype(blackbox)) + switch(display_freq) + if(1459) + blackbox.msg_common += blackbox_msg + if(1351) + blackbox.msg_science += blackbox_msg + if(1353) + blackbox.msg_command += blackbox_msg + if(1355) + blackbox.msg_medical += blackbox_msg + if(1357) + blackbox.msg_engineering += blackbox_msg + if(1359) + blackbox.msg_security += blackbox_msg + if(1441) + blackbox.msg_deathsquad += blackbox_msg + if(1213) + blackbox.msg_syndicate += blackbox_msg + if(1349) + blackbox.msg_service += blackbox_msg + if(1347) + blackbox.msg_cargo += blackbox_msg + else + blackbox.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]" + + 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)]\"" + 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)]\"" + 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) + +//Use this to test if an obj can communicate with a Telecommunications Network + +/atom/proc/test_telecomms() + var/datum/signal/signal = src.telecomms_process() + var/turf/position = get_turf(src) + return (position.z in signal.data["level"] && signal.data["done"]) + +/atom/proc/telecomms_process() + + // First, we want to generate a new radio signal + var/datum/signal/signal = new + signal.transmission_method = 2 // 2 would be a subspace transmission. + var/turf/pos = get_turf(src) + + // --- Finally, tag the actual signal with the appropriate values --- + signal.data = list( + "slow" = 0, // how much to sleep() before broadcasting - simulates net lag + "message" = "TEST", + "compression" = rand(45, 50), // If the signal is compressed, compress our message too. + "traffic" = 0, // dictates the total traffic sum that the signal went through + "type" = 4, // determines what type of radio input it is: test broadcast + "reject" = 0, + "done" = 0, + "level" = pos.z // The level it is being broadcasted at. + ) + signal.frequency = 1459// Common channel + + //#### Sending the signal to all subspace receivers ####// + for(var/obj/machinery/telecomms/receiver/R in telecomms_list) + R.receive_signal(signal) + + sleep(rand(10,25)) + + return signal + diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm new file mode 100644 index 00000000000..8798f07c20c --- /dev/null +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -0,0 +1,232 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/telecomms/server + name = "telecommunications server monitoring console" + icon_state = "comm_logs" + + var/screen = 0 // the screen number: + var/list/servers = list() // the servers located by the computer + var/obj/machinery/telecomms/server/SelectedServer + + var/network = "NULL" // the network to probe + var/temp = "" // temporary feedback messages + + var/universal_translate = 0 // set to 1 if it can translate nonhuman speech + + req_access = list(access_tcomsat) + circuit = "/obj/item/weapon/circuitboard/comm_server" + +/obj/machinery/computer/telecomms/server/attack_hand(mob/user as mob) + if(..()) + return + user.set_machine(src) + var/dat = "Telecommunication Server Monitor
Telecommunications Server Monitor
" + + 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]" + + if(SelectedServer.totaltraffic >= 1024) + dat += "
Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes

" + else + dat += "
Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes

" + + dat += "Stored Logs:
    " + + var/i = 0 + for(var/datum/comm_log_entry/C in SelectedServer.log_entries) + i++ + + + // If the log is a speech file + if(C.input_type == "Speech File") + + dat += "
  1. [C.name] \[X\]
    " + + // -- 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/list/humans = typesof(/mob/living/carbon/human, /mob/living/carbon/brain) + var/list/monkeys = typesof(/mob/living/carbon/monkey) + var/list/silicons = typesof(/mob/living/silicon) + var/list/slimes = typesof(/mob/living/simple_animal/slime) + var/list/animals = typesof(/mob/living/simple_animal) + + if(mobtype in humans) + race = "Human" + language = race + + else if(mobtype in slimes) // NT knows a lot about slimes, but not aliens. Can identify slimes + race = "Slime" + language = race + + else if(mobtype in monkeys) + race = "Monkey" + language = race + + else if(mobtype in silicons || C.parameters["job"] == "AI") // sometimes M gets deleted prematurely for AIs... just check the job + race = "Artificial Life" + language = race + + else if(istype(mobtype, /obj)) + race = "Machinery" + language = race + + else if(mobtype in animals) + race = "Domestic Animal" + language = race + + else + race = "Unidentifiable" + language = race + + // -- 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"]) + 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 += "

  2. " + + else if(C.input_type == "Execution Error") + + dat += "
  3. [C.name] \[X\]
    " + dat += "Output: \"[C.parameters["message"]]\"
    " + dat += "

  4. " + + + dat += "
" + + + + user << browse(dat, "window=comm_monitor;size=575x400") + onclose(user, "server_control") + + temp = "" + return + + +/obj/machinery/computer/telecomms/server/Topic(href, href_list) + if(..()) + return + + + add_fingerprint(usr) + usr.set_machine(src) + + 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(href_list["delete"]) + + if(!src.allowed(usr) && !emagged) + usr << "ACCESS DENIED." + return + + if(SelectedServer) + + var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])] + + temp = "- DELETED ENTRY: [D.name] -" + + SelectedServer.log_entries.Remove(D) + del(D) + + else + temp = "- FAILED: NO SELECTED MACHINE -" + + if(href_list["network"]) + + var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network) + + if(newnet && ((usr in range(1, src) || issilicon(usr)))) + if(length(newnet) > 15) + temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + + else + + network = newnet + screen = 0 + servers = list() + temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" + + updateUsrDialog() + return + +/obj/machinery/computer/telecomms/server/attackby() + ..() + src.updateUsrDialog() + return + +/obj/machinery/computer/telecomms/server/emag_act(mob/user as mob) + if(!emagged) + playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 + user << "You you disable the security protocols." \ No newline at end of file diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm new file mode 100644 index 00000000000..42d752ee079 --- /dev/null +++ b/code/game/machinery/telecomms/presets.dm @@ -0,0 +1,187 @@ +// ### Preset machines ### + +//Relay + +/obj/machinery/telecomms/relay/preset + network = "tcommsat" + +/obj/machinery/telecomms/relay/preset/station + id = "Station Relay" + listening_level = 1 + autolinkers = list("s_relay") + +/obj/machinery/telecomms/relay/preset/telecomms + id = "Telecomms Relay" + autolinkers = list("relay") + +/obj/machinery/telecomms/relay/preset/mining + id = "Mining Relay" + autolinkers = list("m_relay") + +/obj/machinery/telecomms/relay/preset/ruskie + id = "Ruskie Relay" + hide = 1 + toggled = 0 + autolinkers = list("r_relay") + +//HUB + +/obj/machinery/telecomms/hub/preset + id = "Hub" + network = "tcommsat" + autolinkers = list("hub", "relay", "s_relay", "m_relay", "r_relay", "science", "medical", + "supply", "service", "common", "command", "engineering", "security", + "receiverA", "receiverB", "broadcasterA", "broadcasterB") + +//Receivers + +//--PRESET LEFT--// + +/obj/machinery/telecomms/receiver/preset_left + id = "Receiver A" + network = "tcommsat" + autolinkers = list("receiverA") // link to relay + freq_listening = list(1351, 1355, 1347, 1349) // science, medical, supply, service + + +//--PRESET RIGHT--// + +/obj/machinery/telecomms/receiver/preset_right + id = "Receiver B" + network = "tcommsat" + autolinkers = list("receiverB") // link to relay + freq_listening = list(1353, 1357, 1359) //command, engineering, security + + //Common and other radio frequencies for people to freely use + New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + + +//Buses + +/obj/machinery/telecomms/bus/preset_one + id = "Bus 1" + network = "tcommsat" + freq_listening = list(1351, 1355) + autolinkers = list("processor1", "science", "medical") + +/obj/machinery/telecomms/bus/preset_two + id = "Bus 2" + network = "tcommsat" + freq_listening = list(1347,1349) + autolinkers = list("processor2", "supply", "service") + +/obj/machinery/telecomms/bus/preset_three + id = "Bus 3" + network = "tcommsat" + freq_listening = list(1359, 1353) + autolinkers = list("processor3", "security", "command") + +/obj/machinery/telecomms/bus/preset_four + id = "Bus 4" + network = "tcommsat" + freq_listening = list(1357) + autolinkers = list("processor4", "engineering", "common") + +/obj/machinery/telecomms/bus/preset_four/New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + +//Processors + +/obj/machinery/telecomms/processor/preset_one + id = "Processor 1" + network = "tcommsat" + autolinkers = list("processor1") // processors are sort of isolated; they don't need backward links + +/obj/machinery/telecomms/processor/preset_two + id = "Processor 2" + network = "tcommsat" + autolinkers = list("processor2") + +/obj/machinery/telecomms/processor/preset_three + id = "Processor 3" + network = "tcommsat" + autolinkers = list("processor3") + +/obj/machinery/telecomms/processor/preset_four + id = "Processor 4" + network = "tcommsat" + autolinkers = list("processor4") + +//Servers + +/obj/machinery/telecomms/server/presets + network = "tcommsat" + +/obj/machinery/telecomms/server/presets/New() + ..() + name = id + + +/obj/machinery/telecomms/server/presets/science + id = "Science Server" + freq_listening = list(1351) + autolinkers = list("science") + +/obj/machinery/telecomms/server/presets/medical + id = "Medical Server" + freq_listening = list(1355) + autolinkers = list("medical") + +/obj/machinery/telecomms/server/presets/supply + id = "Supply Server" + freq_listening = list(1347) + autolinkers = list("supply") + +/obj/machinery/telecomms/server/presets/service + id = "Service Server" + freq_listening = list(1349) + autolinkers = list("service") + +/obj/machinery/telecomms/server/presets/common + id = "Common Server" + freq_listening = list() + autolinkers = list("common") + + //Common and other radio frequencies for people to freely use + // 1441 to 1489 +/obj/machinery/telecomms/server/presets/common/New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + +/obj/machinery/telecomms/server/presets/command + id = "Command Server" + freq_listening = list(1353) + autolinkers = list("command") + +/obj/machinery/telecomms/server/presets/engineering + id = "Engineering Server" + freq_listening = list(1357) + autolinkers = list("engineering") + +/obj/machinery/telecomms/server/presets/security + id = "Security Server" + freq_listening = list(1359) + autolinkers = list("security") + + +//Broadcasters + +//--PRESET LEFT--// + +/obj/machinery/telecomms/broadcaster/preset_left + id = "Broadcaster A" + network = "tcommsat" + autolinkers = list("broadcasterA") + +//--PRESET RIGHT--// + +/obj/machinery/telecomms/broadcaster/preset_right + id = "Broadcaster B" + network = "tcommsat" + autolinkers = list("broadcasterB") diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm new file mode 100644 index 00000000000..4623e39a7a1 --- /dev/null +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -0,0 +1,136 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + + +/* + Telecomms monitor tracks the overall trafficing of a telecommunications network + and displays a heirarchy of linked machines. +*/ + + +/obj/machinery/computer/telecomms/monitor + name = "telecommunications monitoring console" + icon_state = "comm_monitor" + + var/screen = 0 // the screen number: + var/list/machinelist = list() // the machines located by the computer + var/obj/machinery/telecomms/SelectedMachine + + var/network = "NULL" // the network to probe + + var/temp = "" // temporary feedback messages + circuit = "/obj/item/weapon/circuitboard/comm_monitor" + +/obj/machinery/computer/telecomms/monitor/attack_hand(mob/user as mob) + if(..()) + return + user.set_machine(src) + var/dat = "Telecommunications Monitor
Telecommunications Monitor
" + + switch(screen) + + + // --- Main Menu --- + + if(0) + dat += "
[temp]

" + dat += "
Current Network: [network]
" + if(machinelist.len) + dat += "
Detected Network Entities:
    " + for(var/obj/machinery/telecomms/T in machinelist) + dat += "
  • \ref[T] [T.name] ([T.id])
  • " + dat += "
" + dat += "
\[Flush Buffer\]" + else + dat += "\[Probe Network\]" + + + // --- Viewing Machine --- + + if(1) + dat += "
[temp]
" + dat += "
\[Main Menu\]
" + dat += "
Current Network: [network]
" + dat += "Selected Network Entity: [SelectedMachine.name] ([SelectedMachine.id])
" + dat += "Linked Entities:
    " + for(var/obj/machinery/telecomms/T in SelectedMachine.links) + if(!T.hide) + dat += "
  1. \ref[T.id] [T.name] ([T.id])
  2. " + dat += "
" + + + + user << browse(dat, "window=comm_monitor;size=575x400") + onclose(user, "server_control") + + temp = "" + return + + +/obj/machinery/computer/telecomms/monitor/Topic(href, href_list) + if(..()) + return + + + add_fingerprint(usr) + usr.set_machine(src) + + if(href_list["viewmachine"]) + screen = 1 + for(var/obj/machinery/telecomms/T in machinelist) + if(T.id == href_list["viewmachine"]) + SelectedMachine = T + break + + if(href_list["operation"]) + switch(href_list["operation"]) + + if("release") + machinelist = list() + screen = 0 + + if("mainmenu") + screen = 0 + + if("probe") + if(machinelist.len > 0) + temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" + + else + for(var/obj/machinery/telecomms/T in range(25, src)) + if(T.network == network) + machinelist.Add(T) + + if(!machinelist.len) + temp = "- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -" + else + temp = "- [machinelist.len] ENTITIES LOCATED & BUFFERED -" + + screen = 0 + + + if(href_list["network"]) + + var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network) + if(newnet && ((usr in range(1, src) || issilicon(usr)))) + if(length(newnet) > 15) + temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + + else + network = newnet + screen = 0 + machinelist = list() + temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" + + updateUsrDialog() + return + +/obj/machinery/computer/telecomms/monitor/attackby() + ..() + src.updateUsrDialog() + return + +/obj/machinery/computer/telecomms/monitor/emag_act(mob/user as mob) + if(!emagged) + playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 + user << "You you disable the security protocols." \ No newline at end of file diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm new file mode 100644 index 00000000000..11cf378195a --- /dev/null +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -0,0 +1,290 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + + + + + +/obj/machinery/computer/telecomms/traffic + name = "telecommunications traffic control console" + icon_state = "computer_generic" + + var/screen = 0 // the screen number: + var/list/servers = list() // the servers located by the computer + var/mob/editingcode + var/mob/lasteditor + var/list/viewingcode = list() + var/obj/machinery/telecomms/server/SelectedServer + + var/network = "NULL" // the network to probe + var/temp = "" // temporary feedback messages + + var/storedcode = "" // code stored + var/obj/item/weapon/card/id/auth = null + var/list/access_log = list() + var/process = 0 + circuit = "/obj/item/weapon/circuitboard/comm_traffic" + + req_access = list(access_tcomsat) + +/obj/machinery/computer/telecomms/traffic/proc/stop_editing() + if(editingcode) + if(editingcode.client) + winshow(editingcode, "Telecomms IDE", 0) // hide the window! + editingcode.unset_machine() + editingcode = null + +/obj/machinery/computer/telecomms/traffic/process() + + if(stat & (NOPOWER|BROKEN)) + stop_editing() + return + + if(editingcode && editingcode.machine != src) + stop_editing() + return + + if(!editingcode) + if(length(viewingcode) > 0) + editingcode = pick(viewingcode) + viewingcode.Remove(editingcode) + return + + process = !process + if(!process) + return + + // loop if there's someone manning the keyboard + if(!editingcode.client) + stop_editing() + return + + // For the typer, the input is enabled. Buffer the typed text + storedcode = "[winget(editingcode, "tcscode", "text")]" + winset(editingcode, "tcscode", "is-disabled=false") + + // If the player's not manning the keyboard anymore, adjust everything + if(!in_range(editingcode, src) && !issilicon(editingcode) || editingcode.machine != src) + winshow(editingcode, "Telecomms IDE", 0) // hide the window! + editingcode = null + return + + // 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 = replacetext(storedcode, "\\\"", "\\\\\"") + showcode = replacetext(storedcode, "\"", "\\\"") + + for(var/mob/M in viewingcode) + + if( (M.machine == src && in_range(M, src) ) || issilicon(M)) + winset(M, "tcscode", "is-disabled=true") + winset(M, "tcscode", "text=\"[showcode]\"") + else + viewingcode.Remove(M) + winshow(M, "Telecomms IDE", 0) // hide the windows + + +/obj/machinery/computer/telecomms/traffic/attack_hand(mob/user as mob) + if(..()) + return + user.set_machine(src) + var/dat = "Telecommunication Traffic Control
Telecommunications Traffic Control
" + dat += "
[(auth ? "AUTHED" : "NOT AUTHED")]: [(!auth ? "Insert ID" : auth)]
" + dat += "View System Log
" + + if(issilicon(user) || auth) + + 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) + if(SelectedServer) + 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" + else + screen = 0 + return + + + user << browse(dat, "window=traffic_control;size=575x400") + onclose(user, "server_control") + + temp = "" + return + +/obj/machinery/computer/telecomms/traffic/proc/create_log(var/entry, var/mob/user) + var/id = null + if(issilicon(user)) + id = "System Administrator" + else + if(auth) + id = "[auth.registered_name] ([auth.assignment])" + else + ERROR("There is a null auth while the user isn't a silicon! ([user.name], [user.type])") + return + access_log += "\[[get_timestamp()]\] [id] [entry]" + +/obj/machinery/computer/telecomms/traffic/proc/print_logs() + . = "

Traffic Control Telecomms System Log


" + for(var/entry in access_log) + . += entry + "
" + return . + +/obj/machinery/computer/telecomms/traffic/Topic(href, href_list) + if(..()) + return + + + add_fingerprint(usr) + usr.set_machine(src) + + if(href_list["auth"]) + if(iscarbon(usr)) + var/mob/living/carbon/C = usr + if(!auth) + var/obj/item/weapon/card/id/I = C.get_active_hand() + if(istype(I)) + if(check_access(I)) + C.drop_item() + I.loc = src + auth = I + create_log("has logged in.", usr) + else + create_log("has logged out.", usr) + auth.loc = src.loc + C.put_in_hands(auth) + auth = null + updateUsrDialog() + return + + if(href_list["print"]) + usr << browse(print_logs(), "window=traffic_logs") + return + + if(!auth && !issilicon(usr) && !emagged) + usr << "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 + create_log("selected server [T.name]", usr) + break + + + if(href_list["operation"]) + create_log("has performed action: [href_list["operation"]].", usr) + 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 == usr) return + if(usr in viewingcode) return + + if(!editingcode) + lasteditor = usr + editingcode = usr + winshow(editingcode, "Telecomms IDE", 1) // show the IDE + winset(editingcode, "tcscode", "is-disabled=false") + winset(editingcode, "tcscode", "text=\"\"") + var/showcode = replacetext(storedcode, "\\\"", "\\\\\"") + showcode = replacetext(storedcode, "\"", "\\\"") + winset(editingcode, "tcscode", "text=\"[showcode]\"") + + else + viewingcode.Add(usr) + winshow(usr, "Telecomms IDE", 1) // show the IDE + winset(usr, "tcscode", "is-disabled=true") + winset(editingcode, "tcscode", "text=\"\"") + var/showcode = replacetext(storedcode, "\"", "\\\"") + winset(usr, "tcscode", "text=\"[showcode]\"") + + if("togglerun") + SelectedServer.autoruncode = !(SelectedServer.autoruncode) + + if(href_list["network"]) + + var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network) + + if(newnet && canAccess(usr)) + if(length(newnet) > 15) + temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + + else + + network = newnet + screen = 0 + servers = list() + temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" + create_log("has set the network to [network].", usr) + + updateUsrDialog() + return + +/obj/machinery/computer/telecomms/traffic/attackby() + ..() + src.updateUsrDialog() + return + +/obj/machinery/computer/telecomms/traffic/emag_act(mob/user as mob) + if(!emagged) + playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 + user << "You you disable the security protocols." + +/obj/machinery/computer/telecomms/traffic/proc/canAccess(var/mob/user) + if(issilicon(user) || in_range(user, src)) + return 1 + return 0 \ No newline at end of file diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 2b75380b43b..6c7524e0089 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -54,10 +54,10 @@ if(istype(O, /obj/item/weapon/reagent_containers/glass)) if(O.reagents) if(O.reagents.total_volume < 1) - user << "The [O] is empty." + user << "The [O] is empty." else if(O.reagents.total_volume >= 1) if(O.reagents.has_reagent("facid", 1)) - user << "The acid chews through the balloon!" + user << "The acid chews through the balloon!" O.reagents.reaction(user) qdel(src) else @@ -135,17 +135,17 @@ if (istype(A, /obj/item/toy/ammo/gun)) if (src.bullets >= 7) - user << "It's already fully loaded!" + user << "It's already fully loaded!" return 1 if (A.amount_left <= 0) - user << "There are no more caps!" + user << "There are no more caps!" return 1 if (A.amount_left < (7 - src.bullets)) src.bullets += A.amount_left - user << text("You reload [] cap\s!", A.amount_left) + user << text("You reload [] cap\s.", A.amount_left) A.amount_left = 0 else - user << text("You reload [] cap\s!", 7 - src.bullets) + user << text("You reload [] cap\s.", 7 - src.bullets) A.amount_left -= 7 - src.bullets src.bullets = 7 A.update_icon() @@ -227,7 +227,7 @@ ..() if(istype(W, /obj/item/toy/sword)) if(W == src) - user << "You try to attach the end of the plastic sword to... itself. You're not very smart, are you?" + user << "You try to attach the end of the plastic sword to... itself. You're not very smart, are you?" if(ishuman(user)) user.adjustBrainLoss(10) else if((W.flags & NODROP) || (flags & NODROP)) @@ -442,8 +442,6 @@ graf_rot = 270 else graf_rot = 0 - user << "You start drawing a [temp] on the [target.name]..." - user << "You finish drawing [temp]." user << "You start [instant ? "spraying" : "drawing"] a [temp] on the [target.name]..." if(instant) @@ -475,9 +473,8 @@ return /obj/item/toy/crayon/attack(mob/M as mob, mob/user as mob) - user << "You take a [huffable ? "huff" : "bite"] of the [src.name]. Delicious!" if(edible && (M == user)) - user << "You take a bite of the [src.name]. Delicious!" + user << "You take a bite of the [src.name]. Delicious!" user.nutrition += 5 if(uses) uses -= 5 @@ -748,7 +745,7 @@ obj/item/toy/cards/deck/attack_hand(mob/user as mob) var/choice = null if(cards.len == 0) src.icon_state = "deck_[deckstyle]_empty" - user << "There are no more cards to draw." + user << "There are no more cards to draw!" return var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc) choice = cards[1] @@ -876,7 +873,7 @@ obj/item/toy/cards/cardhand/Topic(href, href_list) C.apply_card_vars(C,O) C.pickup(cardUser) cardUser.put_in_any_hand_if_possible(C) - cardUser.visible_message("[cardUser] draws a card from \his hand.", "You take the [C.cardname] from your hand.") + cardUser.visible_message("[cardUser] draws a card from \his hand.", "You take the [C.cardname] from your hand.") interact(cardUser) if(src.currenthand.len < 3) @@ -1057,7 +1054,7 @@ obj/item/toy/cards/deck/syndicate /obj/item/toy/nuke/attack_self(mob/user) if (cooldown < world.time) cooldown = world.time + 1800 //3 minutes - user.visible_message("[user] presses a button on [src].", "You activate [src], it plays a loud noise!", "You hear the click of a button.") + user.visible_message("[user] presses a button on [src].", "You activate [src], it plays a loud noise!", "You hear the click of a button.") spawn(5) //gia said so icon_state = "nuketoy" playsound(src, 'sound/machines/Alarm.ogg', 100, 0, surround = 0) @@ -1075,7 +1072,7 @@ obj/item/toy/cards/deck/syndicate /obj/item/toy/minimeteor name = "\improper Mini-Meteor" - desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor™" + desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor?" icon = 'icons/obj/toy.dmi' icon_state = "minimeteor" w_class = 2.0 @@ -1116,7 +1113,7 @@ obj/item/toy/cards/deck/syndicate */ /obj/item/toy/redbutton name = "big red button" - desc = "A big, plastic red button. Reads 'From HonkCo Pranks©' on the back." + desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back." icon = 'icons/obj/assemblies.dmi' icon_state = "bigred" w_class = 2.0 @@ -1125,7 +1122,7 @@ obj/item/toy/cards/deck/syndicate /obj/item/toy/redbutton/attack_self(mob/user) if (cooldown < world.time) cooldown = (world.time + 300) // Sets cooldown at 30 seconds - user.visible_message("[user] presses the big red button.", "You press the button, it plays a loud noise!", "You hear a loud click.") + user.visible_message("[user] presses the big red button.", "You press the button, it plays a loud noise!", "The button clicks loudly.") playsound(src, 'sound/effects/explosionfar.ogg', 50, 0, surround = 0) for(var/mob/M in range(10, src)) // Checks range if(!M.stat && !istype(M, /mob/living/silicon/ai)) // Checks to make sure whoever's getting shaken is alive/not the AI @@ -1133,4 +1130,4 @@ obj/item/toy/cards/deck/syndicate shake_camera(M, 2, 1) // Shakes player camera 2 squares for 1 second. else - user << "Nothing happens!" + user << "Nothing happens." diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index c0766520753..67292b52f2d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -4,11 +4,4 @@ locked = 1 icon_state = "secure" health = 200 - user << "You have no idea how this thing is supposed to work!" - user << "You can't do that right now!" - user.visible_message("[user] has [locked ? null : "un"]locked the locker.", "You [locked ? null : "un"]lock the locker.") - user << "Access Denied." - user << "The locker appears to be broken!" - O.show_message("The locker has been broken by [user] with an electromagnetic card!", 1, "You hear a faint electrical spark.", 2) - user << "The locker is locked!" secure = 1 diff --git a/code/modules/reagents/Chemistry-Goon-420BlazeIt.dm b/code/modules/reagents/Chemistry-Goon-420BlazeIt.dm new file mode 100644 index 00000000000..06a63b7c8cd --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-420BlazeIt.dm @@ -0,0 +1,373 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 + +#define REM REAGENTS_EFFECT_MULTIPLIER + +datum/reagent/nicotine + name = "Nicotine" + id = "nicotine" + description = "Slightly reduces stun times. If overdosed it will deal toxin and oxygen damage." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + overdose_threshold = 35 + addiction_threshold = 30 + +datum/reagent/nicotine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/smoke_message = pick("You can just feel your lungs dying!", "You feel relaxed.", "You feel calmed.", "You feel the lung cancer forming.", "You feel the money you wasted.", "You feel like a space cowboy.", "You feel rugged.") + if(prob(5)) + M << "[smoke_message]" + M.AdjustStunned(-1) + M.adjustStaminaLoss(-1*REM) + ..() + return + +datum/reagent/nicotine/overdose_process(var/mob/living/M as mob) + if(prob(20)) + M << "You feel like you've smoked too much." + M.adjustToxLoss(1*REM) + M.adjustOxyLoss(1*REM) + ..() + return + +datum/reagent/crank + name = "Crank" + id = "crank" + description = "Reduces stun times by about 200%. If overdosed or addicted it will deal significant Toxin, Brute and Brain damage." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + overdose_threshold = 20 + addiction_threshold = 10 + +datum/reagent/crank/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/high_message = pick("You feel jittery.", "You feel like you gotta go fast.", "You feel like you need to step it up.") + if(prob(5)) + M << "[high_message]" + M.AdjustParalysis(-2) + M.AdjustStunned(-2) + M.AdjustWeakened(-2) + ..() + return +datum/reagent/crank/overdose_process(var/mob/living/M as mob) + M.adjustBrainLoss(rand(1,10)*REM) + M.adjustToxLoss(rand(1,10)*REM) + M.adjustBruteLoss(rand(1,10)*REM) + ..() + return + +datum/reagent/crank/addiction_act_stage1(var/mob/living/M as mob) + M.adjustBrainLoss(rand(1,10)*REM) + ..() + return +datum/reagent/crank/addiction_act_stage2(var/mob/living/M as mob) + M.adjustToxLoss(rand(1,10)*REM) + ..() + return +datum/reagent/crank/addiction_act_stage3(var/mob/living/M as mob) + M.adjustBruteLoss(rand(1,10)*REM) + ..() + return +datum/reagent/crank/addiction_act_stage4(var/mob/living/M as mob) + M.adjustBrainLoss(rand(1,10)*REM) + M.adjustToxLoss(rand(1,10)*REM) + M.adjustBruteLoss(rand(1,10)*REM) + ..() + return +/datum/chemical_reaction/crank + name = "Crank" + id = "crank" + result = "crank" + required_reagents = list("diphenhydramine" = 1, "ammonia" = 1, "lithium" = 1, "sacid" = 1, "fuel" = 1) + result_amount = 5 + mix_message = "The mixture violently reacts, leaving behind a few crystalline shards." + required_temp = 390 + +/datum/reagent/krokodil + name = "Krokodil" + id = "krokodil" + description = "Cools and calms you down. If overdosed it will deal significant Brain and Toxin damage. If addicted it will begin to deal fatal amounts of Brute damage as the subject's skin falls off." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + overdose_threshold = 20 + addiction_threshold = 15 + + +/datum/reagent/krokodil/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/high_message = pick("You feel calm.", "You feel collected.", "You feel like you need to relax.") + if(prob(5)) + M << "[high_message]" + ..() + return + +/datum/reagent/krokodil/overdose_process(var/mob/living/M as mob) + if(prob(10)) + M.adjustBrainLoss(rand(1,5)*REM) + M.adjustToxLoss(rand(1,5)*REM) + ..() + return + + +/datum/reagent/krokodil/addiction_act_stage1(var/mob/living/M as mob) + M.adjustBrainLoss(rand(1,5)*REM) + M.adjustToxLoss(rand(1,5)*REM) + ..() + return +/datum/reagent/krokodil/addiction_act_stage2(var/mob/living/M as mob) + if(prob(25)) + M << "Your skin feels loose..." + ..() + return +/datum/reagent/krokodil/addiction_act_stage3(var/mob/living/M as mob) + if(prob(25)) + M << "Your skin starts to peel away..." + M.adjustBruteLoss(3*REM) + ..() + return + +/datum/reagent/krokodil/addiction_act_stage4(var/mob/living/carbon/human/M as mob) + if(!istype(M.dna.species, /datum/species/cosmetic_zombie)) + M << "Your skin falls off easily!" + M.adjustBruteLoss(rand(50,80)*REM) // holy shit your skin just FELL THE FUCK OFF + hardset_dna(M, null, null, null, null, /datum/species/cosmetic_zombie) + else + M.adjustBruteLoss(5*REM) + ..() + return +/datum/chemical_reaction/krokodil + name = "Krokodil" + id = "krokodil" + result = "krokodil" + required_reagents = list("diphenhydramine" = 1, "morphine" = 1, "cleaner" = 1, "potassium" = 1, "phosphorus" = 1, "fuel" = 1) + result_amount = 6 + mix_message = "The mixture dries into a pale blue powder." + required_temp = 380 + +/datum/reagent/methamphetamine + name = "Methamphetamine" + id = "methamphetamine" + description = "Reduces stun times by about 300%, speeds the user up, and allows the user to quickly recover stamina while dealing a small amount of Brain damage. If overdosed the subject will move randomly, laugh randomly, drop items and suffer from Toxin and Brain damage. If addicted the subject will constantly jitter and drool, before becoming dizzy and losing motor control and eventually suffer heavy toxin damage." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + overdose_threshold = 20 + addiction_threshold = 10 + metabolization_rate = 0.6 + +/datum/reagent/methamphetamine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/high_message = pick("You feel hyper.", "You feel like you need to go faster.", "You feel like you can run the world.") + if(prob(5)) + M << "[high_message]" + M.AdjustParalysis(-3) + M.AdjustStunned(-3) + M.AdjustWeakened(-3) + M.adjustStaminaLoss(-3) + M.status_flags |= GOTTAGOREALLYFAST + M.Jitter(3) + M.adjustBrainLoss(0.5) + if(prob(5)) + M.emote(pick("twitch", "shiver")) + ..() + return + +/datum/reagent/methamphetamine/overdose_process(var/mob/living/M as mob) + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 4, i++) + step(M, pick(cardinal)) + if(prob(20)) + M.emote("laugh") + if(prob(33)) + M.visible_message("[M]'s hands flip out and flail everywhere!") + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + ..() + if(prob(20)) + M.adjustToxLoss(5) + M.adjustBrainLoss(pick(0.5, 0.6, 0.7, 0.8, 0.9, 1)) + return + +/datum/reagent/methamphetamine/addiction_act_stage1(var/mob/living/M as mob) + M.Jitter(5) + if(prob(20)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/methamphetamine/addiction_act_stage2(var/mob/living/M as mob) + M.Jitter(10) + M.Dizzy(10) + if(prob(30)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/methamphetamine/addiction_act_stage3(var/mob/living/M as mob) + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 4, i++) + step(M, pick(cardinal)) + M.Jitter(15) + M.Dizzy(15) + if(prob(40)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/methamphetamine/addiction_act_stage4(var/mob/living/carbon/human/M as mob) + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 8, i++) + step(M, pick(cardinal)) + M.Jitter(20) + M.Dizzy(20) + M.adjustToxLoss(5) + if(prob(50)) + M.emote(pick("twitch","drool","moan")) + ..() + return + +/datum/chemical_reaction/methamphetamine + name = "methamphetamine" + id = "methamphetamine" + result = "methamphetamine" + required_reagents = list("ephedrine" = 1, "iodine" = 1, "phosphorus" = 1, "hydrogen" = 1) + result_amount = 4 + required_temp = 374 + +/datum/chemical_reaction/saltpetre + name = "saltpetre" + id = "saltpetre" + result = "saltpetre" + required_reagents = list("potassium" = 1, "nitrogen" = 1, "oxygen" = 3) + result_amount = 3 + +/datum/reagent/saltpetre + name = "Saltpetre" + id = "saltpetre" + description = "Volatile." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + +/datum/reagent/bath_salts + name = "Bath Salts" + id = "bath_salts" + description = "Makes you nearly impervious to stuns and grants a stamina regeneration buff, but you will be a nearly uncontrollable tramp-bearded raving lunatic." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + overdose_threshold = 20 + addiction_threshold = 10 + + +/datum/reagent/bath_salts/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.") + if(prob(5)) + M << "[high_message]" + M.AdjustParalysis(-5) + M.AdjustStunned(-5) + M.AdjustWeakened(-5) + M.adjustStaminaLoss(-10) + M.adjustBrainLoss(1) + M.adjustToxLoss(0.1) + M.hallucination += 10 + if(M.canmove && !istype(M.loc, /atom/movable)) + step(M, pick(cardinal)) + step(M, pick(cardinal)) + ..() + return + +/datum/chemical_reaction/bath_salts + name = "bath_salts" + id = "bath_salts" + result = "bath_salts" + required_reagents = list("????" = 1, "saltpetre" = 1, "nutriment" = 1, "cleaner" = 1, "enzyme" = 1, "tea" = 1, "mercury" = 1) + result_amount = 7 + required_temp = 374 + +/datum/reagent/bath_salts/overdose_process(var/mob/living/M as mob) + M.hallucination += 10 + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 8, i++) + step(M, pick(cardinal)) + if(prob(20)) + M.emote(pick("twitch","drool","moan")) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + ..() + return + +/datum/reagent/bath_salts/addiction_act_stage1(var/mob/living/M as mob) + M.hallucination += 10 + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 8, i++) + step(M, pick(cardinal)) + M.Jitter(5) + M.adjustBrainLoss(10) + if(prob(20)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/bath_salts/addiction_act_stage2(var/mob/living/M as mob) + M.hallucination += 20 + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 8, i++) + step(M, pick(cardinal)) + M.Jitter(10) + M.Dizzy(10) + M.adjustBrainLoss(10) + if(prob(30)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/bath_salts/addiction_act_stage3(var/mob/living/M as mob) + M.hallucination += 30 + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 12, i++) + step(M, pick(cardinal)) + M.Jitter(15) + M.Dizzy(15) + M.adjustBrainLoss(10) + if(prob(40)) + M.emote(pick("twitch","drool","moan")) + ..() + return +/datum/reagent/bath_salts/addiction_act_stage4(var/mob/living/carbon/human/M as mob) + M.hallucination += 40 + if(M.canmove && !istype(M.loc, /atom/movable)) + for(var/i = 0, i < 16, i++) + step(M, pick(cardinal)) + M.Jitter(50) + M.Dizzy(50) + M.adjustToxLoss(5) + M.adjustBrainLoss(10) + if(prob(50)) + M.emote(pick("twitch","drool","moan")) + ..() + return + +/datum/chemical_reaction/aranesp + name = "aranesp" + id = "aranesp" + result = "aranesp" + required_reagents = list("epinephrine" = 1, "atropine" = 1, "morphine" = 1) + result_amount = 3 + +/datum/reagent/aranesp + name = "Aranesp" + id = "aranesp" + description = "Amps you up and gets you going, fixes all stamina damage you might have but can cause toxin and oxygen damage.." + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + +/datum/reagent/aranesp/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.") + if(prob(5)) + M << "[high_message]" + M.adjustStaminaLoss(-35) + M.adjustToxLoss(1) + if(prob(50)) + M.losebreath++ + M.adjustOxyLoss(20) + ..() + return diff --git a/code/modules/reagents/Chemistry-Goon-Medicine.dm b/code/modules/reagents/Chemistry-Goon-Medicine.dm new file mode 100644 index 00000000000..2659fed7197 --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-Medicine.dm @@ -0,0 +1,831 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 + +#define REM REAGENTS_EFFECT_MULTIPLIER + +datum/reagent/silver_sulfadiazine + name = "Silver Sulfadiazine" + id = "silver_sulfadiazine" + description = "On touch, quickly heals burn damage. Basic anti-burn healing drug. On ingestion, deals minor toxin damage." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 2 + +datum/reagent/silver_sulfadiazine/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume, var/show_message = 1) + if(iscarbon(M)) + if(method == TOUCH) + M.adjustFireLoss(-volume) + if(show_message) + M << "You feel your burns healing!" + M.emote("scream") + if(method == INGEST) + M.adjustToxLoss(0.5*volume) + if(show_message) + M << "You probably shouldn't have eaten that. Maybe you should of splashed it on, or applied a patch?" + ..() + return + +datum/reagent/silver_sulfadiazine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustFireLoss(-2*REM) + ..() + return + +datum/reagent/styptic_powder + name = "Styptic Powder" + id = "styptic_powder" + description = "On touch, quickly heals brute damage. Basic anti-brute healing drug. On ingestion, deals minor toxin damage." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 2 + +datum/reagent/styptic_powder/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume, var/show_message = 1) + if(iscarbon(M)) + if(method == TOUCH) + M.adjustBruteLoss(-volume) + if(show_message) + M << "You feel your wounds knitting back together!" + M.emote("scream") + if(method == INGEST) + M.adjustToxLoss(0.5*volume) + if(show_message) + M << "You probably shouldn't have eaten that. Maybe you should of splashed it on, or applied a patch?" + ..() + return + +datum/reagent/styptic_powder/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(prob(55)) + M.adjustBruteLoss(-8*REM) + ..() + return + +datum/reagent/salglu_solution + name = "Saline-Glucose Solution" + id = "salglu_solution" + description = "Has a 33% chance per metabolism cycle to heal brute and burn damage." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/salglu_solution/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(prob(33)) + M.adjustBruteLoss(-1*REM) + M.adjustFireLoss(-1*REM) + ..() + return + +datum/reagent/synthflesh + name = "Synthflesh" + id = "synthflesh" + description = "Has a 100% chance of instantly healing brute and burn damage. One unit of the chemical will heal one point of damage. Touch application only." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/synthflesh/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume,var/show_message = 1) + if(!M) M = holder.my_atom + if(iscarbon(M)) + if(method == TOUCH) + M.adjustBruteLoss(-1.5*volume) + M.adjustFireLoss(-1.5*volume) + if(show_message) + M << "You feel your burns healing and your flesh knitting together!" + ..() + return + +datum/reagent/charcoal + name = "Charcoal" + id = "charcoal" + description = "Heals toxin damage, and will also slowly remove any other chemicals." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/charcoal/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(-3*REM) + for(var/datum/reagent/R in M.reagents.reagent_list) + if(R != src) + M.reagents.remove_reagent(R.id,1) + ..() + return + +/datum/chemical_reaction/charcoal + name = "Charcoal" + id = "charcoal" + result = "charcoal" + required_reagents = list("ash" = 1, "sodiumchloride" = 1) + result_amount = 2 + mix_message = "The mixture yields a fine black powder." + required_temp = 380 + +/datum/chemical_reaction/silver_sulfadiazine + name = "Silver Sulfadiazine" + id = "silver_sulfadiazine" + result = "silver_sulfadiazine" + required_reagents = list("ammonia" = 1, "silver" = 1, "sulfur" = 1, "oxygen" = 1, "chlorine" = 1) + result_amount = 5 + +/datum/chemical_reaction/salglu_solution + name = "Saline-Glucose Solution" + id = "salglu_solution" + result = "salglu_solution" + required_reagents = list("sodiumchloride" = 1, "water" = 1, "sugar" = 1) + result_amount = 3 + +/datum/chemical_reaction/synthflesh + name = "Synthflesh" + id = "synthflesh" + result = "synthflesh" + required_reagents = list("blood" = 1, "carbon" = 1, "styptic_powder" = 1) + result_amount = 3 + +/datum/chemical_reaction/styptic_powder + name = "Styptic Powder" + id = "styptic_powder" + result = "styptic_powder" + required_reagents = list("aluminium" = 1, "hydrogen" = 1, "oxygen" = 1, "sacid" = 1) + result_amount = 4 + mix_message = "The solution yields an astringent powder." + +datum/reagent/omnizine + name = "Omnizine" + id = "omnizine" + description = "Heals 1 of each damage type a cycle. If overdosed it will deal significant amounts of each damage type." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + overdose_threshold = 30 + +datum/reagent/omnizine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(-1*REM) + M.adjustOxyLoss(-1*REM) + M.adjustBruteLoss(-1*REM) + M.adjustFireLoss(-1*REM) + ..() + return + +datum/reagent/omnizine/overdose_process(var/mob/living/M as mob) + M.adjustToxLoss(3*REM) + M.adjustOxyLoss(3*REM) + M.adjustBruteLoss(3*REM) + M.adjustFireLoss(3*REM) + ..() + return + +datum/reagent/calomel + name = "Calomel" + id = "calomel" + description = "Quickly purges the body of all chemicals. If your health is above 20, toxin damage is dealt. When you hit 20 health or lower, the damage will cease." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/calomel/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + for(var/datum/reagent/R in M.reagents.reagent_list) + if(R != src) + M.reagents.remove_reagent(R.id,5) + if(M.health > 20) + M.adjustToxLoss(5*REM) + ..() + return + +/datum/chemical_reaction/calomel + name = "Calomel" + id = "calomel" + result = "calomel" + required_reagents = list("mercury" = 1, "chlorine" = 1) + result_amount = 2 + required_temp = 374 + +datum/reagent/potass_iodide + name = "Potassium Iodide" + id = "potass_iodide" + description = "Reduces low radiation damage very effectively." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/potass_iodide/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.radiation > 0) + if(prob(80)) + M.radiation-- + if(M.radiation < 0) + M.radiation = 0 + ..() + return + +/datum/chemical_reaction/potass_iodide + name = "Potassium Iodide" + id = "potass_iodide" + result = "potass_iodide" + required_reagents = list("potassium" = 1, "iodine" = 1) + result_amount = 2 + +datum/reagent/pen_acid + name = "Pentetic Acid" + id = "pen_acid" + description = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body. Has a chance of dealing brute damage." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/pen_acid/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.radiation > 0) + M.radiation -= 7 + M.adjustToxLoss(-4*REM) + if(prob(33)) + M.adjustBruteLoss(1*REM) + if(M.radiation < 0) + M.radiation = 0 + for(var/datum/reagent/R in M.reagents.reagent_list) + if(R != src) + M.reagents.remove_reagent(R.id,4) + ..() + return + +/datum/chemical_reaction/pen_acid + name = "Pentetic Acid" + id = "pen_acid" + result = "pen_acid" + required_reagents = list("fuel" = 1, "chlorine" = 1, "ammonia" = 1, "formaldehyde" = 1, "sodium" = 1, "cyanide" = 1) + result_amount = 6 + +datum/reagent/sal_acid + name = "Salicyclic Acid" + id = "sal_acid" + description = "If you have less than 50 brute damage, there is a 50% chance to heal one unit. If overdosed it will have a 50% chance to deal 2 brute damage if the patient has less than 50 brute damage already." + reagent_state = LIQUID + color = "#C8A5DC" + overdose_threshold = 25 + +datum/reagent/sal_acid/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.getBruteLoss() < 50) + if(prob(50)) + M.adjustBruteLoss(-1*REM) + ..() + return + +datum/reagent/sal_acid/overdose_process(var/mob/living/M as mob) + if(M.getBruteLoss() < 50) + if(prob(50)) + M.adjustBruteLoss(2*REM) + ..() + return + +/datum/chemical_reaction/sal_acid + name = "Salicyclic Acid" + id = "sal_acid" + result = "sal_acid" + required_reagents = list("sodium" = 1, "phenol" = 1, "carbon" = 1, "oxygen" = 1, "sacid" = 1) + result_amount = 5 + +datum/reagent/salbutamol + name = "Salbutamol" + id = "salbutamol" + description = "Quickly heals oxygen damage while slowing down suffocation. Great for stabilizing critical patients!" + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + +datum/reagent/salbutamol/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustOxyLoss(-6*REM) + if(M.losebreath >= 4) + M.losebreath -= 4 + ..() + return + +/datum/chemical_reaction/salbutamol + name = "Salbutamol" + id = "salbutamol" + result = "salbutamol" + required_reagents = list("sal_acid" = 1, "lithium" = 1, "aluminium" = 1, "bromine" = 1, "ammonia" = 1) + result_amount = 5 + +datum/reagent/perfluorodecalin + name = "Perfluorodecalin" + id = "perfluorodecalin" + description = "Heals suffocation damage so quickly that you could have a spacewalk, but it mutes your voice. Has a 33% chance of healing brute and burn damage per cycle as well." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + +datum/reagent/perfluorodecalin/on_mob_life(var/mob/living/carbon/human/M as mob) + if(!M) M = holder.my_atom + M.adjustOxyLoss(-25*REM) + M.silent = max(M.silent, 5) + if(prob(33)) + M.adjustBruteLoss(-1*REM) + M.adjustFireLoss(-1*REM) + ..() + return + +/datum/chemical_reaction/perfluorodecalin + name = "Perfluorodecalin" + id = "perfluorodecalin" + result = "perfluorodecalin" + required_reagents = list("hydrogen" = 1, "fluorine" = 1, "oil" = 1) + result_amount = 3 + required_temp = 370 + mix_message = "The mixture rapidly turns into a dense pink liquid." + +datum/reagent/ephedrine + name = "Ephedrine" + id = "ephedrine" + description = "Reduces stun times, increases run speed. If overdosed it will deal toxin and oxyloss damage." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.3 + overdose_threshold = 45 + addiction_threshold = 30 + +datum/reagent/ephedrine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.status_flags |= IGNORESLOWDOWN + M.AdjustParalysis(-1) + M.AdjustStunned(-1) + M.AdjustWeakened(-1) + M.adjustStaminaLoss(-1*REM) + ..() + return + +datum/reagent/ephedrine/overdose_process(var/mob/living/M as mob) + if(prob(33)) + M.adjustToxLoss(1*REM) + M.losebreath++ + ..() + return + +datum/reagent/ephedrine/addiction_act_stage1(var/mob/living/M as mob) + if(prob(33)) + M.adjustToxLoss(2*REM) + M.losebreath += 2 + ..() + return +datum/reagent/ephedrine/addiction_act_stage2(var/mob/living/M as mob) + if(prob(33)) + M.adjustToxLoss(3*REM) + M.losebreath += 3 + ..() + return +datum/reagent/ephedrine/addiction_act_stage3(var/mob/living/M as mob) + if(prob(33)) + M.adjustToxLoss(4*REM) + M.losebreath += 4 + ..() + return +datum/reagent/ephedrine/addiction_act_stage4(var/mob/living/M as mob) + if(prob(33)) + M.adjustToxLoss(5*REM) + M.losebreath += 5 + ..() + return + +/datum/chemical_reaction/ephedrine + name = "Ephedrine" + id = "ephedrine" + result = "ephedrine" + required_reagents = list("sugar" = 1, "oil" = 1, "hydrogen" = 1, "diethylamine" = 1) + result_amount = 4 + mix_message = "The solution fizzes and gives off toxic fumes." + +datum/reagent/diphenhydramine + name = "Diphenhydramine" + id = "diphenhydramine" + description = "Purges body of lethal Histamine and reduces jitteriness while causing minor drowsiness." + reagent_state = LIQUID + color = "#C8A5DC" +datum/reagent/diphenhydramine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.drowsyness += 1 + M.jitteriness -= 1 + M.reagents.remove_reagent("histamine",3) + ..() + return + +/datum/chemical_reaction/diphenhydramine + name = "Diphenhydramine" + id = "diphenhydramine" + result = "diphenhydramine" + required_reagents = list("oil" = 1, "carbon" = 1, "bromine" = 1, "diethylamine" = 1, "ethanol" = 1) + result_amount = 4 + mix_message = "The mixture dries into a pale blue powder." + +datum/reagent/morphine + name = "Morphine" + id = "morphine" + description = "Will allow you to ignore slowdown from equipment and damage. Will eventually knock you out if you take too much. If overdosed it will cause jitteriness, dizziness, force the victim to drop items in their hands and eventually deal toxin damage." + reagent_state = LIQUID + color = "#C8A5DC" + var/cycle_count = 0 + overdose_threshold = 30 + addiction_threshold = 25 + + +datum/reagent/morphine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.status_flags |= IGNORESLOWDOWN + if(cycle_count >= 36) + M.sleeping += 3 + cycle_count++ + ..() + return + +datum/reagent/morphine/overdose_process(var/mob/living/M as mob) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + M.Dizzy(1) + M.Jitter(1) + ..() + return + +datum/reagent/morphine/addiction_act_stage1(var/mob/living/M as mob) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + M.Dizzy(2) + M.Jitter(2) + ..() + return +datum/reagent/morphine/addiction_act_stage2(var/mob/living/M as mob) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + M.adjustToxLoss(1*REM) + M.Dizzy(3) + M.Jitter(3) + ..() + return +datum/reagent/morphine/addiction_act_stage3(var/mob/living/M as mob) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + M.adjustToxLoss(2*REM) + M.Dizzy(4) + M.Jitter(4) + ..() + return +datum/reagent/morphine/addiction_act_stage4(var/mob/living/M as mob) + if(prob(33)) + var/obj/item/I = M.get_active_hand() + if(I) + M.drop_item() + M.adjustToxLoss(3*REM) + M.Dizzy(5) + M.Jitter(5) + ..() + return + +datum/reagent/oculine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + cycle_amount++ + if(M.eye_blind > 0 && cycle_amount > 20) + if(prob(30)) + M.eye_blind = 0 + else if(prob(80)) + M.eye_blind = 0 + M.eye_blurry = 1 + if(M.eye_blurry > 0) + if(prob(80)) + M.eye_blurry = 0 + ..() + return + +/datum/chemical_reaction/oculine + name = "Oculine" + id = "oculine" + result = "oculine" + required_reagents = list("charcoal" = 1, "carbon" = 1, "hydrogen" = 1) + result_amount = 3 + mix_message = "The mixture sputters loudly and becomes a pale pink color." + +datum/reagent/oculine + name = "Oculine" + id = "oculine" + description = "Cures blindness and heals eye damage over time." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.4 + var/cycle_amount = 0 + +datum/reagent/atropine + name = "Atropine" + id = "atropine" + description = "If patients health is below -25 it will heal 3 brute and burn damage per cycle, as well as stop any oxyloss. Good for stabilising critical patients." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + overdose_threshold = 35 + +datum/reagent/atropine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.health > -60) + M.adjustToxLoss(1*REM) + if(M.health < -25) + M.adjustBruteLoss(-3*REM) + M.adjustFireLoss(-3*REM) + if(M.oxyloss > 65) + M.setOxyLoss(65) + if(M.losebreath > 5) + M.losebreath = 5 + if(prob(30)) + M.Dizzy(5) + M.Jitter(5) + ..() + return + +datum/reagent/atropine/overdose_process(var/mob/living/M as mob) + if(prob(50)) + M.adjustToxLoss(2*REM) + M.Dizzy(1) + M.Jitter(1) + ..() + return + +/datum/chemical_reaction/atropine + name = "Atropine" + id = "atropine" + result = "atropine" + required_reagents = list("ethanol" = 1, "acetone" = 1, "diethylamine" = 1, "phenol" = 1, "sacid" = 1) + result_amount = 5 + +datum/reagent/epinephrine + name = "Epinephrine" + id = "epinephrine" + description = "mReduces most of the knockout/stun effects, minor stamina regeneration buff. Attempts to stop you taking too much oxygen damage. If the patient is in low to severe crit, heals toxins, brute, and burn very effectively. Will not heal patients who are almost dead. If overdosed will stun and deal toxin damage" + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + overdose_threshold = 30 + +datum/reagent/epinephrine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.health < -10 && M.health > -65) + M.adjustToxLoss(-1*REM) + M.adjustBruteLoss(-1*REM) + M.adjustFireLoss(-1*REM) + if(M.oxyloss > 35) + M.setOxyLoss(35) + if(M.losebreath >= 4) + M.losebreath -= 4 + if(M.losebreath < 0) + M.losebreath = 0 + M.adjustStaminaLoss(-1*REM) + if(prob(30)) + M.AdjustParalysis(-1) + M.AdjustStunned(-1) + M.AdjustWeakened(-1) + ..() + return + +datum/reagent/epinephrine/overdose_process(var/mob/living/M as mob) + if(prob(33)) + M.adjustStaminaLoss(5*REM) + M.adjustToxLoss(2*REM) + M.losebreath++ + ..() + return + +/datum/chemical_reaction/epinephrine + name = "Epinephrine" + id = "epinephrine" + result = "epinephrine" + required_reagents = list("phenol" = 1, "acetone" = 1, "diethylamine" = 1, "oxygen" = 1, "chlorine" = 1, "hydrogen" = 1) + result_amount = 6 + +datum/reagent/strange_reagent + name = "Strange Reagent" + id = "strange_reagent" + description = "A miracle drug that can bring a dead body back to life! If the corpse has suffered too much damage, however, no change will occur to the body. If used on a living person it will deal Brute and Burn damage." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/strange_reagent/reaction_mob(var/mob/living/carbon/human/M as mob, var/method=TOUCH, var/volume) + if(M.stat == DEAD) + if(M.getBruteLoss() >= 100 || M.getFireLoss() >= 100) + M.visible_message("[M]'s body convulses a bit, and then falls still once more.") + return + var/mob/dead/observer/ghost = M.get_ghost() + M.visible_message("[M]'s body convulses a bit.") + if(!M.suiciding && !ghost && !(NOCLONE in M.mutations)) + M.stat = 1 + M.adjustOxyLoss(-20) + M.adjustToxLoss(-20) + dead_mob_list -= M + living_mob_list |= list(M) + M.emote("gasp") + add_logs(M, M, "revived", object="strange reagent") + ..() + return +datum/reagent/strange_reagent/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(prob(50)) + M.adjustBruteLoss(2*REM) + M.adjustFireLoss(2*REM) + ..() + return + +/datum/chemical_reaction/strange_reagent + name = "Strange Reagent" + id = "strange_reagent" + result = "strange_reagent" + required_reagents = list("omnizine" = 1, "holywater" = 1, "mutagen" = 1) + result_amount = 3 + +datum/reagent/life + name = "Life" + id = "life" + description = "Can create a life form, however it is not guaranteed to be friendly. May want to have Security on hot standby." + reagent_state = LIQUID + color = "#C8A5DC" + metabolization_rate = 0.2 + +/datum/chemical_reaction/life + name = "Life" + id = "life" + result = "life" + required_reagents = list("strange_reagent" = 1, "synthflesh" = 1, "blood" = 1) + result_amount = 3 + required_temp = 374 + +/datum/chemical_reaction/life/on_reaction(var/datum/reagents/holder, var/created_volume) + chemical_mob_spawn(holder, 1, "Life") + +proc/chemical_mob_spawn(var/datum/reagents/holder, var/amount_to_spawn, var/reaction_name, var/mob_faction = "chemicalsummon") + if(holder && holder.my_atom) + var/blocked = list(/mob/living/simple_animal/hostile, + /mob/living/simple_animal/hostile/pirate, + /mob/living/simple_animal/hostile/pirate/ranged, + /mob/living/simple_animal/hostile/russian, + /mob/living/simple_animal/hostile/russian/ranged, + /mob/living/simple_animal/hostile/syndicate, + /mob/living/simple_animal/hostile/syndicate/melee, + /mob/living/simple_animal/hostile/syndicate/melee/space, + /mob/living/simple_animal/hostile/syndicate/ranged, + /mob/living/simple_animal/hostile/syndicate/ranged/space, + /mob/living/simple_animal/hostile/alien/queen/large, + /mob/living/simple_animal/hostile/retaliate, + /mob/living/simple_animal/hostile/retaliate/clown, + /mob/living/simple_animal/hostile/mushroom, + /mob/living/simple_animal/hostile/asteroid, + /mob/living/simple_animal/hostile/asteroid/basilisk, + /mob/living/simple_animal/hostile/asteroid/goldgrub, + /mob/living/simple_animal/hostile/asteroid/goliath, + /mob/living/simple_animal/hostile/asteroid/hivelord, + /mob/living/simple_animal/hostile/asteroid/hivelordbrood, + /mob/living/simple_animal/hostile/carp/holocarp, + /mob/living/simple_animal/hostile/mining_drone, + /mob/living/simple_animal/hostile/poison, + /mob/living/simple_animal/hostile/blob, + /mob/living/simple_animal/ascendant_shadowling + )//exclusion list for things you don't want the reaction to create. + var/list/critters = typesof(/mob/living/simple_animal/hostile) - blocked // list of possible hostile mobs + var/atom/A = holder.my_atom + var/turf/T = get_turf(A) + var/area/my_area = get_area(T) + var/message = "A [reaction_name] reaction has occured in [my_area.name]. (JMP)" + message += " (VV)" + + var/mob/M = get(A, /mob) + if(M) + message += " - Carried By: [M.real_name] ([M.key]) (PP) (?)" + else + message += " - Last Fingerprint: [(A.fingerprintslast ? A.fingerprintslast : "N/A")]" + + message_admins(message, 0, 1) + + playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + + for(var/mob/living/carbon/human/H in viewers(get_turf(holder.my_atom), null)) + H.flash_eyes() + for(var/i = 1, i <= amount_to_spawn, i++) + var/chosen = pick(critters) + var/mob/living/simple_animal/hostile/C = new chosen + C.faction |= mob_faction + C.loc = get_turf(holder.my_atom) + if(prob(50)) + for(var/j = 1, j <= rand(1, 3), j++) + step(C, pick(NORTH,SOUTH,EAST,WEST)) + +/datum/reagent/mannitol/on_mob_life(mob/living/M as mob) + M.adjustBrainLoss(-3) + ..() + return + +/datum/chemical_reaction/mannitol + name = "Mannitol" + id = "mannitol" + result = "mannitol" + required_reagents = list("sugar" = 1, "hydrogen" = 1, "water" = 1) + result_amount = 3 + mix_message = "The solution slightly bubbles, becoming thicker." + +/datum/reagent/mannitol + name = "Mannitol" + id = "mannitol" + description = "Heals brain damage effectively. Use it in cyro tubes alongside Cryoxadone." + color = "#C8A5DC" + +/datum/reagent/mutadone/on_mob_life(var/mob/living/carbon/human/M as mob) + M.jitteriness = 0 + if(istype(M) && M.dna) + M.dna.remove_all_mutations() + ..() + return + +/datum/chemical_reaction/mutadone + name = "Mutadone" + id = "mutadone" + result = "mutadone" + required_reagents = list("mutagen" = 1, "acetone" = 1, "bromine" = 1) + result_amount = 3 + + +/datum/reagent/mutadone + name = "Mutadone" + id = "mutadone" + description = "Heals your genetic defects." + color = "#C8A5DC" + +datum/reagent/antihol + name = "Antihol" + id = "antihol" + description = "Helps remove Alcohol from someone's body, as well as eliminating its side effects." + color = "#C8A5DC" + +datum/reagent/antihol/on_mob_life(var/mob/living/M as mob) + M.dizziness = 0 + M.drowsyness = 0 + M.slurring = 0 + M.confused = 0 + M.reagents.remove_reagent("ethanol", 8) + M.adjustToxLoss(-0.2*REM) + ..() + +/datum/chemical_reaction/antihol + name = "antihol" + id = "antihol" + result = "antihol" + required_reagents = list("ethanol" = 1, "charcoal" = 1) + result_amount = 2 + +/datum/chemical_reaction/cryoxadone + name = "Cryoxadone" + id = "cryoxadone" + result = "cryoxadone" + required_reagents = list("stable_plasma" = 1, "acetone" = 1, "mutagen" = 1) + result_amount = 3 + +/datum/reagent/stimulants + name = "Stimulants" + id = "stimulants" + description = "Increases run speed and eliminates stuns, can heal minor damage. If overdosed it will deal toxin damage and stun." + color = "#C8A5DC" + metabolization_rate = 0.4 + overdose_threshold = 60 + +datum/reagent/stimulants/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.status_flags |= IGNORESLOWDOWN + if(M.health < 50 && M.health > 0) + if(prob(50)) + M.adjustOxyLoss(-5*REM) + M.adjustToxLoss(-5*REM) + M.adjustBruteLoss(-5*REM) + M.adjustFireLoss(-5*REM) + M.adjustFireLoss(-3*REM) + M.AdjustParalysis(-1) + M.AdjustStunned(-1) + M.AdjustWeakened(-1) + M.adjustStaminaLoss(-3*REM) + ..() + +datum/reagent/stimulants/overdose_process(var/mob/living/M as mob) + if(prob(33)) + M.adjustStaminaLoss(5*REM) + M.adjustToxLoss(2*REM) + M.losebreath++ + ..() + return + +datum/reagent/insulin + name = "Insulin" + id = "insulin" + description = "Increases sugar depletion rates." + reagent_state = LIQUID + color = "#C8A5DC" +datum/reagent/insulin/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.sleeping) + M.sleeping-- + M.reagents.remove_reagent("sugar", 5) + ..() + return diff --git a/code/modules/reagents/Chemistry-Goon-Other.dm b/code/modules/reagents/Chemistry-Goon-Other.dm new file mode 100644 index 00000000000..bda6a4441d8 --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-Other.dm @@ -0,0 +1,286 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 +#define REM REAGENTS_EFFECT_MULTIPLIER + +var/list/random_color_list = list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700") + +datum/reagent/oil + name = "Oil" + id = "oil" + description = "Burns in a small smoky fire, mostly used to get Ash." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/stable_plasma + name = "Stable Plasma" + id = "stable_plasma" + description = "Non-flammable plasma locked into a liquid form that cannot ignite or become gaseous/solid." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/iodine + name = "Iodine" + id = "iodine" + description = "A slippery solution." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/fluorine + name = "Fluorine" + id = "fluorine" + description = "A slippery solution." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/carpet + name = "Carpet" + id = "carpet" + description = "A slippery solution." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/reagent/carpet/reaction_turf(var/turf/simulated/T, var/volume) + if(istype(T, /turf/simulated/floor/plating) || istype(T, /turf/simulated/floor/plasteel)) + var/turf/simulated/floor/F = T + F.ChangeTurf(/turf/simulated/floor/fancy/carpet) + ..() + return + +datum/reagent/bromine + name = "Bromine" + id = "bromine" + description = "A slippery solution." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/phenol + name = "Phenol" + id = "phenol" + description = "Used for certain medical recipes." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/ash + name = "Ash" + id = "ash" + description = "Basic ingredient in a couple of recipes." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/acetone + name = "Acetone" + id = "acetone" + description = "Common ingredient in other recipes." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/acetone + name = "acetone" + id = "acetone" + result = "acetone" + required_reagents = list("oil" = 1, "fuel" = 1, "oxygen" = 1) + result_amount = 3 + +/datum/chemical_reaction/carpet + name = "carpet" + id = "carpet" + result = "carpet" + required_reagents = list("space_drugs" = 1, "blood" = 1) + result_amount = 2 + + +/datum/chemical_reaction/oil + name = "Oil" + id = "oil" + result = "oil" + required_reagents = list("fuel" = 1, "carbon" = 1, "hydrogen" = 1) + result_amount = 3 + +/datum/chemical_reaction/phenol + name = "phenol" + id = "phenol" + result = "phenol" + required_reagents = list("water" = 1, "chlorine" = 1, "oil" = 1) + result_amount = 3 + +/datum/chemical_reaction/ash + name = "Ash" + id = "ash" + result = "ash" + required_reagents = list("oil" = 1) + result_amount = 1 + required_temp = 480 + +datum/reagent/colorful_reagent + name = "Colorful Reagent" + id = "colorful_reagent" + description = "A solution." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/colorful_reagent + name = "colorful_reagent" + id = "colorful_reagent" + result = "colorful_reagent" + required_reagents = list("stable_plasma" = 1, "radium" = 1, "space_drugs" = 1, "cryoxadone" = 1, "triple_citrus" = 1) + result_amount = 5 + +datum/reagent/colorful_reagent/on_mob_life(var/mob/living/M as mob) + if(M && isliving(M)) + M.color = pick(random_color_list) + ..() + return + +datum/reagent/colorful_reagent/reaction_mob(var/mob/living/M, var/volume) + if(M && isliving(M)) + M.color = pick(random_color_list) + ..() + return +datum/reagent/colorful_reagent/reaction_obj(var/obj/O, var/volume) + if(O) + O.color = pick(random_color_list) + ..() + return +datum/reagent/colorful_reagent/reaction_turf(var/turf/T, var/volume) + if(T) + T.color = pick(random_color_list) + ..() + return + + +datum/reagent/triple_citrus + name = "Triple Citrus" + id = "triple_citrus" + description = "A solution." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/triple_citrus + name = "triple_citrus" + id = "triple_citrus" + result = "triple_citrus" + required_reagents = list("lemonjuice" = 1, "limejuice" = 1, "orangejuice" = 1) + result_amount = 5 + +datum/reagent/corn_starch + name = "Corn Starch" + id = "corn_starch" + description = "A slippery solution." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/corn_syrup + name = "corn_syrup" + id = "corn_syrup" + result = "corn_syrup" + required_reagents = list("corn_starch" = 1, "sacid" = 1) + result_amount = 5 + required_temp = 374 + +datum/reagent/corn_syrup + name = "Corn Syrup" + id = "corn_syrup" + description = "Decays into sugar." + reagent_state = LIQUID + color = "#C8A5DC" + +datum/reagent/corn_syrup/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.reagents.add_reagent("sugar", 3) + M.reagents.remove_reagent("corn_syrup", 1) + ..() + return + +/datum/chemical_reaction/corgium + name = "corgium" + id = "corgium" + result = "corgium" + required_reagents = list("nutriment" = 1, "colorful_reagent" = 1, "strange_reagent" = 1, "blood" = 1) + result_amount = 3 + required_temp = 374 + +datum/reagent/corgium + name = "Corgium" + id = "corgium" + description = "Creates a corgi at the reaction location." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/corgium/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + new /mob/living/simple_animal/pet/corgi(location) + ..() + return + +datum/reagent/hair_dye + name = "Quantum Hair Dye" + id = "hair_dye" + description = "A solution." + reagent_state = LIQUID + color = "#C8A5DC" + var/list/potential_colors = list("0ad","a0f","f73","d14","d14","0b5","0ad","f73","fc2","084","05e","d22","fa0") // fucking hair code + +/datum/chemical_reaction/hair_dye + name = "hair_dye" + id = "hair_dye" + result = "hair_dye" + required_reagents = list("colorful_reagent" = 1, "radium" = 1, "space_drugs" = 1) + result_amount = 5 + +datum/reagent/hair_dye/reaction_mob(var/mob/living/M, var/volume) + if(M && ishuman(M)) + var/mob/living/carbon/human/H = M + H.hair_color = pick(potential_colors) + H.facial_hair_color = pick(potential_colors) + H.update_hair() + ..() + return + +datum/reagent/barbers_aid + name = "Barber's Aid" + id = "barbers_aid" + description = "A solution to hair loss across the world." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/barbers_aid + name = "barbers_aid" + id = "barbers_aid" + result = "barbers_aid" + required_reagents = list("carpet" = 1, "radium" = 1, "space_drugs" = 1) + result_amount = 5 + +datum/reagent/barbers_aid/reaction_mob(var/mob/living/M, var/volume) + if(M && ishuman(M)) + var/mob/living/carbon/human/H = M + var/datum/sprite_accessory/hair/picked_hair = pick(hair_styles_list) + var/datum/sprite_accessory/facial_hair/picked_beard = pick(facial_hair_styles_list) + H.hair_style = picked_hair + H.facial_hair_style = picked_beard + H.update_hair() + ..() + return + +datum/reagent/concentrated_barbers_aid + name = "Concentrated Barber's Aid" + id = "concentrated_barbers_aid" + description = "A concentrated solution to hair loss across the world." + reagent_state = LIQUID + color = "#C8A5DC" + +/datum/chemical_reaction/concentrated_barbers_aid + name = "concentrated_barbers_aid" + id = "concentrated_barbers_aid" + result = "concentrated_barbers_aid" + required_reagents = list("barbers_aid" = 1, "mutagen" = 1) + result_amount = 2 + +datum/reagent/concentrated_barbers_aid/reaction_mob(var/mob/living/M, var/volume) + if(M && ishuman(M)) + var/mob/living/carbon/human/H = M + H.hair_style = "Very Long Hair" + H.facial_hair_style = "Very Long Beard" + H.update_hair() + ..() + return \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm b/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm new file mode 100644 index 00000000000..0e3b34e44cb --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm @@ -0,0 +1,486 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 + +#define REM REAGENTS_EFFECT_MULTIPLIER + +/datum/reagent/stabilizing_agent + name = "Stabilizing Agent" + id = "stabilizing_agent" + description = "Keeps unstable chemicals stable. This does not work on everything." + reagent_state = LIQUID + color = "#FFFFFF" + +/datum/chemical_reaction/stabilizing_agent + name = "stabilizing_agent" + id = "stabilizing_agent" + result = "stabilizing_agent" + required_reagents = list("iron" = 1, "oxygen" = 1, "hydrogen" = 1) + result_amount = 3 + +/datum/reagent/clf3 + name = "Chlorine Trifluoride" + id = "clf3" + description = "Makes a temporary 3x3 fireball when it comes into existence, so be careful when mixing. ClF3 applied to a surface burns things that wouldn't otherwise burn, sometimes through the very floors of the station and exposing it to the vacuum of space." + reagent_state = LIQUID + color = "#FF0000" + metabolization_rate = 4 + +/datum/chemical_reaction/clf3 + name = "Chlorine Trifluoride" + id = "clf3" + result = "clf3" + required_reagents = list("chlorine" = 1, "fluorine" = 3) + result_amount = 4 + required_temp = 424 + +/datum/reagent/clf3/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjust_fire_stacks(4) + M.adjustFireLoss(0.35*M.fire_stacks) + ..() + return + +/datum/chemical_reaction/clf3/on_reaction(var/datum/reagents/holder, var/created_volume) + var/turf/T = get_turf(holder.my_atom) + for(var/turf/turf in range(1,T)) + new /obj/effect/hotspot(turf) + holder.chem_temp = 1000 // hot as shit + return + +/datum/reagent/clf3/reaction_turf(var/turf/simulated/T, var/volume) + if(istype(T, /turf/simulated/floor/plating)) + var/turf/simulated/floor/plating/F = T + if(prob(1)) + F.ChangeTurf(/turf/space) + if(istype(T, /turf/simulated/floor/)) + var/turf/simulated/floor/F = T + if(prob(volume/10)) + F.make_plating() + if(istype(F, /turf/simulated/floor/)) + new /obj/effect/hotspot(F) + if(istype(T, /turf/simulated/wall/)) + var/turf/simulated/wall/W = T + if(prob(volume/10)) + W.ChangeTurf(/turf/simulated/floor) + return + +/datum/reagent/clf3/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) + if(method == TOUCH && isliving(M)) + M.adjust_fire_stacks(5) + M.IgniteMob() + new /obj/effect/hotspot(M.loc) + return + +/datum/reagent/sorium + name = "Sorium" + id = "sorium" + description = "Sends everything flying from the detonation point." + reagent_state = LIQUID + color = "#FFA500" + +/datum/chemical_reaction/sorium + name = "Sorium" + id = "sorium" + result = "sorium" + required_reagents = list("mercury" = 1, "oxygen" = 1, "nitrogen" = 1, "carbon" = 1) + result_amount = 4 + +/datum/chemical_reaction/sorium_vortex + name = "sorium_vortex" + id = "sorium_vortex" + result = null + required_reagents = list("sorium" = 1) + required_temp = 474 + +/datum/chemical_reaction/sorium_vortex/on_reaction(var/datum/reagents/holder, var/created_volume) + var/turf/simulated/T = get_turf(holder.my_atom) + goonchem_vortex(T, 1, 5, 6) + +/datum/chemical_reaction/sorium/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + holder.remove_reagent("sorium", created_volume) + var/turf/simulated/T = get_turf(holder.my_atom) + goonchem_vortex(T, 1, 5, 6) + +/datum/reagent/liquid_dark_matter + name = "Liquid Dark Matter" + id = "liquid_dark_matter" + description = "Sucks everything into the detonation point." + reagent_state = LIQUID + color = "#800080" + +/datum/chemical_reaction/liquid_dark_matter + name = "Liquid Dark Matter" + id = "liquid_dark_matter" + result = "liquid_dark_matter" + required_reagents = list("stable_plasma" = 1, "radium" = 1, "carbon" = 1) + result_amount = 3 + +/datum/chemical_reaction/ldm_vortex + name = "LDM Vortex" + id = "ldm_vortex" + result = null + required_reagents = list("liquid_dark_matter" = 1) + required_temp = 474 + +/datum/chemical_reaction/ldm_vortex/on_reaction(var/datum/reagents/holder, var/created_volume) + var/turf/simulated/T = get_turf(holder.my_atom) + goonchem_vortex(T, 0, 5, 6) + return +/datum/chemical_reaction/liquid_dark_matter/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + holder.remove_reagent("liquid_dark_matter", created_volume) + var/turf/simulated/T = get_turf(holder.my_atom) + goonchem_vortex(T, 0, 5, 6) + return + +/proc/goonchem_vortex(var/turf/simulated/T, var/setting_type, var/range, var/pull_times) + for(var/atom/movable/X in orange(range, T)) + if(istype(X, /obj/effect)) + continue //stop pulling smoke and hotspots please + if(istype(X, /atom/movable)) + if((X) && !X.anchored) + if(setting_type) + for(var/i = 0, i < pull_times, i++) + step_away(X,T) + else + for(var/i = 0, i < pull_times, i++) + step_towards(X,T) + +/datum/reagent/blackpowder + name = "Black Powder" + id = "blackpowder" + description = "Explodes. Violently." + reagent_state = LIQUID + color = "#000000" + metabolization_rate = 0.05 + +/datum/chemical_reaction/blackpowder + name = "Black Powder" + id = "blackpowder" + result = "blackpowder" + required_reagents = list("saltpetre" = 1, "charcoal" = 1, "sulfur" = 1) + result_amount = 3 + +/datum/chemical_reaction/blackpowder_explosion + name = "Black Powder Kaboom" + id = "blackpowder_explosion" + result = null + required_reagents = list("blackpowder" = 1) + result_amount = 1 + required_temp = 474 + mix_message = "Sparks start flying around the black powder!" + +/datum/chemical_reaction/blackpowder_explosion/on_reaction(var/datum/reagents/holder, var/created_volume) + sleep(rand(50,100)) + blackpowder_detonate(holder, created_volume) + return + +/datum/reagent/blackpowder/on_ex_act() + blackpowder_detonate(holder, volume) + return + +/proc/blackpowder_detonate(var/datum/reagents/holder, var/created_volume) + var/turf/simulated/T = get_turf(holder.my_atom) + var/ex_severe = round(created_volume / 100) + var/ex_heavy = round(created_volume / 42) + var/ex_light = round(created_volume / 21) + var/ex_flash = round(created_volume / 8) + explosion(T,ex_severe,ex_heavy,ex_light,ex_flash, 1) + return +/datum/reagent/flash_powder + name = "Flash Powder" + id = "flash_powder" + description = "Makes a very bright flash." + reagent_state = LIQUID + color = "#FFFF00" + +/datum/chemical_reaction/flash_powder + name = "Flash powder" + id = "flash_powder" + result = "flash_powder" + required_reagents = list("aluminium" = 1, "potassium" = 1, "sulfur" = 1 ) + result_amount = 3 + +/datum/chemical_reaction/flash_powder_flash + name = "Flash powder activation" + id = "flash_powder_flash" + result = null + required_reagents = list("flash_powder" = 1) + required_temp = 374 + +/datum/chemical_reaction/flash_powder_flash/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, location) + s.start() + for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) + if(C.check_eye_prot()) + continue + flick("e_flash", C.flash) + if(get_dist(C, location) < 4) + C.Weaken(5) + continue + C.Stun(5) + +/datum/chemical_reaction/flash_powder/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + var/location = get_turf(holder.my_atom) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, location) + s.start() + for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) + if(C.check_eye_prot()) + continue + flick("e_flash", C.flash) + if(get_dist(C, location) < 4) + C.Weaken(5) + continue + C.Stun(5) + holder.remove_reagent("flash_powder", created_volume) + +/datum/reagent/smoke_powder + name = "Smoke Powder" + id = "smoke_powder" + description = "Makes a large cloud of smoke that can carry reagents." + reagent_state = LIQUID + color = "#808080" + +/datum/chemical_reaction/smoke_powder + name = "smoke_powder" + id = "smoke_powder" + result = "smoke_powder" + required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1) + result_amount = 3 + + +/datum/chemical_reaction/smoke_powder_smoke + name = "smoke_powder_smoke" + id = "smoke_powder_smoke" + result = null + required_reagents = list("smoke_powder" = 1) + required_temp = 374 + secondary = 1 + mob_react = 1 + +/datum/chemical_reaction/smoke_powder_smoke/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + var/datum/effect/effect/system/chem_smoke_spread/S = new /datum/effect/effect/system/chem_smoke_spread + S.attach(location) + playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3) + spawn(0) + if(S) + S.set_up(holder, 10, 0, location) + S.start() + sleep(10) + S.start() + if(holder && holder.my_atom) + holder.clear_reagents() + return + +/datum/chemical_reaction/smoke_powder/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + holder.remove_reagent("smoke_powder", created_volume) + var/location = get_turf(holder.my_atom) + var/datum/effect/effect/system/chem_smoke_spread/S = new /datum/effect/effect/system/chem_smoke_spread + S.attach(location) + playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3) + spawn(0) + if(S) + S.set_up(holder, 10, 0, location) + S.start() + sleep(10) + S.start() + if(holder && holder.my_atom) + holder.clear_reagents() + return + +/datum/reagent/sonic_powder + name = "Sonic Powder" + id = "sonic_powder" + description = "Makes a deafening noise." + reagent_state = LIQUID + color = "#0000FF" + +/datum/chemical_reaction/sonic_powder + name = "sonic_powder" + id = "sonic_powder" + result = "sonic_powder" + required_reagents = list("oxygen" = 1, "cola" = 1, "phosphorus" = 1) + result_amount = 3 + + +/datum/chemical_reaction/sonic_powder_deafen + name = "sonic_powder_deafen" + id = "sonic_powder_deafen" + result = null + required_reagents = list("sonic_powder" = 1) + required_temp = 374 + +/datum/chemical_reaction/sonic_powder_deafen/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + playsound(location, 'sound/effects/bang.ogg', 25, 1) + for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if((H.ears && (H.ears.flags & EARBANGPROTECT)) || (H.head && (H.head.flags & HEADBANGPROTECT))) + continue + C.show_message("BANG", 2) + C.Stun(5) + C.Weaken(5) + C.setEarDamage(C.ear_damage + rand(0, 5), max(C.ear_deaf,15)) + if(C.ear_damage >= 15) + C << "Your ears start to ring badly!" + else if(C.ear_damage >= 5) + C << "Your ears start to ring!" + +/datum/chemical_reaction/sonic_powder/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + holder.remove_reagent("sonic_powder", created_volume) + var/location = get_turf(holder.my_atom) + playsound(location, 'sound/effects/bang.ogg', 25, 1) + for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/10, location)) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if((H.ears && (H.ears.flags & EARBANGPROTECT)) || (H.head && (H.head.flags & HEADBANGPROTECT))) + continue + C.show_message("BANG", 2) + C.Stun(5) + C.Weaken(5) + C.setEarDamage(C.ear_damage + rand(0, 5), max(C.ear_deaf,15)) + if(C.ear_damage >= 15) + C << "Your ears start to ring badly!" + else if(C.ear_damage >= 5) + C << "Your ears start to ring!" + +/datum/reagent/phlogiston + name = "Phlogiston" + id = "phlogiston" + description = "Catches you on fire and makes you ignite." + reagent_state = LIQUID + color = "#FF9999" + +/datum/chemical_reaction/phlogiston + name = "phlogiston" + id = "phlogiston" + result = "phlogiston" + required_reagents = list("phosphorus" = 1, "sacid" = 1, "stable_plasma" = 1) + result_amount = 3 + +/datum/chemical_reaction/phlogiston/on_reaction(var/datum/reagents/holder, var/created_volume) + if(holder.has_reagent("stabilizing_agent")) + return + var/turf/simulated/T = get_turf(holder.my_atom) + if(istype(T)) + T.atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, created_volume) + return + +/datum/reagent/phlogiston/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjust_fire_stacks(1) + M.IgniteMob() + M.adjustFireLoss(0.2*M.fire_stacks) + ..() + return + +/datum/reagent/napalm + name = "Napalm" + id = "napalm" + description = "Very flammable." + reagent_state = LIQUID + color = "#FF9999" + +/datum/reagent/napalm/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjust_fire_stacks(1) + ..() + return + +/datum/reagent/napalm/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) + if(method == TOUCH && isliving(M)) + M.adjust_fire_stacks(7) + return + +/datum/chemical_reaction/napalm + name = "Napalm" + id = "napalm" + result = "napalm" + required_reagents = list("sugar" = 1, "fuel" = 1, "ethanol" = 1 ) + result_amount = 3 + +datum/reagent/cryostylane + name = "Cryostylane" + id = "cryostylane" + description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Cryostylane slowly cools all other reagents in the mob down to 0K." + color = "#B2B2FF" // rgb: 139, 166, 233 + +/datum/chemical_reaction/cryostylane + name = "cryostylane" + id = "cryostylane" + result = "cryostylane" + required_reagents = list("water" = 1, "stable_plasma" = 1, "nitrogen" = 1) + result_amount = 3 + +/datum/chemical_reaction/cryostylane/on_reaction(var/datum/reagents/holder, var/created_volume) + holder.chem_temp = 20 // cools the fuck down + return + + +datum/reagent/cryostylane/on_mob_life(var/mob/living/M as mob) //TODO: code freezing into an ice cube + if(M.reagents.has_reagent("oxygen")) + M.reagents.remove_reagent("oxygen", 1) + M.bodytemperature -= 30 + ..() + return + +datum/reagent/cryostylane/on_tick() + if(holder.has_reagent("oxygen")) + holder.remove_reagent("oxygen", 1) + holder.chem_temp -= 10 + holder.handle_reactions() + ..() + return + + +datum/reagent/cryostylane/reaction_turf(var/turf/simulated/T, var/volume) + if(volume >= 5) + for(var/mob/living/simple_animal/slime/M in T) + M.adjustToxLoss(rand(15,30)) + +datum/reagent/pyrosium + name = "Pyrosium" + id = "pyrosium" + description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly cools all other reagents in the mob down to 0K." + color = "#B20000" // rgb: 139, 166, 233 + +/datum/chemical_reaction/pyrosium + name = "pyrosium" + id = "pyrosium" + result = "pyrosium" + required_reagents = list("stable_plasma" = 1, "radium" = 1, "phosphorus" = 1) + result_amount = 3 + +/datum/chemical_reaction/pyrosium/on_reaction(var/datum/reagents/holder, var/created_volume) + holder.chem_temp = 20 // also cools the fuck down + return + +datum/reagent/pyrosium/on_mob_life(var/mob/living/M as mob) + if(M.reagents.has_reagent("oxygen")) + M.reagents.remove_reagent("oxygen", 1) + M.bodytemperature += 30 + ..() + return + +datum/reagent/pyrosium/on_tick() + if(holder.has_reagent("oxygen")) + holder.remove_reagent("oxygen", 1) + holder.chem_temp += 10 + holder.handle_reactions() + ..() + return diff --git a/code/modules/reagents/Chemistry-Goon-Readme.dm b/code/modules/reagents/Chemistry-Goon-Readme.dm new file mode 100644 index 00000000000..0731e28ba93 --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-Readme.dm @@ -0,0 +1,34 @@ +/* + Credit goes to Cogwerks, and all the other goonstation coders + for the original idea and implementation of this over at goonstation. + + THE REQUESTED DON'T PORT LIST: IF YOU PORT THESE THE GOONS WILL MURDER US IN OUR SLEEP SO PLEASE DON'T KTHX - Iamgoofball + Any of the Secret Chems + Goon in-joke chems (Eg. Cat Drugs, Hairgrownium) + Liquid Electricity + Rajajajah + + +/datum/reagent/blankgoonchembase + name = "blank goonchem base" + id = "blankgoonchembase" + description = "A blank chem" + reagent_state = LIQUID + color = "#60A584" // rgb: 96, 165, 132 + + +/datum/reagent/blankgoonchembase/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + ..() + return + +/datum/chemical_reaction/blankgoonchembase + name = "blank goonchem base" + id = "blankgoonchembase" + result = "blankgoonchembase" + required_reagents = list("diphenhydramine" = 1, "morphine" = 1, "cleaner" = 1) + result_amount = 3 + mix_message = "The mixture dries into a pale blue powder." + required_temp = 420 + +*/ \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Goon-Toxins.dm b/code/modules/reagents/Chemistry-Goon-Toxins.dm new file mode 100644 index 00000000000..b8ebe016012 --- /dev/null +++ b/code/modules/reagents/Chemistry-Goon-Toxins.dm @@ -0,0 +1,369 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 + +#define REM REAGENTS_EFFECT_MULTIPLIER + +datum/reagent/polonium + name = "Polonium" + id = "polonium" + description = "Cause significant Radiation damage over time." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.1 + +datum/reagent/polonium/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.radiation += 8 + ..() + return + + +datum/reagent/histamine + name = "Histamine" + id = "histamine" + description = "A dose-dependent toxin, ranges from annoying to incredibly lethal." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.2 + overdose_threshold = 30 + +datum/reagent/histamine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + switch(pick(1, 2, 3, 4)) + if(1) + M << "You can barely see!" + M.eye_blurry = 3 + if(2) + M.emote("cough") + if(3) + M.emote("sneeze") + if(4) + if(prob(75)) + M << "You scratch at an itch." + M.adjustBruteLoss(2*REM) + ..() + return +datum/reagent/histamine/overdose_process(var/mob/living/M as mob) + M.adjustOxyLoss(pick(1,3)*REM) + M.adjustBruteLoss(pick(1,3)*REM) + M.adjustToxLoss(pick(1,3)*REM) + ..() + return + +datum/reagent/formaldehyde + name = "Formaldehyde" + id = "formaldehyde" + description = "Deals a moderate amount of Toxin damage over time. 10% chance to decay into 10-15 histamine." + reagent_state = LIQUID + color = "#CF3600" + +datum/reagent/formaldehyde/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(1*REM) + if(prob(10)) + M.reagents.add_reagent("histamine",pick(5,15)) + M.reagents.remove_reagent("formaldehyde",1) + ..() + return + +/datum/chemical_reaction/formaldehyde + name = "formaldehyde" + id = "Formaldehyde" + result = "formaldehyde" + required_reagents = list("ethanol" = 1, "oxygen" = 1, "silver" = 1) + result_amount = 3 + required_temp = 420 + +datum/reagent/venom + name = "Venom" + id = "venom" + description = "Will deal scaling amounts of Toxin and Brute damage over time. 25% chance to decay into 5-10 histamine." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.2 +datum/reagent/venom/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss((0.1*volume)*REM) + M.adjustBruteLoss((0.1*volume)*REM) + if(prob(25)) + M.reagents.add_reagent("histamine",pick(5,10)) + M.reagents.remove_reagent("venom",1) + ..() + return + +datum/reagent/neurotoxin2 + name = "Neurotoxin" + id = "neurotoxin2" + description = "Deals toxin and brain damage up to 60 before it slows down, causing confusion and a knockout after 17 elapsed cycles." + reagent_state = LIQUID + color = "#CF3600" + var/cycle_count = 0 + metabolization_rate = 1 + +datum/reagent/neurotoxin2/on_mob_life(var/mob/living/M as mob) + cycle_count++ + if(M.brainloss + M.toxloss <= 60) + M.adjustBrainLoss(1*REM) + M.adjustToxLoss(1*REM) + if(cycle_count == 17) + M.sleeping += 10 // buffed so it works + ..() + return + +/datum/chemical_reaction/neurotoxin2 + name = "neurotoxin2" + id = "neurotoxin2" + result = "neurotoxin2" + required_reagents = list("space_drugs" = 1) + result_amount = 1 + required_temp = 674 + +datum/reagent/cyanide + name = "Cyanide" + id = "cyanide" + description = "Deals toxin damage, alongside some oxygen loss. 8% chance of stun and some extra toxin damage." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.1 + +datum/reagent/cyanide/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(1.5*REM) + if(prob(10)) + M.losebreath += 1 + if(prob(8)) + M << "You feel horrendously weak!" + M.Stun(2) + M.adjustToxLoss(2*REM) + ..() + return + +/datum/chemical_reaction/cyanide + name = "Cyanide" + id = "cyanide" + result = "cyanide" + required_reagents = list("oil" = 1, "ammonia" = 1, "oxygen" = 1) + result_amount = 3 + required_temp = 380 + +/datum/reagent/questionmark // food poisoning + name = "Bad Food" + id = "????" + description = "????" + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.2 + +datum/reagent/questionmark/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(1*REM) + ..() + return + +datum/reagent/itching_powder + name = "Itching Powder" + id = "itching_powder" + description = "Lots of annoying random effects, chances to do some brute damage from scratching. 6% chance to decay into 1-3 units of histamine." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.3 + +/datum/reagent/itching_powder/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) + if(method == TOUCH) + M.reagents.add_reagent("itching_powder", volume) + return + +datum/reagent/itching_powder/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(prob(27)) + M << "You scratch at your head." + M.adjustBruteLoss(0.2*REM) + if(prob(27)) + M << "You scratch at your leg." + M.adjustBruteLoss(0.2*REM) + if(prob(27)) + M << "You scratch at your arm." + M.adjustBruteLoss(0.2*REM) + if(prob(6)) + M.reagents.add_reagent("histamine",rand(1,3)) + M.reagents.remove_reagent("itching_powder",1) + ..() + return + +/datum/chemical_reaction/itching_powder + name = "Itching Powder" + id = "itching_powder" + result = "itching_powder" + required_reagents = list("fuel" = 1, "ammonia" = 1, "charcoal" = 1) + result_amount = 3 + +/datum/chemical_reaction/facid + name = "Fluorosulfuric acid" + id = "facid" + result = "facid" + required_reagents = list("sacid" = 1, "fluorine" = 1, "hydrogen" = 1, "potassium" = 1) + result_amount = 4 + required_temp = 380 + +datum/reagent/initropidril + name = "Initropidril" + id = "initropidril" + description = "33% chance to hit with a random amount of toxin damage, 5-10% chances to cause stunning, suffocation, or immediate heart failure." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.4 + +datum/reagent/initropidril/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(prob(33)) + M.adjustToxLoss(rand(5,25)) + if(prob(7)) + var/picked_option = rand(1,3) + switch(picked_option) + if(1) + M.Stun(3) + M.Weaken(3) + if(2) + M.losebreath += 10 + M.adjustOxyLoss(rand(5,25)) + if(3) + var/mob/living/carbon/human/H = M + if(!H.heart_attack) + H.visible_message("[H] clutches at their chest as if their heart stopped!", "You clutch at your chest as if your heart stopped!") + H.heart_attack = 1 // rip in pepperoni + else + H.losebreath += 10 + H.adjustOxyLoss(rand(5,25)) + ..() + return + +datum/reagent/pancuronium + name = "Pancuronium" + id = "pancuronium" + description = "Knocks you out after 30 seconds, 7% chance to cause some oxygen loss." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.2 + +datum/reagent/pancuronium/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(current_cycle >= 10) + M.SetParalysis(3) + if(prob(7)) + M.losebreath += rand(3,5) + ..() + return + +datum/reagent/sodium_thiopental + name = "Sodium Thiopental" + id = "sodium_thiopental" + description = "Puts you to sleep after 30 seconds, along with some major stamina loss." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.7 + +datum/reagent/sodium_thiopental/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(current_cycle >= 10) + M.sleeping += 3 + M.adjustStaminaLoss(10) + ..() + return + +datum/reagent/sulfonal + name = "Sulfonal" + id = "sulfonal" + description = "Deals some toxin damage, and puts you to sleep after 66 seconds." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.1 + +/datum/chemical_reaction/sulfonal + name = "sulfonal" + id = "sulfonal" + result = "sulfonal" + required_reagents = list("acetone" = 1, "diethylamine" = 1, "sulfur" = 1) + result_amount = 3 + +datum/reagent/sulfonal/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(current_cycle >= 22) + M.sleeping += 3 + M.adjustToxLoss(1) + ..() + return + +datum/reagent/amanitin + name = "Amanitin" + id = "amanitin" + description = "On the last second that it's in you, it hits you with a stack of toxin damage based on how long it's been in you. The more you use, the longer it takes before anything happens, but the harder it hits when it does." + reagent_state = LIQUID + color = "#CF3600" + +datum/reagent/amanitin/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + ..() + return + +datum/reagent/amanitin/on_mob_delete(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.adjustToxLoss(current_cycle*rand(2,4)) + ..() + +datum/reagent/lipolicide + name = "Lipolicide" + id = "lipolicide" + description = "Deals some toxin damage unless they keep eating food. Will reduce nutrition values." + reagent_state = LIQUID + color = "#CF3600" + +/datum/chemical_reaction/lipolicide + name = "lipolicide" + id = "lipolicide" + result = "lipolicide" + required_reagents = list("mercury" = 1, "diethylamine" = 1, "ephedrine" = 1) + result_amount = 3 + +datum/reagent/lipolicide/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(!holder.has_reagent("nutriment")) + M.adjustToxLoss(1) + M.nutrition -= 10 * REAGENTS_METABOLISM + M.overeatduration = 0 + if(M.nutrition < 0)//Prevent from going into negatives. + M.nutrition = 0 + ..() + return + +datum/reagent/coniine + name = "Coniine" + id = "coniine" + description = "Does moderate toxin damage and oxygen loss." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.05 + +datum/reagent/coniine/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + M.losebreath += 5 + M.adjustToxLoss(2) + ..() + return + +datum/reagent/curare + name = "Curare" + id = "curare" + description = "Does some oxygen and toxin damage, weakens you after 33 seconds." + reagent_state = LIQUID + color = "#CF3600" + metabolization_rate = 0.1 + +datum/reagent/curare/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(current_cycle >= 11) + M.Weaken(3) + M.adjustToxLoss(1) + M.adjustOxyLoss(1) + ..() + return \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents.dm new file mode 100644 index 00000000000..d86016f96ab --- /dev/null +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents.dm @@ -0,0 +1,956 @@ +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 + +#define REM REAGENTS_EFFECT_MULTIPLIER + +//The reaction procs must ALWAYS set src = null, this detaches the proc from the object (the reagent) +//so that it can continue working when the reagent is deleted while the proc is still active. + + +//Various reagents +//Toxin & acid reagents +//Hydroponics stuff + +datum/reagent + var/name = "Reagent" + var/id = "reagent" + var/description = "" + var/datum/reagents/holder = null + var/reagent_state = LIQUID + var/list/data + var/current_cycle = 0 + var/volume = 0 + var/color = "#000000" // rgb: 0, 0, 0 + var/can_synth = 1 + var/metabolization_rate = REAGENTS_METABOLISM + var/overrides_metab = 0 + var/overdose_threshold = 0 + var/addiction_threshold = 0 + var/addiction_stage = 0 + var/overdosed = 0 // You fucked up and this is now triggering it's overdose effects, purge that shit quick. + +datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references + ..() + holder = null + +datum/reagent/proc/reaction_mob(var/mob/M, var/method=TOUCH, var/volume, var/show_message = 1) //By default we have a chance to transfer some + if(!istype(M, /mob/living)) + return 0 + var/datum/reagent/self = src + src = null //of the reagent to the mob on TOUCHING it. + + if(!istype(self.holder.my_atom, /obj/effect/effect/chem_smoke)) + // If the chemicals are in a smoke cloud, do not try to let the chemicals "penetrate" into the mob's system (balance station 13) -- Doohl + + if(method == TOUCH) + + var/chance = 1 + var/block = 0 + + for(var/obj/item/clothing/C in M.get_equipped_items()) + if(C.permeability_coefficient < chance) chance = C.permeability_coefficient + if(istype(C, /obj/item/clothing/suit/bio_suit)) + // bio suits are just about completely fool-proof - Doohl + // kind of a hacky way of making bio suits more resistant to chemicals but w/e + if(prob(75)) + block = 1 + + if(istype(C, /obj/item/clothing/head/bio_hood)) + if(prob(75)) + block = 1 + + chance = chance * 100 + + if(prob(chance) && !block) + if(M.reagents) + M.reagents.add_reagent(self.id,self.volume/2) + return 1 + +datum/reagent/proc/reaction_obj(var/obj/O, var/volume) //By default we transfer a small part of the reagent to the object + src = null //if it can hold reagents. nope! + //if(O.reagents) + // O.reagents.add_reagent(id,volume/3) + return + +datum/reagent/proc/reaction_turf(var/turf/T, var/volume) + src = null + return + +datum/reagent/proc/on_mob_life(var/mob/living/M as mob) + current_cycle++ + if(!istype(M, /mob/living)) + return //Noticed runtime errors from facid trying to damage ghosts, this should fix. --NEO + holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears. + return + +// Called when this reagent is removed while inside a mob +datum/reagent/proc/on_mob_delete(mob/M) + return + +datum/reagent/proc/on_move(var/mob/M) + return + +// Called after add_reagents creates a new reagent. +datum/reagent/proc/on_new(var/data) + return + +// Called when two reagents of the same are mixing. +datum/reagent/proc/on_merge(var/data) + return + +datum/reagent/proc/on_update(var/atom/A) + return + +// Called every time reagent containers process. +datum/reagent/proc/on_tick(var/data) + return + +// Called when the reagent container is hit by an explosion +datum/reagent/proc/on_ex_act(var/severity) + return + +// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects +datum/reagent/proc/overdose_process(var/mob/living/M as mob) + return + +datum/reagent/proc/overdose_start(var/mob/living/M as mob) + return + +datum/reagent/proc/addiction_act_stage1(var/mob/living/M as mob) + if(prob(30)) + M << "You feel like some [name] right about now." + return + +datum/reagent/proc/addiction_act_stage2(var/mob/living/M as mob) + if(prob(30)) + M << "You feel like you need [name]. You just can't get enough." + return + +datum/reagent/proc/addiction_act_stage3(var/mob/living/M as mob) + if(prob(30)) + M << "You have an intense craving for [name]." + return + +datum/reagent/proc/addiction_act_stage4(var/mob/living/M as mob) + if(prob(30)) + M << "You're not feeling good at all! You really need some [name]." + return + +datum/reagent/blood + data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null) + name = "Blood" + id = "blood" + color = "#C80000" // rgb: 200, 0, 0 + +datum/reagent/blood/reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + var/datum/reagent/blood/self = src + src = null + if(self.data && self.data["viruses"]) + for(var/datum/disease/D in self.data["viruses"]) + + if(D.spread_flags & SPECIAL || D.spread_flags & NON_CONTAGIOUS) + continue + + if(method == TOUCH) + M.ContractDisease(D) + else //injected + M.ForceContractDisease(D) + +datum/reagent/blood/on_new(var/list/data) + if(istype(data)) + SetViruses(src, data) + +datum/reagent/blood/on_merge(var/list/data) + if(src.data && data) + src.data["cloneable"] = 0 //On mix, consider the genetic sampling unviable for pod cloning, or else we won't know who's even getting cloned, etc + if(src.data["viruses"] || data["viruses"]) + + var/list/mix1 = src.data["viruses"] + var/list/mix2 = data["viruses"] + + // Stop issues with the list changing during mixing. + var/list/to_mix = list() + + for(var/datum/disease/advance/AD in mix1) + to_mix += AD + for(var/datum/disease/advance/AD in mix2) + to_mix += AD + + var/datum/disease/advance/AD = Advance_Mix(to_mix) + if(AD) + var/list/preserve = list(AD) + for(var/D in src.data["viruses"]) + if(!istype(D, /datum/disease/advance)) + preserve += D + src.data["viruses"] = preserve + return 1 + +datum/reagent/blood/reaction_turf(var/turf/simulated/T, var/volume)//splash the blood all over the place + if(!istype(T)) return + var/datum/reagent/blood/self = src + src = null + if(!(volume >= 3)) return + //var/datum/disease/D = self.data["virus"] + if(!self.data["donor"] || istype(self.data["donor"], /mob/living/carbon/human)) + var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T //find some blood here + if(!blood_prop) //first blood! + blood_prop = new(T) + blood_prop.blood_DNA[self.data["blood_DNA"]] = self.data["blood_type"] + + for(var/datum/disease/D in self.data["viruses"]) + var/datum/disease/newVirus = D.Copy(1) + blood_prop.viruses += newVirus + newVirus.holder = blood_prop + + + else if(istype(self.data["donor"], /mob/living/carbon/monkey)) + var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T + if(!blood_prop) + blood_prop = new(T) + blood_prop.blood_DNA["Non-Human DNA"] = "A+" + for(var/datum/disease/D in self.data["viruses"]) + var/datum/disease/newVirus = D.Copy(1) + blood_prop.viruses += newVirus + newVirus.holder = blood_prop + + else if(istype(self.data["donor"], /mob/living/carbon/alien)) + var/obj/effect/decal/cleanable/xenoblood/blood_prop = locate() in T + if(!blood_prop) + blood_prop = new(T) + blood_prop.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" + for(var/datum/disease/D in self.data["viruses"]) + var/datum/disease/newVirus = D.Copy(1) + blood_prop.viruses += newVirus + newVirus.holder = blood_prop + return + +datum/reagent/vaccine + //data must contain virus type + name = "Vaccine" + id = "vaccine" + color = "#C81040" // rgb: 200, 16, 64 + +datum/reagent/vaccine/reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + var/datum/reagent/vaccine/self = src + src = null + if(islist(self.data) && method == INGEST) + for(var/datum/disease/D in M.viruses) + if(D.GetDiseaseID() in self.data) + D.cure() + M.resistances |= self.data + return + +datum/reagent/vaccine/on_merge(var/list/data) + if(istype(data)) + src.data |= data.Copy() + + +datum/reagent/water + name = "Water" + id = "water" + description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen." + color = "#AAAAAA77" // rgb: 170, 170, 170, 77 (alpha) + var/cooling_temperature = 2 + +/* + * Water reaction to turf + */ + +datum/reagent/water/reaction_turf(var/turf/simulated/T, var/volume) + if (!istype(T)) return + var/CT = cooling_temperature + src = null + if(volume >= 10) + T.MakeSlippery() + + for(var/mob/living/simple_animal/slime/M in T) + M.apply_water() + + var/hotspot = (locate(/obj/effect/hotspot) in T) + if(hotspot && !istype(T, /turf/space)) + if(T.air) + var/datum/gas_mixture/G = T.air + G.temperature = max(min(G.temperature-(CT*1000),G.temperature/CT),0) + G.react() + qdel(hotspot) + return + +/* + * Water reaction to an object + */ + +datum/reagent/water/reaction_obj(var/obj/O, var/volume) + src = null + // Monkey cube + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/monkeycube)) + var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = O + if(!cube.wrapped) + cube.Expand() + + // Dehydrated carp + if(istype(O,/obj/item/toy/carpplushie/dehy_carp)) + var/obj/item/toy/carpplushie/dehy_carp/dehy = O + dehy.Swell() // Makes a carp + + return + +/* + * Water reaction to a mob + */ + +datum/reagent/water/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume)//Splashing people with water can help put them out! + if(!istype(M, /mob/living)) + return + if(method == TOUCH) + M.adjust_fire_stacks(-(volume / 10)) + if(M.fire_stacks <= 0) + M.ExtinguishMob() + return + +datum/reagent/water/holywater + name = "Holy Water" + id = "holywater" + description = "Water blessed by some deity." + color = "#E0E8EF" // rgb: 224, 232, 239 + +datum/reagent/water/holywater/on_mob_life(var/mob/living/M as mob) + if(!data) data = 1 + data++ + M.jitteriness = max(M.jitteriness-5,0) + if(data >= 30) // 12 units, 54 seconds @ metabolism 0.4 units & tick rate 1.8 sec + if (!M.stuttering) M.stuttering = 1 + M.stuttering += 4 + M.Dizzy(5) + if(iscultist(M) && prob(5)) + M.say(pick("Av'te Nar'sie","Pa'lid Mors","INO INO ORA ANA","SAT ANA!","Daim'niodeis Arc'iai Le'eones","Egkau'haom'nai en Chaous","Ho Diak'nos tou Ap'iron","R'ge Na'sie","Diabo us Vo'iscum","Si gn'um Co'nu")) + if(data >= 75 && prob(33)) // 30 units, 135 seconds + if (!M.confused) M.confused = 1 + M.confused += 3 + if(iscultist(M)) + ticker.mode.remove_cultist(M.mind) + holder.remove_reagent(src.id, src.volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? + M.jitteriness = 0 + M.stuttering = 0 + M.confused = 0 + holder.remove_reagent(src.id, 0.4) //fixed consumption to prevent balancing going out of whack + return + +datum/reagent/water/holywater/reaction_turf(var/turf/simulated/T, var/volume) + ..() + if(!istype(T)) return + if(volume>=10) + for(var/obj/effect/rune/R in T) + qdel(R) + T.Bless() + +datum/reagent/fuel/unholywater //if you somehow managed to extract this from someone, dont splash it on yourself and have a smoke + name = "Unholy Water" + id = "unholywater" + description = "Something that shouldn't exist on this plane of existance." + +datum/reagent/fuel/unholywater/on_mob_life(var/mob/living/M as mob) + M.adjustBrainLoss(3) + if(iscultist(M)) + M.status_flags |= GOTTAGOFAST + M.drowsyness = max(M.drowsyness-5, 0) + M.AdjustParalysis(-2) + M.AdjustStunned(-2) + M.AdjustWeakened(-2) + else + M.adjustToxLoss(2) + M.adjustFireLoss(2) + M.adjustOxyLoss(2) + M.adjustBruteLoss(2) + holder.remove_reagent(src.id, 1) + +datum/reagent/hellwater //if someone has this in their system they've really pissed off an eldrich god + name = "Hell Water" + id = "hell_water" + description = "YOUR FLESH! IT BURNS!" + +datum/reagent/hellwater/on_mob_life(var/mob/living/M as mob) + M.fire_stacks = min(5,M.fire_stacks + 3) + M.IgniteMob() //Only problem with igniting people is currently the commonly availible fire suits make you immune to being on fire + M.adjustToxLoss(1) + M.adjustFireLoss(1) //Hence the other damages... ain't I a bastard? + M.adjustBrainLoss(5) + holder.remove_reagent(src.id, 1) + +datum/reagent/lube + name = "Space Lube" + id = "lube" + description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity." + color = "#009CA8" // rgb: 0, 156, 168 + +datum/reagent/lube/reaction_turf(var/turf/simulated/T, var/volume) + if (!istype(T)) return + src = null + if(volume >= 1) + T.MakeSlippery(2) + +datum/reagent/slimetoxin + name = "Mutation Toxin" + id = "mutationtoxin" + description = "A corruptive toxin produced by slimes." + color = "#13BC5E" // rgb: 19, 188, 94 + +datum/reagent/unstableslimetoxin + name = "Unstable Mutation Toxin" + id = "unstablemutationtoxin" + description = "An unstable and unpredictable corruptive toxin produced by slimes." + color = "#5EFF3B" //RGB: 94, 255, 59 + metabolization_rate = INFINITY //So it instantly removes all of itself + +datum/reagent/unstableslimetoxin/on_mob_life(var/mob/living/carbon/human/H as mob) + ..() + H << "You crumple in agony as your flesh wildly morphs into new forms!" + H.visible_message("[H] falls to the ground and screams as their skin bubbles and froths!") //'froths' sounds painful when used with SKIN. + H.Weaken(3) + sleep(30) + var/list/blacklisted_species = list(/datum/species/zombie, /datum/species/skeleton, /datum/species/human, /datum/species/golem, /datum/species/golem/adamantine, /datum/species/shadow) + var/list/possible_morphs = typesof(/datum/species/) - blacklisted_species + var/datum/species/mutation = pick(possible_morphs) + if(prob(90) && mutation && H.dna.species != /datum/species/golem && H.dna.species != /datum/species/golem/adamantine) + H << "The pain subsides. You feel... different." + H.dna.species = new mutation() + H.regenerate_icons() + if(mutation == /datum/species/slime) + H.faction |= "slime" + else + H.faction -= "slime" + else + H << "The pain vanishes suddenly. You feel no different." + return 1 + +datum/reagent/aslimetoxin + name = "Advanced Mutation Toxin" + id = "amutationtoxin" + description = "An advanced corruptive toxin produced by slimes." + color = "#13BC5E" // rgb: 19, 188, 94 + +datum/reagent/aslimetoxin/reaction_mob(var/mob/M, var/volume) + src = null + M.ForceContractDisease(new /datum/disease/transformation/slime(0)) + +datum/reagent/space_drugs + name = "Space drugs" + id = "space_drugs" + description = "An illegal chemical compound used as drug." + color = "#60A584" // rgb: 96, 165, 132 + metabolization_rate = 0.5 * REAGENTS_METABOLISM + +datum/reagent/space_drugs/on_mob_life(var/mob/living/M as mob) + M.druggy = max(M.druggy, 15) + if(isturf(M.loc) && !istype(M.loc, /turf/space)) + if(M.canmove) + if(prob(10)) step(M, pick(cardinal)) + if(prob(7)) M.emote(pick("twitch","drool","moan","giggle")) + ..() + return + +datum/reagent/serotrotium + name = "Serotrotium" + id = "serotrotium" + description = "A chemical compound that promotes concentrated production of the serotonin neurotransmitter in humans." + color = "#202040" // rgb: 20, 20, 40 + metabolization_rate = 0.25 * REAGENTS_METABOLISM + +datum/reagent/serotrotium/on_mob_life(var/mob/living/M as mob) + if(ishuman(M)) + if(prob(7)) M.emote(pick("twitch","drool","moan","gasp")) + ..() + return + +datum/reagent/oxygen + name = "Oxygen" + id = "oxygen" + description = "A colorless, odorless gas." + reagent_state = GAS + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/copper + name = "Copper" + id = "copper" + description = "A highly ductile metal." + reagent_state = SOLID + color = "#6E3B08" // rgb: 110, 59, 8 + +datum/reagent/nitrogen + name = "Nitrogen" + id = "nitrogen" + description = "A colorless, odorless, tasteless gas." + reagent_state = GAS + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/hydrogen + name = "Hydrogen" + id = "hydrogen" + description = "A colorless, odorless, nonmetallic, tasteless, highly combustible diatomic gas." + reagent_state = GAS + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/potassium + name = "Potassium" + id = "potassium" + description = "A soft, low-melting solid that can easily be cut with a knife. Reacts violently with water." + reagent_state = SOLID + color = "#A0A0A0" // rgb: 160, 160, 160 + +datum/reagent/mercury + name = "Mercury" + id = "mercury" + description = "A chemical element." + color = "#484848" // rgb: 72, 72, 72 + +datum/reagent/mercury/on_mob_life(var/mob/living/M as mob) + if(M.canmove && istype(M.loc, /turf/space)) + step(M, pick(cardinal)) + if(prob(5)) + M.emote(pick("twitch","drool","moan")) + M.adjustBrainLoss(2) + ..() + return + +datum/reagent/sulfur + name = "Sulfur" + id = "sulfur" + description = "A chemical element." + reagent_state = SOLID + color = "#BF8C00" // rgb: 191, 140, 0 + +datum/reagent/carbon + name = "Carbon" + id = "carbon" + description = "A chemical element." + reagent_state = SOLID + color = "#1C1300" // rgb: 30, 20, 0 + +datum/reagent/carbon/reaction_turf(var/turf/T, var/volume) + src = null + if(!istype(T, /turf/space)) + new /obj/effect/decal/cleanable/dirt(T) + +datum/reagent/chlorine + name = "Chlorine" + id = "chlorine" + description = "A chemical element." + reagent_state = GAS + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/chlorine/on_mob_life(var/mob/living/M as mob) + M.take_organ_damage(1*REM, 0) + ..() + return + +datum/reagent/fluorine + name = "Fluorine" + id = "fluorine" + description = "A highly-reactive chemical element." + reagent_state = GAS + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/fluorine/on_mob_life(var/mob/living/M as mob) + M.adjustToxLoss(1*REM) + ..() + return + +datum/reagent/sodium + name = "Sodium" + id = "sodium" + description = "A chemical element." + reagent_state = SOLID + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/phosphorus + name = "Phosphorus" + id = "phosphorus" + description = "A chemical element." + reagent_state = SOLID + color = "#832828" // rgb: 131, 40, 40 + +datum/reagent/lithium + name = "Lithium" + id = "lithium" + description = "A chemical element." + reagent_state = SOLID + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/lithium/on_mob_life(var/mob/living/M as mob) + if(M.canmove && istype(M.loc, /turf/space)) + step(M, pick(cardinal)) + if(prob(5)) + M.emote(pick("twitch","drool","moan")) + ..() + return + +datum/reagent/glycerol + name = "Glycerol" + id = "glycerol" + description = "Glycerol is a simple polyol compound. Glycerol is sweet-tasting and of low toxicity." + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/nitroglycerin + name = "Nitroglycerin" + id = "nitroglycerin" + description = "Nitroglycerin is a heavy, colorless, oily, explosive liquid obtained by nitrating glycerol." + color = "#808080" // rgb: 128, 128, 128 + +datum/reagent/radium + name = "Radium" + id = "radium" + description = "Radium is an alkaline earth metal. It is extremely radioactive." + reagent_state = SOLID + color = "#C7C7C7" // rgb: 199,199,199 + +datum/reagent/radium/on_mob_life(var/mob/living/M as mob) + M.apply_effect(2*REM/M.metabolism_efficiency,IRRADIATE,0) + ..() + return + +datum/reagent/radium/reaction_turf(var/turf/T, var/volume) + src = null + if(volume >= 3) + if(!istype(T, /turf/space)) + var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/greenglow(T) + reagentdecal.reagents.add_reagent("uranium", volume) + +datum/reagent/thermite + name = "Thermite" + id = "thermite" + description = "Thermite produces an aluminothermic reaction known as a thermite reaction. Can be used to melt walls." + reagent_state = SOLID + color = "#673910" // rgb: 103, 57, 16 + +datum/reagent/thermite/reaction_turf(var/turf/T, var/volume) + src = null + if(volume >= 1 && istype(T, /turf/simulated/wall)) + var/turf/simulated/wall/Wall = T + if(istype(Wall, /turf/simulated/wall/r_wall)) + Wall.thermite = Wall.thermite+(volume*2.5) + else + Wall.thermite = Wall.thermite+(volume*10) + Wall.overlays = list() + Wall.overlays += image('icons/effects/effects.dmi',"thermite") + return + +datum/reagent/thermite/on_mob_life(var/mob/living/M as mob) + M.adjustFireLoss(1) + ..() + return + +datum/reagent/sterilizine + name = "Sterilizine" + id = "sterilizine" + description = "Sterilizes wounds in preparation for surgery." + color = "#C8A5DC" // rgb: 200, 165, 220 + +datum/reagent/iron + name = "Iron" + id = "iron" + description = "Pure iron is a metal." + reagent_state = SOLID + color = "#C8A5DC" // rgb: 200, 165, 220 + +datum/reagent/gold + name = "Gold" + id = "gold" + description = "Gold is a dense, soft, shiny metal and the most malleable and ductile metal known." + reagent_state = SOLID + color = "#F7C430" // rgb: 247, 196, 48 + +datum/reagent/silver + name = "Silver" + id = "silver" + description = "A soft, white, lustrous transition metal, it has the highest electrical conductivity of any element and the highest thermal conductivity of any metal." + reagent_state = SOLID + color = "#D0D0D0" // rgb: 208, 208, 208 + +datum/reagent/uranium + name ="Uranium" + id = "uranium" + description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive." + reagent_state = SOLID + color = "#B8B8C0" // rgb: 184, 184, 192 + +datum/reagent/uranium/on_mob_life(var/mob/living/M as mob) + M.apply_effect(1/M.metabolism_efficiency,IRRADIATE,0) + ..() + return + + +datum/reagent/uranium/reaction_turf(var/turf/T, var/volume) + src = null + if(volume >= 3) + if(!istype(T, /turf/space)) + var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/greenglow(T) + reagentdecal.reagents.add_reagent("uranium", volume) + +datum/reagent/aluminium + name = "Aluminium" + id = "aluminium" + description = "A silvery white and ductile member of the boron group of chemical elements." + reagent_state = SOLID + color = "#A8A8A8" // rgb: 168, 168, 168 + +datum/reagent/silicon + name = "Silicon" + id = "silicon" + description = "A tetravalent metalloid, silicon is less reactive than its chemical analog carbon." + reagent_state = SOLID + color = "#A8A8A8" // rgb: 168, 168, 168 + +datum/reagent/fuel + name = "Welding fuel" + id = "fuel" + description = "Required for welders. Flamable." + color = "#660000" // rgb: 102, 0, 0 + +datum/reagent/fuel/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume)//Splashing people with welding fuel to make them easy to ignite! + if(!istype(M, /mob/living)) + return + if(method == TOUCH) + M.adjust_fire_stacks(volume / 10) + return + +datum/reagent/fuel/on_mob_life(var/mob/living/M as mob) + M.adjustToxLoss(1) + ..() + return + +datum/reagent/space_cleaner + name = "Space cleaner" + id = "cleaner" + description = "A compound used to clean things. Now with 50% more sodium hypochlorite!" + color = "#A5F0EE" // rgb: 165, 240, 238 + +datum/reagent/space_cleaner/reaction_obj(var/obj/O, var/volume) + if(istype(O,/obj/effect/decal/cleanable)) + qdel(O) + else + if(O) + O.clean_blood() + +datum/reagent/space_cleaner/reaction_turf(var/turf/T, var/volume) + if(volume >= 1) + T.clean_blood() + for(var/obj/effect/decal/cleanable/C in T) + qdel(C) + + for(var/mob/living/simple_animal/slime/M in T) + M.adjustToxLoss(rand(5,10)) + if(istype(T, /turf/simulated/floor)) + var/turf/simulated/floor/F = T + if(volume >= 1) + F.dirt = 0 + +datum/reagent/space_cleaner/reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.lip_style) + H.lip_style = null + H.update_body() + if(C.r_hand) + C.r_hand.clean_blood() + if(C.l_hand) + C.l_hand.clean_blood() + if(C.wear_mask) + if(C.wear_mask.clean_blood()) + C.update_inv_wear_mask(0) + if(ishuman(M)) + var/mob/living/carbon/human/H = C + if(H.head) + if(H.head.clean_blood()) + H.update_inv_head(0) + if(H.wear_suit) + if(H.wear_suit.clean_blood()) + H.update_inv_wear_suit(0) + else if(H.w_uniform) + if(H.w_uniform.clean_blood()) + H.update_inv_w_uniform(0) + if(H.shoes) + if(H.shoes.clean_blood()) + H.update_inv_shoes(0) + M.clean_blood() + +datum/reagent/cryptobiolin + name = "Cryptobiolin" + id = "cryptobiolin" + description = "Cryptobiolin causes confusion and dizzyness." + color = "#C8A5DC" // rgb: 200, 165, 220 + metabolization_rate = 1.5 * REAGENTS_METABOLISM + +datum/reagent/cryptobiolin/on_mob_life(var/mob/living/M as mob) + M.Dizzy(1) + if(!M.confused) + M.confused = 1 + M.confused = max(M.confused, 20) + ..() + return + +datum/reagent/impedrezene + name = "Impedrezene" + id = "impedrezene" + description = "Impedrezene is a narcotic that impedes one's ability by slowing down the higher brain cell functions." + color = "#C8A5DC" // rgb: 200, 165, 220 + +datum/reagent/impedrezene/on_mob_life(var/mob/living/M as mob) + M.jitteriness = max(M.jitteriness-5,0) + if(prob(80)) M.adjustBrainLoss(1*REM) + if(prob(50)) M.drowsyness = max(M.drowsyness, 3) + if(prob(10)) M.emote("drool") + ..() + return + +datum/reagent/nanites + name = "Nanomachines" + id = "nanomachines" + description = "Microscopic construction robots." + color = "#535E66" // rgb: 83, 94, 102 + +datum/reagent/nanites/reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + src = null + if( (prob(10) && method==TOUCH) || method==INGEST) + M.ForceContractDisease(new /datum/disease/transformation/robot(0)) + +datum/reagent/xenomicrobes + name = "Xenomicrobes" + id = "xenomicrobes" + description = "Microbes with an entirely alien cellular structure." + color = "#535E66" // rgb: 83, 94, 102 + +datum/reagent/xenomicrobes/reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + src = null + if( (prob(10) && method==TOUCH) || method==INGEST) + M.ContractDisease(new /datum/disease/transformation/xeno(0)) + +datum/reagent/fluorosurfactant//foam precursor + name = "Fluorosurfactant" + id = "fluorosurfactant" + description = "A perfluoronated sulfonic acid that forms a foam when mixed with water." + color = "#9E6B38" // rgb: 158, 107, 56 + +datum/reagent/foaming_agent// Metal foaming agent. This is lithium hydride. Add other recipes (e.g. LiH + H2O -> LiOH + H2) eventually. + name = "Foaming agent" + id = "foaming_agent" + description = "A agent that yields metallic foam when mixed with light metal and a strong acid." + reagent_state = SOLID + color = "#664B63" // rgb: 102, 75, 99 + +datum/reagent/ammonia + name = "Ammonia" + id = "ammonia" + description = "A caustic substance commonly used in fertilizer or household cleaners." + reagent_state = GAS + color = "#404030" // rgb: 64, 64, 48 + +datum/reagent/diethylamine + name = "Diethylamine" + id = "diethylamine" + description = "A secondary amine, mildly corrosive." + color = "#604030" // rgb: 96, 64, 48 + + + +/////////////////////////Coloured Crayon Powder//////////////////////////// +//For colouring in /proc/mix_color_from_reagents + + +datum/reagent/crayonpowder + name = "Crayon Powder" + id = "crayon powder" + var/colorname = "none" + description = "A powder made by grinding down crayons, good for colouring chemical reagents." + reagent_state = SOLID + color = "#FFFFFF" // rgb: 207, 54, 0 + +datum/reagent/crayonpowder/New() + description = "\an [colorname] powder made by grinding down crayons, good for colouring chemical reagents." + + +datum/reagent/crayonpowder/red + name = "Red Crayon Powder" + id = "redcrayonpowder" + colorname = "red" + +datum/reagent/crayonpowder/orange + name = "Orange Crayon Powder" + id = "orangecrayonpowder" + colorname = "orange" + color = "#FF9300" // orange + +datum/reagent/crayonpowder/yellow + name = "Yellow Crayon Powder" + id = "yellowcrayonpowder" + colorname = "yellow" + color = "#FFF200" // yellow + +datum/reagent/crayonpowder/green + name = "Green Crayon Powder" + id = "greencrayonpowder" + colorname = "green" + color = "#A8E61D" // green + +datum/reagent/crayonpowder/blue + name = "Blue Crayon Powder" + id = "bluecrayonpowder" + colorname = "blue" + color = "#00B7EF" // blue + +datum/reagent/crayonpowder/purple + name = "Purple Crayon Powder" + id = "purplecrayonpowder" + colorname = "purple" + color = "#DA00FF" // purple + +datum/reagent/crayonpowder/invisible + name = "Invisible Crayon Powder" + id = "invisiblecrayonpowder" + colorname = "invisible" + color = "#FFFFFF00" // white + no alpha + + + + +//////////////////////////////////Hydroponics stuff/////////////////////////////// + +datum/reagent/plantnutriment + name = "Generic nutriment" + id = "plantnutriment" + description = "Some kind of nutriment. You can't really tell what it is. You should probably report it, along with how you obtained it." + color = "#000000" // RBG: 0, 0, 0 + var/tox_prob = 0 + +datum/reagent/plantnutriment/on_mob_life(var/mob/living/M as mob) + if(prob(tox_prob)) + M.adjustToxLoss(1*REM) + ..() + return + +datum/reagent/plantnutriment/eznutriment + name = "E-Z-Nutrient" + id = "eznutriment" + description = "Cheap and extremely common type of plant nutriment." + color = "#376400" // RBG: 50, 100, 0 + tox_prob = 10 + +datum/reagent/plantnutriment/left4zednutriment + name = "Left 4 Zed" + id = "left4zednutriment" + description = "Unstable nutriment that makes plants mutate more often than usual." + color = "#1A1E4D" // RBG: 26, 30, 77 + tox_prob = 25 + +datum/reagent/plantnutriment/robustharvestnutriment + name = "Robust Harvest" + id = "robustharvestnutriment" + description = "Very potent nutriment that prevents plants from mutating." + color = "#9D9D00" // RBG: 157, 157, 0 + tox_prob = 15 + + + +// Undefine the alias for REAGENTS_EFFECT_MULTIPLER +#undef REM diff --git a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm index 7f426393b39..17fea97c5dd 100644 --- a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm @@ -46,7 +46,6 @@ datum/reagent/drug/nicotine/on_mob_life(var/mob/living/M as mob) M.adjustStaminaLoss(-0.5*REM) ..() - M << "You feel like you smoked too much." datum/reagent/drug/crank name = "Crank" id = "crank" diff --git a/code/modules/reagents/grenade_launcher.dm b/code/modules/reagents/grenade_launcher.dm new file mode 100644 index 00000000000..f3bd6bbea87 --- /dev/null +++ b/code/modules/reagents/grenade_launcher.dm @@ -0,0 +1,61 @@ +/obj/item/weapon/gun/grenadelauncher + name = "grenade launcher" + desc = "a terrible, terrible thing. it's really awful!" + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "riotgun" + item_state = "riotgun" + w_class = 4.0 + throw_speed = 2 + throw_range = 7 + force = 5.0 + var/list/grenades = new/list() + var/max_grenades = 3 + m_amt = 2000 + +/obj/item/weapon/gun/grenadelauncher/examine(mob/user) + ..() + user << "[grenades] / [max_grenades] grenades loaded." + +/obj/item/weapon/gun/grenadelauncher/attackby(obj/item/I as obj, mob/user as mob, params) + + if((istype(I, /obj/item/weapon/grenade))) + if(grenades.len < max_grenades) + user.drop_item() + I.loc = src + grenades += I + user << "You put the grenade in the grenade launcher." + user << "[grenades.len] / [max_grenades] Grenades." + else + usr << "The grenade launcher cannot hold more grenades!" + +/obj/item/weapon/gun/grenadelauncher/afterattack(obj/target, mob/user , flag) + + if (istype(target, /obj/item/weapon/storage/backpack )) + return + + else if (locate (/obj/structure/table, src.loc)) + return + + else if(target == user) + return + + if(grenades.len) + spawn(0) fire_grenade(target,user) + else + usr << "The grenade launcher is empty!" + +/obj/item/weapon/gun/grenadelauncher/proc/fire_grenade(atom/target, mob/user) + for(var/mob/O in viewers(world.view, user)) + O.show_message(text("[] fired a grenade!", user), 1) + user << "You fire the grenade launcher!" + var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta! + grenades -= F + F.loc = user.loc + F.throw_at(target, 30, 2) + message_admins("[key_name_admin(user)] fired a grenade ([F.name]) from a grenade launcher ([src.name]).") + log_game("[key_name(user)] fired a grenade ([F.name]) from a grenade launcher ([src.name]).") + F.active = 1 + F.icon_state = initial(icon_state) + "_active" + playsound(user.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(15) + F.prime() diff --git a/code/modules/reagents/syringe_gun.dm b/code/modules/reagents/syringe_gun.dm new file mode 100644 index 00000000000..5c6327abcfa --- /dev/null +++ b/code/modules/reagents/syringe_gun.dm @@ -0,0 +1,77 @@ +/obj/item/weapon/gun/syringe + name = "syringe gun" + desc = "A spring loaded rifle designed to fit syringes, used to incapacitate unruly patients from a distance." + icon_state = "syringegun" + item_state = "syringegun" + w_class = 3 + throw_speed = 3 + throw_range = 7 + force = 4 + m_amt = 2000 + clumsy_check = 0 + fire_sound = 'sound/items/syringeproj.ogg' + var/list/syringes = list() + var/max_syringes = 1 + +/obj/item/weapon/gun/syringe/New() + ..() + chambered = new /obj/item/ammo_casing/syringegun(src) + +/obj/item/weapon/gun/syringe/proc/newshot() + if(!syringes.len) return + + var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] + + if(!S) return + + chambered.BB = new /obj/item/projectile/bullet/dart/syringe(src) + S.reagents.trans_to(chambered.BB, S.reagents.total_volume) + chambered.BB.name = S.name + syringes.Remove(S) + + qdel(S) + return + +/obj/item/weapon/gun/syringe/process_chamber() + return + +/obj/item/weapon/gun/syringe/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) + newshot() + ..() + +/obj/item/weapon/gun/syringe/examine(mob/user) + ..() + user << "Can hold [max_syringes] syringe\s. Has [syringes.len] syringe\s remaining." + +/obj/item/weapon/gun/syringe/attack_self(mob/living/user as mob) + if(!syringes.len) + user << "[src] is empty." + return 0 + + var/obj/item/weapon/reagent_containers/syringe/S = syringes[syringes.len] + + if(!S) return 0 + S.loc = user.loc + + syringes.Remove(S) + user << "You unload [S] from \the [src]." + + return 1 + +/obj/item/weapon/gun/syringe/attackby(var/obj/item/A as obj, mob/user as mob, params, var/show_msg = 1) + if(istype(A, /obj/item/weapon/reagent_containers/syringe)) + if(syringes.len < max_syringes) + user.drop_item() + user << "You load [A] into \the [src]." + syringes.Add(A) + A.loc = src + return 1 + else + usr << "[src] cannot hold more syringes!" + return 0 + +/obj/item/weapon/gun/syringe/rapidsyringe + name = "rapid syringe gun" + desc = "A modification of the syringe gun design, using a rotating cylinder to store up to six syringes." + icon_state = "rapidsyringegun" + max_syringes = 6