diff --git a/aurorastation.dme b/aurorastation.dme index 78288be2a19..0f7cec43c83 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -1133,11 +1133,23 @@ #include "code\game\objects\items\weapons\grenades\spawnergrenade.dm" #include "code\game\objects\items\weapons\implants\implant.dm" #include "code\game\objects\items\weapons\implants\implantcase.dm" -#include "code\game\objects\items\weapons\implants\implantcircuits.dm" #include "code\game\objects\items\weapons\implants\implanter.dm" -#include "code\game\objects\items\weapons\implants\implantfreedom.dm" #include "code\game\objects\items\weapons\implants\implantpad.dm" -#include "code\game\objects\items\weapons\implants\implantuplink.dm" +#include "code\game\objects\items\weapons\implants\implants\adrenaline.dm" +#include "code\game\objects\items\weapons\implants\implants\aggression.dm" +#include "code\game\objects\items\weapons\implants\implants\anti-augment.dm" +#include "code\game\objects\items\weapons\implants\implants\chem.dm" +#include "code\game\objects\items\weapons\implants\implants\circuit.dm" +#include "code\game\objects\items\weapons\implants\implants\compressed_matter.dm" +#include "code\game\objects\items\weapons\implants\implants\death_alarm.dm" +#include "code\game\objects\items\weapons\implants\implants\emp.dm" +#include "code\game\objects\items\weapons\implants\implants\explosive.dm" +#include "code\game\objects\items\weapons\implants\implants\freedom.dm" +#include "code\game\objects\items\weapons\implants\implants\health_tracker.dm" +#include "code\game\objects\items\weapons\implants\implants\loyalty.dm" +#include "code\game\objects\items\weapons\implants\implants\mindshield.dm" +#include "code\game\objects\items\weapons\implants\implants\tracking.dm" +#include "code\game\objects\items\weapons\implants\implants\uplink.dm" #include "code\game\objects\items\weapons\material\ashtray.dm" #include "code\game\objects\items\weapons\material\bats.dm" #include "code\game\objects\items\weapons\material\caltrops.dm" diff --git a/code/__defines/_macros.dm b/code/__defines/_macros.dm index 4e69dac1985..62c88d2a9f8 100644 --- a/code/__defines/_macros.dm +++ b/code/__defines/_macros.dm @@ -21,6 +21,7 @@ #define SPAN_SUBTLE(X) ("" + X + "") #define SPAN_SOGHUN(X) ("" + X + "") #define SPAN_VOTE(X) ("" + X + "") +#define SPAN_HEAR(X) ("" + X + "") #define SPAN_SIZE(size, text) ("" + text + "") diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index acba5cca978..2c7a2b09f53 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -228,6 +228,32 @@ /datum/action/item_action/hands_free check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE +/datum/action/item_action/hands_free/activate + name = "Activate" + +/datum/action/item_action/hands_free/activate/implant + action_type = AB_ITEM_USE_ICON + button_icon = 'icons/obj/action_buttons/implants.dmi' + button_icon_state = "default" + +/datum/action/item_action/hands_free/activate/implant/adrenaline + button_icon_state = "adrenal" + +/datum/action/item_action/hands_free/activate/implant/chemical + button_icon_state = "reagents" + +/datum/action/item_action/hands_free/activate/implant/compressed + button_icon_state = "storage" + +/datum/action/item_action/hands_free/activate/implant/emp + button_icon_state = "emp" + +/datum/action/item_action/hands_free/activate/implant/explosive + button_icon_state = "explosive" + +/datum/action/item_action/hands_free/activate/implant/freedom + button_icon_state = "freedom" + /datum/action/item_action/organ action_type = AB_ITEM_USE_ICON button_icon = 'icons/obj/action_buttons/organs.dmi' diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 22531ab2c27..8248b6c5434 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -358,7 +358,7 @@ switch(href_list["implant"]) if("remove") - for(var/obj/item/implant/mindshield/I in H.contents) + for(var/obj/item/implant/mindshield/loyalty/I in H.contents) for(var/obj/item/organ/external/organs in H.organs) if(I in organs.implants) qdel(I) diff --git a/code/datums/uplink/implants.dm b/code/datums/uplink/implants.dm index 14300bef4d3..26abc434bd3 100644 --- a/code/datums/uplink/implants.dm +++ b/code/datums/uplink/implants.dm @@ -7,18 +7,19 @@ /datum/uplink_item/item/implants/imp_freedom name = "Freedom Implant" telecrystal_cost = 1 + desc = "A box containing a freedom implant case and implanter." path = /obj/item/storage/box/syndie_kit/imp_freedom -/datum/uplink_item/item/implants/imp_compress - name = "Compressed Matter Implant" - desc = "A box containing a single implanter and matter cartridge. To remove an unintended target, use the implanter in-hand then open the cartridge with a screwdriver." - bluecrystal_cost = 1 - path = /obj/item/storage/box/syndie_kit/imp_compress +/datum/uplink_item/item/implants/imp_emp + name = "EMP Implant" + telecrystal_cost = 1 + desc = "A box containing an EMP implant case and implanter." + path = /obj/item/storage/box/syndie_kit/imp_emp /datum/uplink_item/item/implants/imp_explosive name = "Explosive Implant (DANGER!)" bluecrystal_cost = 3 - desc = "A box containing an explosive implant and implanter. Use the implant in-hand to set the explosion size and trigger phrase." + desc = "A box containing an explosive implant case and implanter. Use the implant case with the implant pad to set the explosion size, trigger phrase, and trigger code." path = /obj/item/storage/box/syndie_kit/imp_explosive /datum/uplink_item/item/implants/imp_deadman diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm index 85f14d6089b..d1f1860a84f 100644 --- a/code/game/machinery/body_scanner.dm +++ b/code/game/machinery/body_scanner.dm @@ -736,9 +736,16 @@ if (e.implants.len) var/unk = 0 var/list/organic = list() - for(var/atom/movable/I in e.implants) - if(is_type_in_list(I, known_implants)) - wounds += "\a [I.name] implanted:" + var/imp + for(var/I in e.implants) + if(istype(I, /obj/item/implant)) + var/obj/item/implant/A = I + if (A.hidden) + return + else if(A.known) + imp += "[I] implanted:" + else + unk += 1 else if(istype(I, /obj/effect/spider)) organic += I else diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 627b7c42884..2ca6594e149 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -376,23 +376,6 @@ else if (mess) icon_state = "pod_g" -//Health Tracker Implant - -/obj/item/implant/health - name = "health implant" - var/healthstring = "" - -/obj/item/implant/health/proc/sensehealth() - if(!implanted) - return "ERROR" - else - if(isliving(implanted)) - var/mob/living/L = implanted - healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]" - if(!healthstring) - healthstring = "ERROR" - return healthstring - //Disk stuff. //The return of data disks?? Just for transferring between genetics machine/cloning machine. //TO-DO: Make the genetics machine accept them. diff --git a/code/game/objects/items/devices/uplink_random_lists.dm b/code/game/objects/items/devices/uplink_random_lists.dm index 1089a4f81cb..af954589f94 100644 --- a/code/game/objects/items/devices/uplink_random_lists.dm +++ b/code/game/objects/items/devices/uplink_random_lists.dm @@ -70,7 +70,7 @@ var/datum/uplink_random_selection/default_uplink_selection = new/datum/uplink_ra items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/ai_module, 25, 0) items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_freedom) - items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_compress) + items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_emp) items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_explosive) items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/sinpockets, reselect_propbability = 20) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 3891f3b8244..6118816a08c 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -3,44 +3,120 @@ /obj/item/implant + abstract_type = /obj/item/implant name = "implant" - icon = 'icons/obj/device.dmi' - icon_state = "implant" + icon = 'icons/obj/item/implants.dmi' w_class = ITEMSIZE_TINY + /** + * This gives the user an action button that allows them to activate the implant. + * If the implant needs no action button, then null this out. + * Or, if you want to add a unique action button, then replace this. + */ + default_action_type = /datum/action/item_action/hands_free/activate/implant + action_button_name = "Activate Implant" var/implanted = null + ///The mob that has been implanted with this var/mob/imp_in = null + ///The organ/limb that has been implanted with this var/obj/item/organ/external/part = null - var/implant_color = "b" - var/allow_reagents = 0 + ///Implant icon name, used for getting the name of the implant for usage in the implant case name. + var/implant_icon = null + ///Implant color, used for overlaying the implant into an implanter. + var/implant_color = null var/malfunction = 0 + ///If advanced scanners would name these in results + var/known + ///If scanners can locate this implant at all + var/hidden /obj/item/implant/Initialize() . = ..() implants += src -/obj/item/implant/proc/trigger(emote, source as mob) +/obj/item/implant/proc/trigger(emote, source) + return + +/obj/item/implant/ui_action_click() + INVOKE_ASYNC(src, PROC_REF(activate), "action_button") + +/obj/item/implant/item_action_slot_check(slot, mob/user) + return user = imp_in + +/obj/item/implant/proc/hear(message) return /obj/item/implant/proc/activate() return - // What does the implant do upon injection? - // return 0 if the implant fails (ex. Revhead and loyalty implant.) - // return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.) -/obj/item/implant/proc/implanted(var/mob/source, mob/user) - return 1 +/** + * What does the implant do upon injection? + * return FALSE if the implant fails (ex. Revhead and loyalty implant.) + * return TRUE if the implant succeeds (ex. Nonrevhead and loyalty implant.) +*/ +/obj/item/implant/proc/implanted(mob/source) + return TRUE +/obj/item/implant/proc/canImplant(mob/M, mob/user, target_zone) + var/mob/living/carbon/human/H = M + if(istype(H) && !H.get_organ(target_zone)) + to_chat(user, SPAN_WARNING("\The [M] is missing that body part!")) + return FALSE + return TRUE + +/obj/item/implant/proc/implantInMob(mob/M, target_zone) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/affected = H.get_organ(target_zone) + if(affected) + affected.implants += src + part = affected + + forceMove(M) + imp_in = M + implanted = TRUE + implanted(M) + + return TRUE + +///Remove implant from mob. +/obj/item/implant/proc/removed() + imp_in = null + if(part) + part.implants -= src + part = null + implanted = FALSE + +///Called in surgery when incision is retracted open / ribs are opened - basically before you can take the implant out +/obj/item/implant/proc/exposed() + return + +///Get implant specifications for the implant pad /obj/item/implant/proc/get_data() return "No information available" -/obj/item/implant/proc/hear(message, source as mob) - return +/obj/item/implant/interact(user) + var/datum/browser/popup = new(user, capitalize(name), capitalize(name), 300, 700, src) + var/dat = "Implant Mini-Computer:
" + dat += get_data() + if(malfunction) + popup.title = "??? Implant" + dat = stars(dat,10) + popup.set_content(dat) + popup.open() -/obj/item/implant/proc/islegal() - return 0 +/** + * Determines if the implant is known as a legal implant or not. + * + * If TRUE, increases the chance of removal during surgery + */ +/obj/item/implant/proc/isLegal() + return FALSE -/obj/item/implant/proc/meltdown() //breaks it down, making implant unrecongizible - to_chat(imp_in, "You feel something melting inside [part ? "your [part.name]" : "you"]!") +///Breaks the implant down, making it unrecognizable +/obj/item/implant/proc/meltdown() + if(malfunction == MALFUNCTION_PERMANENT) + return + to_chat(imp_in, SPAN_DANGER("You feel something melting inside [part ? "your [part.name]" : "you"]!")) if (part) part.take_damage(burn = 15, used_weapon = "Electronics meltdown") else @@ -59,690 +135,5 @@ implants -= src return ..() -/obj/item/implant/proc/removed() - imp_in = null - if(part) - part.implants -= src - part = null - implanted = 0 - -/obj/item/implant/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/implanter)) - var/obj/item/implanter/implanter = I - if(implanter.imp) - to_chat(user, SPAN_NOTICE("\The [implanter] already has an implant loaded.")) - return // It's full. - user.drop_from_inventory(src) - forceMove(implanter) - implanter.imp = src - implanter.update() - else - ..() - -/obj/item/implant/tracking - name = "tracking implant" - desc = "Track with this." - var/id = 1.0 - -/obj/item/implant/tracking/Initialize() - var/list/tracking_list = list() - for(var/obj/item/implant/tracking/T in implants) - tracking_list += T - id = length(tracking_list) + 1 - . = ..() - -/obj/item/implant/tracking/get_data() - . = {"Implant Specifications:
-Name: Tracking Beacon
-Life: 10 minutes after death of host
-Important Notes: None
-
-Implant Details:
-Function: Continuously transmits low power signal. Useful for tracking.
-Special Features:
-Neuro-Safe- Specialized shell absorbs excess voltages self-destructing the chip if -a malfunction occurs thereby securing safety of subject. The implant will melt and -disintegrate into bio-safe elements.
-Integrity: Gradient creates slight risk of being overcharged and frying the -circuitry. As a result neurotoxins can cause massive damage.
-Implant Specifics:
"} - -/obj/item/implant/tracking/emp_act(severity) - if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning - return - malfunction = MALFUNCTION_TEMPORARY - - var/delay = 20 - switch(severity) - if(1) - if(prob(60)) - meltdown() - if(2) - delay = rand(5*60*10,15*60*10) //from 5 to 15 minutes of free time - - spawn(delay) - malfunction-- - -//BS12 Explosive -/obj/item/implant/explosive - name = "explosive implant" - desc = "A military grade micro bio-explosive. Highly dangerous." - var/elevel = "Localized Limb" - var/phrase - var/setup_done = FALSE //Have we set this yet? - var/uses_codewords = TRUE - var/list/possible_explosions = list("Localized Limb", "Destroy Body") - icon_state = "implant_evil" - -/obj/item/implant/explosive/Initialize() - . = ..() - if(uses_codewords) - phrase = "You are [pick(adjectives)]" - -/obj/item/implant/explosive/get_data() - . = {" -Implant Specifications:
-Name: Robust Corp RX-78 Intimidation Class Implant
-Life: Activates upon codephrase.
-Important Notes: Explodes
-
-Implant Details:
-Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
-Special Features: Explodes. Explosion severity can be altered.
-Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - -/obj/item/implant/explosive/attackby(obj/item/I, mob/user) - if(uses_codewords) - if(istype(I, /obj/item/implanter)) - var/obj/item/implanter/implanter = I - if(implanter.imp) - to_chat(user, SPAN_NOTICE("\The [implanter] already has an implant loaded.")) - return // It's full. - if(!setup_done) - var/choice = alert("\The [src]'s default settings have not been changed. Continue?", "Ready for Implantation?", "Yes", "Cancel") - if(choice == "Cancel") - return - to_chat(user, "You load \the [src] into \the [I]. The current setting is \"[elevel]\" and the current phrase is \"[phrase]\".") - user.drop_from_inventory(src) - forceMove(implanter) - implanter.imp = src - implanter.update() - else - ..() - -/obj/item/implant/explosive/hear_talk(mob/M, msg) - hear(msg) - -/obj/item/implant/explosive/hear(var/msg) - var/list/replacechars = list("\"" = "",">" = "","<" = "","(" = "",")" = "") - msg = replace_characters(msg, replacechars) - if(findtext(msg,phrase)) - activate() - -/obj/item/implant/explosive/activate() - if(malfunction == MALFUNCTION_PERMANENT) - return - - if(!imp_in) - small_countdown() - return - - message_admins("Explosive implant triggered in [imp_in] ([imp_in.key]). (JMP) ") - log_game("Explosive implant triggered in [imp_in] ([imp_in.key]).") - if(ishuman(imp_in)) - var/mob/living/carbon/human/T = imp_in - if(elevel == "Localized Limb" && part) - small_countdown() - return //to avoid hotspot_expose. - if(elevel == "Destroy Body") - explosion(get_turf(T), -1, 0, 2, 6) - T.gib() - if(elevel == "Full Explosion") - explosion_spread(get_turf(T), rand(8,13)) - T.gib() - else if(ismob(imp_in)) - var/mob/M = imp_in - M.gib() - - var/turf/F = get_turf(imp_in) - if(F) - F.hotspot_expose(3500,125) - qdel(src) - -/obj/item/implant/explosive/proc/small_countdown() - if(!imp_in) - visible_message(SPAN_WARNING("Something begins beeping...")) - if(ishuman(imp_in)) - var/message = "Something beeps inside of [imp_in][part ? "'s [part.name]" : ""]..." //for some reason SPAN_X and span() both hate having this in-line - imp_in.visible_message(SPAN_WARNING(message)) - else if(ismob(imp_in)) - imp_in.visible_message(SPAN_WARNING("Something beeps inside of [imp_in]...")) - playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) - addtimer(CALLBACK(src, PROC_REF(small_boom)), 25) - -/obj/item/implant/explosive/proc/small_boom() - if(!imp_in) - explosion(get_turf(src), -1, 0, 2, 4) - if(ishuman(imp_in) && part) - //No tearing off these parts since it's pretty much killing. Mangle them. - if(part.vital && !istype(part, /obj/item/organ/external/head)) //Head explodes - part.createwound(BRUISE, 70) - part.add_pain(50) - imp_in.visible_message(SPAN_WARNING("[imp_in]'s [part.name] bursts open with a horrible ripping noise!"), - SPAN_DANGER("Your [part.name] bursts open with a horrible ripping noise!"), - SPAN_WARNING("You hear a horrible ripping noise.")) - else - part.droplimb(0,DROPLIMB_BLUNT) - playsound(get_turf(imp_in), BP_IS_ROBOTIC(part) ? 'sound/effects/meteorimpact.ogg' : 'sound/effects/splat.ogg') - else if(ismob(imp_in)) - var/mob/M = imp_in - M.gib() //Simple mobs just get got - qdel(src) - -/proc/explosion_spread(turf/epicenter, power, adminlog = 1, z_transfer = UP|DOWN) - var/datum/explosiondata/data = new - data.epicenter = epicenter - data.rec_pow = power - data.spreading = TRUE - data.adminlog = adminlog - data.z_transfer = z_transfer - SSexplosives.queue(data) - -/obj/item/implant/explosive/implanted(mob/source, mob/user) - if(user.mind) - user.mind.store_memory("\The [src] in [source] can be activated by saying something containing the phrase ''[phrase]'', say [phrase] to attempt to activate.", 0, 0) - to_chat(usr, "\The [src] in [source] can be activated by saying something containing the phrase ''[phrase]'', say [phrase] to attempt to activate.") - return TRUE - -/obj/item/implant/explosive/attack_self(mob/user) - elevel = input(user, "What sort of explosion would you prefer?", "Implant Intent") as null|anything in possible_explosions - phrase = input("Choose activation phrase:") as text - var/list/replacechars = list("\"" = "",">" = "","<" = "","(" = "",")" = "") - phrase = replace_characters(phrase, replacechars) - user.mind.store_memory("\The [src] can be activated by saying something containing the phrase ''[phrase]'', say [phrase] to attempt to activate.", 0, 0) - to_chat(user, "\The [src] can be activated by saying something containing the phrase ''[phrase]'', say [phrase] to attempt to activate.") - setup_done = TRUE - -/obj/item/implant/explosive/emp_act(severity) - if(malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - switch (severity) - if(2.0) //Weak EMP will make implant tear limbs off. - if(prob(50)) - small_countdown() - if(1.0) //strong EMP will melt implant either making it go off, or disarming it - if(prob(70)) - if(prob(50)) - small_countdown() - else - if(prob(50)) - activate() //50% chance of bye bye - else - meltdown() //50% chance of implant disarming - addtimer(CALLBACK(src, PROC_REF(self_correct)), 20) - -/obj/item/implant/explosive/proc/self_correct() - malfunction-- - -/obj/item/implant/explosive/islegal() - return FALSE - -/obj/item/implant/explosive/New() - ..() - become_hearing_sensitive(ROUNDSTART_TRAIT) - -/obj/item/implant/explosive/Destroy() - return ..() - -/obj/item/implant/explosive/full - possible_explosions = list("Localized Limb", "Destroy Body", "Full Explosion") - -/obj/item/implant/explosive/deadman - name = "deadman explosive" - desc = "A military grade micro bio-explosive that detonates upon death." - icon_state = "implant_evil" - uses_codewords = FALSE - -/obj/item/implant/explosive/deadman/get_data() - . = {" -Implant Specifications:
-Name: Robust Corp RX-78 Employee Management Implant
-Life: Activates upon death.
-Important Notes: Explodes
-
-Implant Details:
-Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
-Special Features: Explodes
-Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - -/obj/item/implant/explosive/deadman/attack_self(mob/user) - return - -/obj/item/implant/explosive/deadman/hear(var/msg) - return - -/obj/item/implant/explosive/deadman/process() - if(malfunction) - STOP_PROCESSING(SSprocessing, src) - return - if (!implanted) - return - var/mob/M = imp_in - - if(M.stat == DEAD) - activate() - -/obj/item/implant/explosive/deadman/activate(var/cause) - small_countdown(src) - STOP_PROCESSING(SSprocessing, src) - -/obj/item/implant/explosive/deadman/small_boom() - if(imp_in) - explosion(get_turf(src), -1, 0, 1, 6) - imp_in.gib() - qdel(src) - -/obj/item/implant/explosive/deadman/implanted(mob/source) - START_PROCESSING(SSprocessing, src) - return TRUE - -/obj/item/implant/explosive/deadman/emp_act(severity) - if(malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - switch (severity) - if(3.0) - if(prob(1)) - small_countdown() - else if(prob(5)) - meltdown() - if(2.0) - if(prob(5)) - small_countdown() - else if (prob(10)) - meltdown() - if(1.0) - if(prob(10)) - small_countdown() - else if (prob(30)) - meltdown() - -/obj/item/implant/chem - name = "chemical implant" - desc = "Injects things." - allow_reagents = 1 - -/obj/item/implant/chem/get_data() - . = {" -Implant Specifications:
-Name: Robust Corp MJ-420 Prisoner Management Implant
-Life: Deactivates upon death but remains within the body.
-Important Notes: Due to the system functioning off of nutrients in the implanted subject's body, the subject
-will suffer from an increased appetite.

-
-Implant Details:
-Function: Contains a small capsule that can contain various chemicals. Upon receiving a specially encoded signal
-the implant releases the chemicals directly into the blood stream.
-Special Features: -Micro-Capsule- Can be loaded with any sort of chemical agent via the common syringe and can hold 50 units.
-Can only be loaded while still in its original case.
-Integrity: Implant will last so long as the subject is alive. However, if the subject suffers from malnutrition,
-the implant may become unstable and either pre-maturely inject the subject or simply break."} - - -/obj/item/implant/chem/New() - ..() - var/datum/reagents/R = new/datum/reagents(50) - reagents = R - R.my_atom = src - - -/obj/item/implant/chem/trigger(emote, source as mob) - if(emote == "deathgasp") - src.activate(src.reagents.total_volume) - return - - -/obj/item/implant/chem/activate(var/cause) - if((!cause) || (!src.imp_in)) return 0 - var/mob/living/carbon/R = src.imp_in - src.reagents.trans_to_mob(R, cause, CHEM_BLOOD) - to_chat(R, "You hear a faint *beep*.") - if(!src.reagents.total_volume) - to_chat(R, "You hear a faint click from your chest.") - spawn(0) - qdel(src) - -/obj/item/implant/chem/emp_act(severity) - if (malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - - switch(severity) - if(1) - if(prob(60)) - activate(20) - if(2) - if(prob(30)) - activate(5) - - spawn(20) - malfunction-- - -/obj/item/implant/mindshield - name = "mind shield implant" - desc = "A controversial and debatably unethical neurostimulator and autohypnosis device. When implanted against the amygdala, it ensures the host maintains a consistent personality, preventing outside interference through brainwashing or hypnotic suggestion." - -/obj/item/implant/mindshield/get_data() - . = {" -Implant Specifications:
-Name: [current_map.company_name] Employee Management Implant
-Life: Ten years.
-Important Notes: Personnel injected with this device tend to be much more resistant to brain washing and other external influences.
-
-Implant Details:
-Function: Contains a small pod of nanobots that manipulate the host's mental functions.
-Special Features: Will prevent and cure most forms of brainwashing.
-Integrity: Implant will last so long as the nanobots are inside the bloodstream."} - -/obj/item/implant/mindshield/emp_act(severity) - if (malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - - activate("emp") - if(severity == 1) - if(prob(50)) - meltdown() - else if (prob(50)) - malfunction = MALFUNCTION_PERMANENT - return - spawn(20) - malfunction-- - -/obj/item/implant/mindshield/ipc - name = "software protection chip" - desc = "A dedicated processor core designed to identify and terminate malignant software, ensuring a synthetics protection from outside hacking." - -/obj/item/implant/mindshield/ipc/implanted(mob/M) - if (!isipc(M)) - return - - ..() - -/obj/item/implant/mindshield/sol - name = "loyalty implant" - desc = "Makes you loyal to the Sol Alliance, or to a certain individual." - -/obj/item/implant/mindshield/sol/implanted(mob/M) - if(!istype(M, /mob/living/carbon/human)) return 0 - var/mob/living/carbon/human/H = M - var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) - if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE)) - H.visible_message("[H] seems to resist the implant!", "You feel the tendrils of the Sol Alliance try to invade your mind!") - return 0 - else - clear_antag_roles(H.mind, 1) - to_chat(H, "You feel a surge of loyalty towards Admiral Michael Frost.") - return 1 - -/obj/item/implant/adrenalin - name = "adrenalin" - desc = "Removes all stuns and knockdowns." - var/uses - -/obj/item/implant/adrenalin/get_data() - . = {" -Implant Specifications:
-Name: Cybersun Industries Adrenalin Implant
-Life: Five days.
-Important Notes: Illegal
-
-Implant Details: Subjects injected with implant can activate a massive injection of adrenalin.
-Function: Contains nanobots to stimulate body to mass-produce Adrenalin.
-Special Features: Will prevent and cure most forms of brainwashing.
-Integrity: Implant can only be used three times before the nanobots are depleted."} - - -/obj/item/implant/adrenalin/trigger(emote, mob/source as mob) - if (src.uses < 1) - return 0 - if (emote == "pale") - src.uses-- - to_chat(source, "You feel a sudden surge of energy!") - source.SetStunned(0) - source.SetWeakened(0) - source.SetParalysis(0) - - -/obj/item/implant/adrenalin/implanted(mob/source) - source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) - to_chat(source, "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate.") - return 1 - - -/obj/item/implant/death_alarm - name = "death alarm implant" - desc = "An alarm which monitors host vital signs and transmits a radio message upon death." - var/mobname = "Will Robinson" - -/obj/item/implant/death_alarm/get_data() - . = {" -Implant Specifications:
-Name: [current_map.company_name] \"Profit Margin\" Class Employee Lifesign Sensor
-Life: Activates upon death.
-Important Notes: Alerts crew to crewmember death.
-
-Implant Details:
-Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
-Special Features: Alerts crew to crewmember death.
-Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - -/obj/item/implant/death_alarm/process() - if (!implanted) - return - var/mob/M = imp_in - - if(QDELETED(M)) // If the mob got gibbed - M = null - activate() - else if(M.stat == 2) - activate("death") - -/obj/item/implant/death_alarm/activate(var/cause) - var/mob/M = imp_in - var/area/t = get_area(M) - switch (cause) - if("death") - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) - if(istype(t, /area/antag) || istype(t, /area/shuttle/mercenary) || istype(t, /area/shuttle/syndicate_elite) ) - //give the syndies a bit of stealth - a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm") - else - a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm") - qdel(a) - STOP_PROCESSING(SSprocessing, src) - if ("emp") - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) - var/name = prob(50) ? t.name : pick(the_station_areas) - a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm") - qdel(a) - else - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) - a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm") - qdel(a) - STOP_PROCESSING(SSprocessing, src) - -/obj/item/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this - if (malfunction) //so I'm just going to add a meltdown chance here - return - malfunction = MALFUNCTION_TEMPORARY - - activate("emp") //let's shout that this dude is dead - if(severity == 1) - if(prob(40)) //small chance of obvious meltdown - meltdown() - else if (prob(60)) //but more likely it will just quietly die - malfunction = MALFUNCTION_PERMANENT - STOP_PROCESSING(SSprocessing, src) - - spawn(20) - malfunction-- - -/obj/item/implant/death_alarm/implanted(mob/source as mob) - mobname = source.real_name - START_PROCESSING(SSprocessing, src) - return 1 - -/obj/item/implant/compressed - name = "compressed matter implant" - desc = "Based on compressed matter technology, can store a single item." - icon_state = "implant_evil" - var/activation_emote = "sigh" - var/obj/item/scanned = null - -/obj/item/implant/compressed/attackby(var/obj/item/T, mob/user) - if(T.isscrewdriver()) - if(!scanned) - to_chat(user, SPAN_NOTICE("There is nothing to remove from the implant.")) - else - to_chat(user, SPAN_NOTICE("You remove \the [scanned] from the implant.")) - user.put_in_hands(scanned) - scanned = null - if(istype(T, /obj/item/implanter)) - var/obj/item/implanter/implanter = T - if(implanter.imp) - to_chat(user, SPAN_NOTICE("\The [implanter] already has an implant loaded.")) - return - user.drop_from_inventory(src) - forceMove(implanter) - implanter.imp = src - implanter.update() - else - ..() - -/obj/item/implant/compressed/get_data() - . = {" -Implant Specifications:
-Name: [current_map.company_name] \"Profit Margin\" Class Employee Lifesign Sensor
-Life: Activates upon death.
-Important Notes: Alerts crew to crewmember death.
-
-Implant Details:
-Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
-Special Features: Alerts crew to crewmember death.
-Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - -/obj/item/implant/compressed/trigger(emote, mob/source as mob) - if (src.scanned == null) - return 0 - - if (emote == src.activation_emote) - to_chat(source, "The air glows as \the [src.scanned.name] uncompresses.") - activate() - -/obj/item/implant/compressed/activate() - var/turf/t = get_turf(src) - if (imp_in) - imp_in.put_in_hands(scanned) - else - scanned.forceMove(t) - qdel(src) - -/obj/item/implant/compressed/implanted(mob/source as mob) - src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - if (source.mind) - source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) - to_chat(source, "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.") - return 1 - -/obj/item/implant/compressed/islegal() - return 0 - -/obj/item/implant/aggression - name = "aggression implant" - desc = "An implant that microdoses its user with chemicals that induce anger." - -/obj/item/implant/aggression/get_data() - . = {" - Implant Specifications:
- Name: Aggression Implant
- Life: N/A.
- Important Notes: Users injected with this device get increasingly angry to a breaking point. Users tend to expire before the implant does.
-
- Implant Details:
- Function: Contains a small pod of nanobots that manipulate the host's mental functions.
- Integrity: Implant will last so long as the nanobots are inside the bloodstream."} - -/obj/item/implant/aggression/implanted(mob/M) - if(!istype(M, /mob/living/carbon/human)) - return FALSE - - var/mob/living/carbon/human/H = M - - for(var/obj/item/implant/mindshield/I in H) - if(I.implanted) - to_chat(H, SPAN_DANGER("Rage surges through your body, but the nanobots from your mind shield implant stop it soon after it starts!")) - return TRUE - - var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) - if(antag_data?.flags & ANTAG_IMPLANT_IMMUNE) - H.visible_message("[H] seems to resist the implant!", "You feel rage overtake your body, but you manage to fend it off by sheer will!") - log_and_message_admins("[key_name(H)] was implanted by an aggression implant, but was not effected.", H) - else if(antag_data?.id == MODE_LOYALIST) - clear_antag_roles(H.mind, 1) - to_chat(H, SPAN_DANGER("You feel a surge of rage override your loyalty!")) - log_and_message_admins("[key_name(H)] was implanted by an aggression implant, clearing their loyalist status!", H) - else - to_chat(H, SPAN_DANGER("You feel a surge of rage course through your body and very soul!")) - log_and_message_admins("[key_name(H)] was implanted by an aggression implant!", H) - return TRUE - -/obj/item/implant/aggression/emp_act(severity) - if(malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - - activate("emp") - if(severity == 1) - if(prob(50)) - meltdown() - else if(prob(50)) - malfunction = MALFUNCTION_PERMANENT - return - spawn(20) - malfunction-- - -/obj/item/implant/anti_augment - name = "augmentation disrupter implant" - desc = "An implant that emits signals able to disrupt the use of commonly used augments." - -/obj/item/implant/anti_augment/get_data() - . = {" -Implant Specifications:
-Name: Augmentation Disrupter Implant
-Life: Three Months.
-Important Notes: Emits a signal able to block most augments from functioning..
-
-Implant Details:
-Function: Emits a short radio wave that will block most augments.
-Special Features: Will stop the host from using any augment they might have.
-Integrity: Implant will last so long as it inside the host."} - -/obj/item/implant/anti_augment/emp_act(severity) - switch(severity) - if(1.0) - if (prob(75)) - qdel(src) - if(2.0) - if (prob(50)) - qdel(src) - if(3.0) - if (prob(25)) - qdel(src) - return - - #undef MALFUNCTION_TEMPORARY #undef MALFUNCTION_PERMANENT diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index 49b2f572cb4..4ccb03863e6 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -1,183 +1,86 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - +/** + * Item used to store implants. Can be renamed with a pen. Implants are moved between these and implanters when a mob uses an implanter on the case. + */ /obj/item/implantcase - name = "glass case" - desc = "A case containing an implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-0" + name = "implant case" + desc = "An aluminium case, which can safely contain an implant." + icon = 'icons/obj/item/implants.dmi' + icon_state = "implantcase" item_state = "implantcase" throw_speed = 1 throw_range = 5 w_class = ITEMSIZE_TINY + ///The implant within the case var/obj/item/implant/imp = null -/obj/item/implantcase/proc/update() - if (src.imp) - src.icon_state = text("implantcase-[]", src.imp.implant_color) - else - src.icon_state = "implantcase-0" - return +/obj/item/implantcase/Initialize(mapload) + . = ..() + if(ispath(imp)) + imp = new imp(src) + update_description() + update_icon() -/obj/item/implantcase/attackby(obj/item/I as obj, mob/user as mob) - ..() +/obj/item/implantcase/proc/update_description() + if(imp) + desc = "An aluminium case, containing \a [imp]." + origin_tech = imp.origin_tech + else + desc = "An aluminium case, which can safely contain an implant." + origin_tech.Cut() + + +/obj/item/implantcase/update_icon() + cut_overlays() + if (imp) + var/overlay_icon_state = "implantstorage_[imp.implant_icon]" + var/mutable_appearance/overlay_implant_icon = mutable_appearance(icon, overlay_icon_state) + add_overlay(overlay_implant_icon) + +/obj/item/implantcase/attackby(obj/item/I, mob/user) if (I.ispen()) - var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text + var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) if (user.get_active_hand() != I) return - if((!in_range(src, usr) && src.loc != user)) + if((!in_range(src, usr) && loc != user)) return t = sanitizeSafe(t, MAX_NAME_LEN) if(t) - src.name = text("Glass Case - '[]'", t) + src.name = text("implant case - '[]'", t) + desc = "An aluminium case, containing \a [t] implant." else - src.name = "Glass Case" + src.name = "implant case" + desc = "An aluminium case, which can safely contain an implant." else if(istype(I, /obj/item/reagent_containers/syringe)) - if(!src.imp) return - if(!src.imp.allow_reagents) return - if(src.imp.reagents.total_volume >= src.imp.reagents.maximum_volume) - to_chat(user, "\The [src] is full.") - else - var/trans = I.reagents.trans_to_obj(src.imp, 5) - if (trans > 0) - to_chat(user, "You inject [trans] units of the solution. The syringe now contains [I.reagents.total_volume] units.") + imp.attackby(I, user) else if (istype(I, /obj/item/implanter)) var/obj/item/implanter/M = I - if (M.imp) - if ((src.imp || M.imp.implanted)) - return + if (M.imp && !imp && !M.imp.implanted) M.imp.forceMove(src) - src.imp = M.imp + imp = M.imp M.imp = null - src.update() - M.update() + else if (imp && !M.imp) + imp.forceMove(M) + M.imp = src.imp + imp = null + update_description() + update_icon() + M.update_icon() + else if (istype(I, /obj/item/implant)) + if(imp == null) + to_chat(user, SPAN_NOTICE("You slide \the [I] into \the [src].")) + user.drop_from_inventory(I,src) + imp = I else - if (src.imp) - if (M.imp) - return - src.imp.forceMove(M) - M.imp = src.imp - src.imp = null - update() - M.update() - return - - -/obj/item/implantcase/tracking - name = "glass case - 'tracking'" - desc = "A case containing a tracking implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/tracking/New() - src.imp = new /obj/item/implant/tracking( src ) + to_chat(user, SPAN_WARNING("\The [src] already has an implant inside of it!")) + update_description() + update_icon() + else if(istype(I, /obj/item/implantpad)) + var/obj/item/implantpad/pad = I + if(!pad.case) + user.drop_from_inventory(src,pad) + pad.case = src + pad.update_icon() + else + to_chat(user, SPAN_WARNING("\The [pad] already has an implant case attached to it!")) ..() - return - -/obj/item/implantcase/explosive - name = "glass case - 'explosive'" - desc = "A case containing an explosive implant." - icon_state = "implantcase-r" - -/obj/item/implantcase/explosive/New() - src.imp = new /obj/item/implant/explosive( src ) - ..() - return - - -/obj/item/implantcase/chem - name = "glass case - 'chem'" - desc = "A case containing a chemical implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/chem/New() - src.imp = new /obj/item/implant/chem( src ) - ..() - return - - -/obj/item/implantcase/loyalty - name = "glass case - 'mind shield'" - desc = "A case containing a mind shield implant." - icon_state = "implantcase-r" - -/obj/item/implantcase/loyalty/New() - src.imp = new /obj/item/implant/mindshield( src ) - ..() - return - - -/obj/item/implantcase/death_alarm - name = "glass case - 'death alarm'" - desc = "A case containing a death alarm implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/death_alarm/New() - src.imp = new /obj/item/implant/death_alarm( src ) - ..() - return - - -/obj/item/implantcase/freedom - name = "glass case - 'freedom'" - desc = "A case containing a freedom implant." - icon_state = "implantcase-r" - -/obj/item/implantcase/freedom/New() - src.imp = new /obj/item/implant/freedom( src ) - ..() - return - - -/obj/item/implantcase/adrenalin - name = "glass case - 'adrenalin'" - desc = "A case containing an adrenalin implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/adrenalin/New() - src.imp = new /obj/item/implant/adrenalin( src ) - ..() - return - - -/obj/item/implantcase/explosive/deadman - name = "glass case - 'explosive'" - desc = "A case containing an explosive." - icon_state = "implantcase-r" - -/obj/item/implantcase/explosive/deadman/New() - src.imp = new /obj/item/implant/explosive/deadman( src ) - ..() - return - - -/obj/item/implantcase/health - name = "glass case - 'health'" - desc = "A case containing a health tracking implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/health/New() - src.imp = new /obj/item/implant/health( src ) - ..() - return - - -/obj/item/implantcase/aggression - name = "glass case - 'aggression'" - desc = "A case containing an aggression inducing implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/aggression/New() - src.imp = new /obj/item/implant/aggression(src) - ..() - return - - -/obj/item/implantcase/anti_augment - name = "glass case - 'augmentation disrupter'" - desc = "A case containing an augmentation disrupter implant." - icon_state = "implantcase-b" - -/obj/item/implantcase/anti_augment/New() - src.imp = new /obj/item/implant/anti_augment(src) - ..() - return diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 6dfc7b56764..abcd38e60e6 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -1,32 +1,35 @@ /obj/item/implanter name = "implanter" - icon = 'icons/obj/item/reagent_containers/syringe.dmi' + icon = 'icons/obj/item/implants.dmi' contained_sprite = TRUE - icon_state = "implanter0" - item_state = "syringe_0" + icon_state = "implanter-0" throw_speed = 1 throw_range = 5 w_class = ITEMSIZE_SMALL matter = list(DEFAULT_WALL_MATERIAL = 320, MATERIAL_GLASS = 800) var/obj/item/implant/imp = null -/obj/item/implanter/attack_self(var/mob/user) - if(!imp) - return ..() - imp.forceMove(get_turf(src)) - user.put_in_hands(imp) - to_chat(user, "You remove \the [imp] from \the [src].") - name = "implanter" - imp = null - update() - return +/obj/item/implanter/New() + if(ispath(imp)) + imp = new imp(src) + ..() + update_icon() -/obj/item/implanter/proc/update() +/obj/item/implanter/update_icon() + cut_overlays() + icon_state = "implanter-[imp ? "1" : "0"]" if (imp) - icon_state = "implanter1" + var/mutable_appearance/overlay_implant_icon = mutable_appearance(icon, "implanter-overlay") + overlay_implant_icon.color = imp.implant_color + add_overlay(overlay_implant_icon) + +/obj/item/implanter/attackby(obj/item/I, mob/user) + if(!imp && istype(I, /obj/item/implant) && user.unEquip(I,src)) + to_chat(usr, SPAN_NOTICE("You slide \the [I] into \the [src].")) + imp = I + update_icon() else - icon_state = "implanter0" - return + ..() /obj/item/implanter/attack(mob/living/carbon/human/M, mob/user, var/target_zone) if(!istype(M)) @@ -35,15 +38,15 @@ var/obj/item/organ/external/affected = M.get_organ(target_zone) if(user && imp && affected) - M.visible_message("[user] is attempting to implant [M] in \the [affected.name].") + M.visible_message(SPAN_WARNING("[user] is attempting to implant [M] in \the [affected.name].")) user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) user.do_attack_animation(M) var/turf/T1 = get_turf(M) - if (T1 && ((M == user) || do_after(user, 50))) + if (T1 && ((M == user) || do_after(user, 5 SECONDS))) if(user && M && (get_turf(M) == T1) && src && imp) - M.visible_message("[M] has been implanted by [user] in the [affected.name].") + M.visible_message(SPAN_WARNING("[M] has been implanted by [user] in the [affected.name].")) admin_attack_log(user, M, "Implanted using \the [name] ([imp.name])", "Implanted with \the [name] ([imp.name])", "used an implanter, [name] ([imp.name]), on") @@ -54,101 +57,12 @@ affected.implants += imp imp.part = affected BITSET(M.hud_updateflag, IMPLOYAL_HUD) - if(istype(imp, /obj/item/implanter/loyalty)) - to_chat(M, "") imp = null - update() + update_icon() return -/obj/item/implanter/loyalty - name = "implanter-loyalty" - -/obj/item/implanter/loyalty/New() - imp = new /obj/item/implant/mindshield(src) - ..() - update() - return - -/obj/item/implanter/explosive - name = "implanter (E)" - -/obj/item/implanter/explosive/New() - imp = new /obj/item/implant/explosive(src) - ..() - update() - return - -/obj/item/implanter/adrenalin - name = "implanter-adrenalin" - -/obj/item/implanter/adrenalin/New() - imp = new /obj/item/implant/adrenalin(src) - ..() - update() - return - -/obj/item/implanter/compressed - name = "implanter (C)" - -/obj/item/implanter/compressed/New() - imp = new /obj/item/implant/compressed( src ) - ..() - update() - return - -/obj/item/implanter/compressed/attack(mob/M as mob, mob/user as mob) - var/obj/item/implant/compressed/c = imp - if (!c) return - if (c.scanned == null) - to_chat(user, "Please scan an object with the implanter first.") - return - ..() - -/obj/item/implanter/compressed/afterattack(atom/A, mob/user as mob, proximity) - if(!proximity) - return - if(istype(A,/obj/item) && imp) - var/obj/item/implant/compressed/c = imp - if(istype(A,/obj/item/implant/compressed)) - to_chat(user, SPAN_NOTICE("The implant is loaded into the implanter.")) - return - if (c.scanned) - to_chat(user, SPAN_WARNING("Something is already scanned inside the implant!")) - return - c.scanned = A - if(istype(A.loc,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = A.loc - H.remove_from_mob(A) - else if(istype(A.loc,/obj/item/storage)) - var/obj/item/storage/S = A.loc - S.remove_from_storage(A) - A.loc.contents.Remove(A) - update() - -/obj/item/implanter/freedom/Initialize() - imp = new /obj/item/implant/freedom( src ) - . = ..() - update() - -/obj/item/implanter/uplink - name = "implanter (U)" - -/obj/item/implanter/uplink/Initialize() - imp = new /obj/item/implant/uplink( src ) - . = ..() - update() - -/obj/item/implanter/anti_augment - name = "implanter-augmentation disrupter" - -/obj/item/implanter/anti_augment/New() - imp = new /obj/item/implant/anti_augment(src) - ..() - update() - return - /obj/item/implanter/ipc_tag name = "IPC tag implanter" desc = "A special implanter used for implanting synthetics with a special tag." @@ -157,9 +71,9 @@ /obj/item/implanter/ipc_tag/Initialize() . = ..() ipc_tag = new /obj/item/organ/internal/ipc_tag(src) - update() + update_icon() -/obj/item/implanter/ipc_tag/update() +/obj/item/implanter/ipc_tag/update_icon() if(ipc_tag) icon_state = "cimplanter1" else @@ -195,7 +109,7 @@ ipc_tag.serial_number = uppertext(dd_limittext(md5(M.real_name), 12)) ipc_tag = null - update() + update_icon() /obj/item/implanter/ipc_tag/attackby(obj/item/I, mob/user) if(I.isscrewdriver()) @@ -206,7 +120,7 @@ ipc_tag.forceMove(get_turf(user)) user.put_in_hands(ipc_tag) ipc_tag = null - update() + update_icon() return if(istype(I, /obj/item/organ/internal/ipc_tag)) if(ipc_tag) @@ -214,6 +128,6 @@ return ipc_tag = I user.drop_from_inventory(I, src) - update() + update_icon() return ..() diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm deleted file mode 100644 index 20ce9ea08ab..00000000000 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ /dev/null @@ -1,74 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/implant/freedom - name = "freedom implant" - desc = "Use this to escape from those evil Red Shirts." - implant_color = "r" - var/activation_emote = "chuckle" - var/uses = 1 - -/obj/item/implant/freedom/New() - uses = rand(1, 5) - ..() - -/obj/item/implant/freedom/trigger(emote, mob/living/carbon/source) - if(!activation_emote) - return - if(uses < 1) - to_chat(source, SPAN_WARNING("\The [src] gives a faint beep inside your head, indicating that it's out of uses!")) - activation_emote = null //Disable this to allow them to emote normally - return - if(emote == activation_emote) - uses-- - to_chat(source, "You feel a faint click.") - if(source.handcuffed) - var/obj/item/W = source.handcuffed - source.handcuffed = null - if(source.buckled_to && source.buckled_to.buckle_require_restraints) - source.buckled_to.unbuckle() - source.update_inv_handcuffed() - if(source.client) - source.client.screen -= W - if(W) - W.forceMove(source.loc) - dropped(source) - if (W) - W.layer = initial(W.layer) - if(source.legcuffed) - var/obj/item/W = source.legcuffed - source.legcuffed = null - source.update_inv_legcuffed() - if(source.client) - source.client.screen -= W - if(W) - W.forceMove(source.loc) - dropped(source) - if(W) - W.layer = initial(W.layer) - return - - -/obj/item/implant/freedom/implanted(mob/living/carbon/source) - activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - if(source.mind) - source.mind.store_memory("\The [src] can be activated by using the [activation_emote] emote, say *[activation_emote] to attempt to activate.") - to_chat(source, "The implanted [src] can be activated by using the [activation_emote] emote, say *[activation_emote] to attempt to activate.") - return TRUE - - -/obj/item/implant/freedom/get_data() - var/dat = {" -Implant Specifications:
-Name: Freedom Beacon
-Life: optimum 5 uses
-Important Notes: Illegal
-
-Implant Details:
-Function: Transmits a specialized cluster of signals to override handcuff locking -mechanisms
-Special Features:
-Neuro-Scan- Analyzes certain shadow signals in the nervous system
-Integrity: The battery is extremely weak and commonly after injection its -life can drive down to only 1 use.
-No Implant Specifics"} - return dat diff --git a/code/game/objects/items/weapons/implants/implantpad.dm b/code/game/objects/items/weapons/implants/implantpad.dm index f0bd1cbcd44..a2ffd62317d 100644 --- a/code/game/objects/items/weapons/implants/implantpad.dm +++ b/code/game/objects/items/weapons/implants/implantpad.dm @@ -1,7 +1,7 @@ /obj/item/implantpad name = "implantpad" desc = "A device used to modify implants." - icon = 'icons/obj/items.dmi' + icon = 'icons/obj/item/implants.dmi' icon_state = "implantpad-0" item_state = "electronic" throw_speed = 1 @@ -12,16 +12,23 @@ var/listening = TRUE /obj/item/implantpad/update_icon() + cut_overlays() icon_state = "implantpad-[case ? "1" : "0"]" + if(case.imp) + var/obj/item/implant/caseimplant = case.imp + var/implant_overlay_icon_state = "implantstorage_[caseimplant.implant_icon]" + var/mutable_appearance/implant_case_implant_overlay = mutable_appearance(icon, implant_overlay_icon_state) + add_overlay(implant_case_implant_overlay) + /obj/item/implantpad/attack_hand(mob/user) - if(src.case && (user.l_hand == src || user.r_hand == src)) + if(case && (user.l_hand == src || user.r_hand == src)) user.put_in_active_hand(case) - src.case.add_fingerprint(user) - src.case = null + case.add_fingerprint(user) + case = null - src.add_fingerprint(user) + add_fingerprint(user) update_icon() return return ..() @@ -30,28 +37,17 @@ if(istype(C, /obj/item/implantcase)) if(!case) user.drop_from_inventory(C,src) - src.case = C + case = C update_icon() else - to_chat(user, SPAN_WARNING("\The [src] already has an implant case inside it!")) - return + to_chat(user, SPAN_WARNING("\The [src] already has an implant case attached to it!")) ..() /obj/item/implantpad/attack_self(mob/user) - user.set_machine(src) - var/dat = "Implant Mini-Computer:
" - if (src.case) - if(src.case.imp) - if(istype(src.case.imp, /obj/item/implant)) - dat += src.case.imp.get_data() - else - dat += "The implant casing is empty." + if(case.imp) + case.imp.interact(user) else - dat += "Please insert an implant casing!" - - var/datum/browser/implantpad_win = new(user, "implantpad", capitalize_first_letters(name)) - implantpad_win.set_content(dat) - implantpad_win.open() + to_chat(user, SPAN_WARNING("There's no implant loaded in \the [src]!")) /obj/item/implantpad/Topic(href, href_list) ..() @@ -68,4 +64,4 @@ src.attack_self(M) src.add_fingerprint(usr) else - usr << browse(null, "window=implantpad") \ No newline at end of file + usr << browse(null, "window=implantpad") diff --git a/code/game/objects/items/weapons/implants/implants/adrenaline.dm b/code/game/objects/items/weapons/implants/implants/adrenaline.dm new file mode 100644 index 00000000000..5f3ff7dea20 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/adrenaline.dm @@ -0,0 +1,41 @@ +/obj/item/implant/adrenaline + name = "adrenaline implant" + desc = "Removes all stuns and knockdowns." + icon_state = "implant_chem" //Temporary, this is currently unused so no need for a custom sprite + implant_icon = "chem" //Ditto + implant_color = "#eba7eb" //Ditto + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_ILLEGAL = 2) + default_action_type = /datum/action/item_action/hands_free/activate/implant/adrenaline + action_button_name = "Activate Adrenaline Implant" + var/uses = 3 + +/obj/item/implant/adrenaline/get_data() + . = {" +Implant Specifications:
+Name: Kumar Arms ZV-16 Combat Readiness Implant
+Life: Five days.
+Important Notes: Illegal for non-licensed personnel in Biesel space.
+
+Implant Details: Subjects injected with implant can activate a massive injection of adrenaline.
+Function: Contains nanobots to stimulate body to mass-produce Adrenaline.
+Integrity: Implant can only be used three times before the nanobots are depleted."} + +/obj/item/implant/adrenaline/activate() + if (malfunction || !imp_in) + return + if (uses < 1) + to_chat(imp_in, SPAN_WARNING("\The [src] gives a faint beep inside your head, indicating that it's out of uses!")) + return + uses-- + to_chat(imp_in, SPAN_NOTICE("You feel a sudden surge of energy!")) + imp_in.SetStunned(0) + imp_in.SetWeakened(0) + imp_in.SetParalysis(0) + +/obj/item/implantcase/adrenaline + name = "glass case - 'adrenalin'" + imp = /obj/item/implant/adrenaline + +/obj/item/implanter/adrenaline + name = "implanter-adrenaline" + imp = /obj/item/implant/adrenaline diff --git a/code/game/objects/items/weapons/implants/implants/aggression.dm b/code/game/objects/items/weapons/implants/implants/aggression.dm new file mode 100644 index 00000000000..b77ee2e408b --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/aggression.dm @@ -0,0 +1,67 @@ +#define MALFUNCTION_TEMPORARY 1 +#define MALFUNCTION_PERMANENT 2 + +/obj/item/implant/aggression + name = "aggression implant" + desc = "An implant that microdoses its user with chemicals that induce anger." + icon_state = "implant_chem" //Temporary + implant_icon = "chem" //Ditto + implant_color = "#eba7eb" //Ditto + default_action_type = null + +/obj/item/implant/aggression/get_data() + . = {" + Implant Specifications:
+ Name: Aggression Implant
+ Life: N/A.
+ Important Notes: Users injected with this device get increasingly angry to a breaking point. Users tend to expire before the implant does.
+
+ Implant Details:
+ Function: Contains a small pod of nanobots that manipulate the host's mental functions.
+ Integrity: Implant will last so long as the nanobots are inside the bloodstream."} + +/obj/item/implant/aggression/implanted(mob/M) + if(!istype(M, /mob/living/carbon/human)) + return FALSE + + var/mob/living/carbon/human/H = M + + for(var/obj/item/implant/mindshield/I in H) + if(I.implanted) + to_chat(H, SPAN_DANGER("Rage surges through your body, but the nanobots from your mind shield implant stop it soon after it starts!")) + return TRUE + + var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) + if(antag_data?.flags & ANTAG_IMPLANT_IMMUNE) + H.visible_message("[H] seems to resist the implant!", "You feel rage overtake your body, but you manage to fend it off by sheer will!") + log_and_message_admins("[key_name(H)] was implanted by an aggression implant, but was not affected.", H) + else if(antag_data?.id == MODE_LOYALIST) + clear_antag_roles(H.mind, 1) + to_chat(H, SPAN_DANGER("You feel a surge of rage override your loyalty!")) + log_and_message_admins("[key_name(H)] was implanted by an aggression implant, clearing their loyalist status!", H) + else + to_chat(H, SPAN_DANGER("You feel a surge of rage course through your body and very soul!")) + log_and_message_admins("[key_name(H)] was implanted by an aggression implant!", H) + return TRUE + +/obj/item/implant/aggression/emp_act(severity) + if(malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + + activate("emp") + if(severity == 1) + if(prob(50)) + meltdown() + else if(prob(50)) + malfunction = MALFUNCTION_PERMANENT + return + spawn(20) + malfunction-- + +#undef MALFUNCTION_TEMPORARY +#undef MALFUNCTION_PERMANENT + +/obj/item/implantcase/aggression + name = "glass case - 'aggression'" + imp = /obj/item/implant/aggression diff --git a/code/game/objects/items/weapons/implants/implants/anti-augment.dm b/code/game/objects/items/weapons/implants/implants/anti-augment.dm new file mode 100644 index 00000000000..9267f9f9b07 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/anti-augment.dm @@ -0,0 +1,44 @@ +/obj/item/implant/anti_augment + name = "augmentation disrupter implant" + desc = "An implant that emits signals able to disrupt the use of commonly used augments." + icon_state = "implant_excel" //Temporary + implant_icon = "excel" //Ditto + implant_color = "#ffd079" //Ditto + default_action_type = null + known = TRUE + +/obj/item/implant/anti_augment/get_data() + . = {" +Implant Specifications:
+Name: Hephaestus Industries HP-152 Augmentation Disrupter Implant
+Life: Three Months.
+Important Notes: Emits a signal able to block most augments from functioning.
+
+Implant Details:
+Function: Emits a short radio wave that will block most augments.
+Special Features: Will stop the host from using any augment they might have.
+Integrity: Implant will last so long as it inside the host."} + +/obj/item/implant/anti_augment/isLegal() + return TRUE + +/obj/item/implant/anti_augment/emp_act(severity) + switch(severity) + if(1.0) + if (prob(75)) + qdel(src) + if(2.0) + if (prob(50)) + qdel(src) + if(3.0) + if (prob(25)) + qdel(src) + return + +/obj/item/implantcase/anti_augment + name = "glass case - 'augmentation disrupter'" + imp = /obj/item/implant/anti_augment + +/obj/item/implanter/anti_augment + name = "implanter-augmentation disrupter" + imp = /obj/item/implant/anti_augment diff --git a/code/game/objects/items/weapons/implants/implants/chem.dm b/code/game/objects/items/weapons/implants/implants/chem.dm new file mode 100644 index 00000000000..9281e1289f1 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/chem.dm @@ -0,0 +1,84 @@ +#define MALFUNCTION_TEMPORARY 1 + +/obj/item/implant/chem + name = "chemical implant" + desc = "Injects things." + icon_state = "implant_chem" + implant_icon = "chem" + implant_color = "#eba7eb" + origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) + default_action_type = /datum/action/item_action/hands_free/activate/implant/chemical + action_button_name = "Dispense Reagents from Chemical Implant" + known = TRUE + +/obj/item/implant/chem/get_data() + . = {" +Implant Specifications:
+Name: Ingkom ZV-02 Prisoner Management Implant
+Life: Deactivates upon death but remains within the body.
+Important Notes: Due to the system functioning off of nutrients in the implanted subject's body, the subject
+will suffer from an increased appetite.

+
+Implant Details:
+Function: Contains a small capsule that can contain various chemicals. Upon receiving a specially encoded signal
+the implant releases the chemicals directly into the blood stream.
+Special Features: +Micro-Capsule- Can be loaded with any sort of chemical agent via the common syringe and can hold 50 units.
+Can only be loaded while still in its original case.
+Integrity: Implant will last so long as the subject is alive. However, if the subject suffers from malnutrition,
+the implant may become unstable and either pre-maturely inject the subject or simply break."} + +/obj/item/implant/chem/New() + ..() + var/datum/reagents/R = new/datum/reagents(50) + reagents = R + R.my_atom = src + +/obj/item/implant/chem/trigger(emote, source as mob) + if(emote == "deathgasp") + src.activate(src.reagents.total_volume) + return + +/obj/item/implant/chem/activate(cause) + if((malfunction) || (!iscarbon(imp_in))) + return 0 + if(!cause) + cause = rand(1, 25) + var/mob/living/carbon/R = imp_in + src.reagents.trans_to_mob(R, cause, CHEM_BLOOD) + to_chat(R, SPAN_HEAR("You hear a faint *beep*.")) + if(!reagents.total_volume) + to_chat(R, SPAN_WARNING("You hear a faint *click*.")) + +/obj/item/implant/chem/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/reagent_containers/syringe)) + if(reagents.total_volume >= reagents.maximum_volume) + to_chat(user, SPAN_WARNING("\The [src] is full.")) + else + if(do_after(user, 0.5 SECONDS, src)) + I.reagents.trans_to_obj(src, 5) + to_chat(user, SPAN_NOTICE("You inject 5 units of the solution. The syringe now contains [I.reagents.total_volume] units.")) + else + ..() + +/obj/item/implant/chem/emp_act(severity) + if (malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + + switch(severity) + if(1) + if(prob(60)) + activate(20) + if(2) + if(prob(30)) + activate(5) + + spawn(20) + malfunction-- + +#undef MALFUNCTION_TEMPORARY + +/obj/item/implantcase/chem + name = "glass case - 'chem'" + imp = /obj/item/implant/chem diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implants/circuit.dm similarity index 96% rename from code/game/objects/items/weapons/implants/implantcircuits.dm rename to code/game/objects/items/weapons/implants/implants/circuit.dm index 6231c27149a..09c2a77c20b 100644 --- a/code/game/objects/items/weapons/implants/implantcircuits.dm +++ b/code/game/objects/items/weapons/implants/implants/circuit.dm @@ -3,9 +3,10 @@ desc = "It's a case, for building very tiny electronics with." icon = 'icons/obj/assemblies/electronic_setups.dmi' icon_state = "setup_implant" + known = TRUE var/obj/item/device/electronic_assembly/implant/IC = null -/obj/item/implant/integrated_circuit/islegal() +/obj/item/implant/integrated_circuit/isLegal() return TRUE /obj/item/implant/integrated_circuit/Initialize() diff --git a/code/game/objects/items/weapons/implants/implants/compressed_matter.dm b/code/game/objects/items/weapons/implants/implants/compressed_matter.dm new file mode 100644 index 00000000000..674d4872853 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/compressed_matter.dm @@ -0,0 +1,69 @@ +/obj/item/implant/compressed //TODO: This code is awful, and this implant is difficult to use. Port atom storage, and make the implant its own storage item + name = "compressed matter implant" + desc = "Based on compressed matter technology, can store a single item." + icon_state = "implant_storage" + implant_icon = "storage" + implant_color = "#143464" + origin_tech = list(TECH_MATERIAL = 4, TECH_BIO = 2, TECH_ILLEGAL = 2) + default_action_type = /datum/action/item_action/hands_free/activate/implant/compressed + action_button_name = "Retrieve Item from Compressed Implant" + hidden = TRUE + var/obj/item/scanned = null + +/obj/item/implant/compressed/attackby(var/obj/item/T, mob/user) + if(T.isscrewdriver()) + if(!scanned) + to_chat(user, SPAN_NOTICE("There is nothing to remove from the implant.")) + else + to_chat(user, SPAN_NOTICE("You remove \the [scanned] from the implant.")) + user.put_in_hands(scanned) + scanned = null + if(istype(T, /obj/item/implanter)) + var/obj/item/implanter/implanter = T + if(implanter.imp) + to_chat(user, SPAN_NOTICE("\The [implanter] already has an implant loaded.")) + return + user.drop_from_inventory(src) + forceMove(implanter) + implanter.imp = src + implanter.update_icon() + else + ..() + +/obj/item/implant/compressed/get_data() + . = {" +Implant Specifications:
+Name: NT-06 Covert Insertion Implant
+Life: Up to 6 months.
+Important Notes: Uses a localized pocket of bluespace to store an item, that cannot be detected from most external sources.
+
+Implant Details:
+Function: Can store one item, that can be retrieved at will.
+Special Features:
+Neuro-Scan- Analyzes certain shadow signals in the nervous system
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + +/obj/item/implant/compressed/trigger(emote, mob/source as mob) + if (src.scanned == null) + return FALSE + + to_chat(source, SPAN_NOTICE("The air glows as \the [src.scanned.name] uncompresses.")) + activate() + +/obj/item/implant/compressed/activate() + var/turf/t = get_turf(src) + if (imp_in) + imp_in.put_in_hands(scanned) + else + scanned.forceMove(t) + qdel(src) + +/obj/item/implant/compressed/implanted(mob/source as mob) + return TRUE + +/obj/item/implant/compressed/isLegal() + return FALSE + +/obj/item/implanter/compressed + name = "implanter (C)" + imp = /obj/item/implant/compressed diff --git a/code/game/objects/items/weapons/implants/implants/death_alarm.dm b/code/game/objects/items/weapons/implants/implants/death_alarm.dm new file mode 100644 index 00000000000..75733b37ff4 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/death_alarm.dm @@ -0,0 +1,83 @@ +#define MALFUNCTION_TEMPORARY 1 +#define MALFUNCTION_PERMANENT 2 + +/obj/item/implant/death_alarm + name = "death alarm implant" + desc = "An alarm which monitors host vital signs and transmits a radio message upon death." + icon_state = "implant_deathalarm" + implant_icon = "deathalarm" + implant_color = "#9cdb43" + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 3, TECH_DATA = 2) + default_action_type = null + known = TRUE + var/mobname = "Will Robinson" + +/obj/item/implant/death_alarm/get_data() + . = {" +Implant Specifications:
+Name: Idris Incorporated ID-15 \"Profit Margin\" Class Sapient Lifesign Sensor
+Life: Activates upon death.
+Important Notes: Alerts crew to crewmember death.
+
+Implant Details:
+Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
+Special Features: Alerts crew to crewmember death.
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + +/obj/item/implant/death_alarm/process() + if (!implanted) + return + var/mob/M = imp_in + + if(QDELETED(M)) // If the mob got gibbed + M = null + activate(null) + else if(M.stat == DEAD) + activate("death") + +/obj/item/implant/death_alarm/activate(cause = "emp") + if (malfunction) + return + var/mob/M = imp_in + var/area/A = get_area(M) + var/location = A.name + if(cause == "emp" && prob(50)) + location = pick(teleportbeacons) + if(!A.requires_power) // We assume areas that don't use power are special zones + var/area/default = world.area + location = initial(default.name) + var/death_message = "[mobname] has died in [location]!" + if(!cause) + death_message = "[mobname] has died-zzzzt in-in-in..." + STOP_PROCESSING(SSprocessing, src) + + for(var/channel in list("Security", "Medical", "Command")) + global_announcer.autosay(death_message, "[mobname]'s Death Alarm", channel) + +/obj/item/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this + if (malfunction) //so I'm just going to add a meltdown chance here + return + malfunction = MALFUNCTION_TEMPORARY + + activate("emp") //let's shout that this dude is dead + if(severity == 1) + if(prob(40)) //small chance of obvious meltdown + meltdown() + else if (prob(60)) //but more likely it will just quietly die + malfunction = MALFUNCTION_PERMANENT + STOP_PROCESSING(SSprocessing, src) + + spawn(20) + malfunction-- + +/obj/item/implant/death_alarm/implanted(mob/source as mob) + mobname = source.real_name + START_PROCESSING(SSprocessing, src) + return TRUE + +#undef MALFUNCTION_TEMPORARY +#undef MALFUNCTION_PERMANENT + +/obj/item/implantcase/death_alarm + name = "glass case - 'death alarm'" + imp = /obj/item/implant/death_alarm diff --git a/code/game/objects/items/weapons/implants/implants/emp.dm b/code/game/objects/items/weapons/implants/implants/emp.dm new file mode 100644 index 00000000000..9d34bf79c79 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/emp.dm @@ -0,0 +1,23 @@ +/obj/item/implant/emp + name = "\improper EMP implant" + desc = "Triggers an EMP." + icon_state = "implant_emp" + implant_icon = "emp" + implant_color = "#249fde" + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_ILLEGAL = 2) + default_action_type = /datum/action/item_action/hands_free/activate/implant/emp + action_button_name = "Activate EMP Implant" + var/uses = 3 + +/obj/item/implant/emp/activate() + if (malfunction || !imp_in) + return + if (uses < 1) + to_chat(imp_in, SPAN_WARNING("\The [src] gives a faint beep inside your head, indicating that it's out of uses!")) + return + uses-- + empulse(imp_in, 3, 5) + +/obj/item/implantcase/emp + name = "implant case - 'EMP'" + imp = /obj/item/implant/emp diff --git a/code/game/objects/items/weapons/implants/implants/explosive.dm b/code/game/objects/items/weapons/implants/implants/explosive.dm new file mode 100644 index 00000000000..a0356ebefc0 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/explosive.dm @@ -0,0 +1,320 @@ +#define MALFUNCTION_TEMPORARY 1 +#define MALFUNCTION_PERMANENT 2 + +//BS12 Explosive +/obj/item/implant/explosive + name = "explosive implant" + desc = "A military grade micro bio-explosive. Highly dangerous." + icon_state = "implant_explosive" + implant_icon = "explosive" + implant_color = "#e46b5d" + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_ILLEGAL = 3) + default_action_type = /datum/action/item_action/hands_free/activate/implant/explosive + action_button_name = "Activate Explosive Implant" + hidden = TRUE + var/elevel = "Localized Limb" + var/explodes_on_death = FALSE + var/phrase + var/code = 13 + var/frequency = 1443 + var/datum/radio_frequency/radio_connection + var/list/possible_explosions = list("Localized Limb", "Destroy Body") + var/warning_message = "Tampering detected. Tampering detected." + +/obj/item/implant/explosive/Initialize() + . = ..() + setFrequency(frequency) + +/obj/item/implant/explosive/get_data() + . = {" +Implant Specifications:
+Name: Kumar Arms ZX-01 \"Obscuration\" Class Implant
+Life: Activates upon codephrase.
+Important Notes: Explodes
+
+Implant Details:
+Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
+Special Features: Explodes. Explosion severity can be altered.
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + if(!malfunction) + . += {" +
Explosion yield mode: + [elevel ? elevel : "NONE SET"]
+ Activation phrase:
+ [phrase ? phrase : "NONE SET"]
+ Frequency:
+ - + - + [format_frequency(src.frequency)] + + + +
+ Code:
+ - + - + [src.code] + + + +
+ Tampering warning message:
+ This will be broadcasted on radio if the implant is exposed during surgery.
+ [warning_message ? warning_message : "NONE SET"] + "} + +/obj/item/implant/explosive/Topic(href, href_list) + ..() + if(href_list["freq"]) + var/new_frequency = frequency + text2num(href_list["freq"]) + new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + setFrequency(new_frequency) + interact(usr) + if(href_list["code"]) + var/adj = text2num(href_list["code"]) + if(!adj) + code = input("Set radio activation code","Radio activation") as num + else + code += adj + code = clamp(code,1,100) + interact(usr) + if(href_list["mode"]) + var/mod = input("Set explosion mode", "Explosion mode") as null|anything in possible_explosions + if(mod) + elevel = mod + interact(usr) + if(href_list["msg"]) + var/msg = input("Set tampering message, or leave blank for no broadcasting.", "Anti-tampering", warning_message) as text|null + if(msg) + warning_message = msg + interact(usr) + if(href_list["phrase"]) + var/talk = input("Set activation phrase", "Audio activation", phrase) as text|null + if(talk) + phrase = sanitizePhrase(talk) + interact(usr) + +/obj/item/implant/explosive/receive_signal(datum/signal/signal) + if(signal && signal.encryption == code) + activate() + +/obj/item/implant/explosive/proc/setFrequency(new_frequency) + if(!frequency) + return + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT) + +/obj/item/implant/explosive/hear_talk(mob/M, msg) + hear(msg) + +/obj/item/implant/explosive/hear(var/msg) + if(!phrase) + return + if(findtext(sanitizePhrase(msg),phrase)) + activate() + qdel(src) + +/obj/item/implant/explosive/exposed() + if(warning_message) + global_announcer.autosay(warning_message, "Anti-Tampering System") + +/obj/item/implant/explosive/proc/sanitizePhrase(phrase) + var/list/replacechars = list("'" = "", "\"" = "", ">" = "", "<" = "", "(" = "", ")" = "") + return replace_characters(phrase, replacechars) + +/obj/item/implant/explosive/activate() + if(malfunction) + return + + if(!imp_in) + small_countdown() + return + + message_admins("Explosive implant triggered in [imp_in] ([imp_in.key]). (JMP) ") + log_game("Explosive implant triggered in [imp_in] ([imp_in.key]).") + if(!elevel) + elevel = "Localized Limb" + switch(elevel) + if("Localized Limb") + if(part) + small_countdown() + return + if("Destroy Body") + explosion(get_turf(imp_in), -1, 0, 2, 6) + if(ismob(imp_in)) + imp_in.gib() + if("Full Explosion") + explosion_spread(get_turf(imp_in), rand(8,13)) + if(ismob(imp_in)) + imp_in.gib() + + var/turf/F = get_turf(imp_in) + if(F) + F.hotspot_expose(3500,125) + qdel(src) + +/obj/item/implant/explosive/proc/small_countdown() + if(!imp_in) + audible_message(SPAN_WARNING("[src] beeps ominously!")) + if(ishuman(imp_in)) + var/message = "Something beeps inside of [imp_in][part ? "'s [part.name]" : ""]..." //for some reason SPAN_X and span() both hate having this in-line + imp_in.audible_message(SPAN_WARNING(message)) + else if(ismob(imp_in)) + imp_in.audible_message(SPAN_WARNING("Something beeps inside of [imp_in]...")) + playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) + addtimer(CALLBACK(src, PROC_REF(small_boom)), 25) + +/obj/item/implant/explosive/proc/small_boom() + if(!imp_in) + explosion(get_turf(src), -1, 0, 2, 4) + if(ishuman(imp_in) && part) + //No tearing off these parts since it's pretty much killing. Mangle them. + if(part.vital && !istype(part, /obj/item/organ/external/head)) //Head explodes + part.createwound(BRUISE, 70) + part.add_pain(50) + imp_in.visible_message(SPAN_WARNING("\The [imp_in]'s [part.name] bursts open with a horrible ripping noise!"), + SPAN_DANGER("Your [part.name] bursts open with a horrible ripping noise!"), + SPAN_WARNING("You hear a horrible ripping noise.")) + else + part.droplimb(0,DROPLIMB_BLUNT) + playsound(get_turf(imp_in), BP_IS_ROBOTIC(part) ? 'sound/effects/meteorimpact.ogg' : 'sound/effects/splat.ogg') + else if(ismob(imp_in)) + var/mob/M = imp_in + M.gib() //Simple mobs just get got + qdel(src) + +/proc/explosion_spread(turf/epicenter, power, adminlog = 1, z_transfer = UP|DOWN) + var/datum/explosiondata/data = new + data.epicenter = epicenter + data.rec_pow = power + data.spreading = TRUE + data.adminlog = adminlog + data.z_transfer = z_transfer + SSexplosives.queue(data) + +/obj/item/implant/explosive/implanted(mob/source, mob/user) + var/memo = "\The [src] in [source] can be activated by saying something containing the phrase ''[phrase]'', say [phrase] to attempt to activate. It can also be triggered with a radio signal on frequency [format_frequency(src.frequency)] with code [code]." + if(user.mind) + user.mind.store_memory(memo, 0, 0) + to_chat(usr, memo) + return TRUE + +/obj/item/implant/explosive/emp_act(severity) + if(malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + switch (severity) + if(2.0) //Weak EMP will make implant tear limbs off. + if(prob(50)) + small_countdown() + if(1.0) //strong EMP will melt implant either making it go off, or disarming it + if(prob(70)) + if(prob(50)) + small_countdown() + else + if(prob(50)) + activate() //50% chance of bye bye + else + meltdown() //50% chance of implant disarming + addtimer(CALLBACK(src, PROC_REF(self_correct)), 20) + +/obj/item/implant/explosive/proc/self_correct() + malfunction-- + +/obj/item/implant/explosive/isLegal() + return FALSE + +/obj/item/implant/explosive/New() + ..() + become_hearing_sensitive(ROUNDSTART_TRAIT) + +/obj/item/implant/explosive/Destroy() + return ..() + +/obj/item/implant/explosive/full + possible_explosions = list("Localized Limb", "Destroy Body", "Full Explosion") + +/obj/item/implant/explosive/deadman + name = "deadman explosive" + desc = "A military grade micro bio-explosive that detonates upon death." + icon_state = "implant_evil" + +/obj/item/implant/explosive/deadman/get_data() + . = {" +Implant Specifications:
+Name: Kumar Arms ZX-01a \"Obscuration\" Class Implant
+Life: Activates upon death.
+Important Notes: Explodes
+
+Implant Details:
+Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
+Special Features: Explodes
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + +/obj/item/implant/explosive/deadman/attack_self(mob/user) + return + +/obj/item/implant/explosive/deadman/hear(var/msg) + return + +/obj/item/implant/explosive/deadman/process() + if(malfunction) + STOP_PROCESSING(SSprocessing, src) + return + if (!implanted) + return + var/mob/M = imp_in + + if(M.stat == DEAD) + activate() + +/obj/item/implant/explosive/deadman/activate(var/cause) + small_countdown(src) + STOP_PROCESSING(SSprocessing, src) + +/obj/item/implant/explosive/deadman/small_boom() + if(imp_in) + explosion(get_turf(src), -1, 0, 1, 6) + imp_in.gib() + qdel(src) + +/obj/item/implant/explosive/deadman/implanted(mob/source) + START_PROCESSING(SSprocessing, src) + return TRUE + +/obj/item/implant/explosive/deadman/emp_act(severity) + if(malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + switch (severity) + if(3.0) + if(prob(1)) + small_countdown() + else if(prob(5)) + meltdown() + if(2.0) + if(prob(5)) + small_countdown() + else if (prob(10)) + meltdown() + if(1.0) + if(prob(10)) + small_countdown() + else if (prob(30)) + meltdown() + +#undef MALFUNCTION_TEMPORARY +#undef MALFUNCTION_PERMANENT + +/obj/item/implantcase/explosive + name = "implant case - 'explosive'" + imp = /obj/item/implant/explosive + +/obj/item/implantcase/explosive/deadman + name = "glass case - 'deadman'" + imp = /obj/item/implant/explosive/deadman + +/obj/item/implanter/explosive + name = "implanter (E)" + imp = /obj/item/implant/explosive + +/obj/item/implanter/explosive/deadman + name = "implanter (D)" + imp = /obj/item/implant/explosive/deadman diff --git a/code/game/objects/items/weapons/implants/implants/freedom.dm b/code/game/objects/items/weapons/implants/implants/freedom.dm new file mode 100644 index 00000000000..7fd50279779 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/freedom.dm @@ -0,0 +1,77 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/implant/freedom + name = "freedom implant" + desc = "Use this to escape from those evil Red Shirts." + icon_state = "implant_freedom" + implant_icon = "freedom" + implant_color = "#88f2e0" + origin_tech = list(TECH_MATERIAL = 1, TECH_ILLEGAL = 2, TECH_BIO = 3) + default_action_type = /datum/action/item_action/hands_free/activate/implant/freedom + action_button_name = "Activate Freedom Implant" + hidden = TRUE + var/uses = 1 + +/obj/item/implant/freedom/New() + uses = rand(1, 5) + ..() + +/obj/item/implant/freedom/activate(cause) + if(malfunction || !imp_in) + return + if(uses < 1) + to_chat(imp_in, SPAN_WARNING("\The [src] gives a faint beep inside your [part], indicating that it's out of uses!")) + return + uses-- + to_chat(imp_in, SPAN_HEAR("You feel a faint click.")) + if(iscarbon(imp_in)) + var/mob/living/carbon/C_imp_in = imp_in + if(C_imp_in.handcuffed) + var/obj/item/W = C_imp_in.handcuffed + C_imp_in.handcuffed = null + if(C_imp_in.buckled_to && C_imp_in.buckled_to.buckle_require_restraints) + C_imp_in.buckled_to.unbuckle() + C_imp_in.update_inv_handcuffed() + if(C_imp_in.client) + C_imp_in.client.screen -= W + if(W) + W.forceMove(C_imp_in.loc) + dropped(C_imp_in) + if (W) + W.layer = initial(W.layer) + if(C_imp_in.legcuffed) + var/obj/item/W = C_imp_in.legcuffed + C_imp_in.legcuffed = null + C_imp_in.update_inv_legcuffed() + if(C_imp_in.client) + C_imp_in.client.screen -= W + if(W) + W.forceMove(C_imp_in.loc) + dropped(C_imp_in) + if(W) + W.layer = initial(W.layer) + +/obj/item/implant/freedom/get_data() + var/dat = {" +Implant Specifications:
+Name: Freedom Beacon
+Life: optimum 5 uses
+Important Notes: Illegal
+
+Implant Details:
+Function: Transmits a specialized cluster of signals to override handcuff locking +mechanisms
+Special Features:
+Neuro-Scan- Analyzes certain shadow signals in the nervous system
+Integrity: The battery is extremely weak and commonly after injection its +life can drive down to only 1 use.
+No Implant Specifics"} + return dat + +/obj/item/implantcase/freedom + name = "glass case - 'freedom'" + imp = /obj/item/implant/freedom + +/obj/item/implanter/freedom + name = "implanter (F)" + imp = /obj/item/implant/freedom diff --git a/code/game/objects/items/weapons/implants/implants/health_tracker.dm b/code/game/objects/items/weapons/implants/implants/health_tracker.dm new file mode 100644 index 00000000000..53cfb6ea8fc --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/health_tracker.dm @@ -0,0 +1,22 @@ +//Health Tracker Implant +/obj/item/implant/health + name = "health implant" + icon_state = "implant_health" + implant_icon = "deathalarm" //This is intentionally the same as the death alarm + implant_color = "#9cdb43" //This is intentionally the same as the death alarm + var/healthstring = "" + +/obj/item/implant/health/proc/sensehealth() + if(!implanted) + return "ERROR" + else + if(isliving(implanted)) + var/mob/living/L = implanted + healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]" + if(!healthstring) + healthstring = "ERROR" + return healthstring + +/obj/item/implantcase/health + name = "glass case - 'health'" + imp = /obj/item/implant/health diff --git a/code/game/objects/items/weapons/implants/implants/loyalty.dm b/code/game/objects/items/weapons/implants/implants/loyalty.dm new file mode 100644 index 00000000000..2052c6e2f98 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/loyalty.dm @@ -0,0 +1,104 @@ +/obj/item/implant/mindshield/loyalty + name = "loyalty implant" + desc = "A controversial device, these were replaced with mindshield implants by the corporations of the spur. However, they still find usage with several entities across the spur." + ///The entity that the implantee should be loyal to + var/loyal_entity + ///Whether this implant will override mindshield implants. These are supposed to be older versions of mindshields, so only specially modified versions should do so. + var/mindshield_override = FALSE + +/obj/item/implant/mindshield/loyalty/get_data() + . = {" +Implant Specifications:
+Name: Solarian Corporate Authority NT-02 Employee Management Implant Mk.I
+Life: Ten years.
+Important Notes: Personnel injected with this device tend to be much more loyal to the entity provided.
+
+Implant Details:
+Function: Contains a small pod of nanobots that manipulate the host's mental functions, to ensure no harmful thoughts are present against an entity.
+Special Features: Will prevent and cure most forms of brainwashing.
+Integrity: Implant will last so long as the nanobots are inside the bloodstream." +Loyal entity:
+This is the entity that the implantee will align their thoughts to benefit.
+[loyal_entity ? loyal_entity : "NONE SET"] +"} + +/obj/item/implant/mindshield/loyalty/Topic(href, href_list) + ..() + if(href_list["loyal"]) + var/entity = input("Set loyalty target.", "Loyalty", loyal_entity) as text|null + if(entity) + loyal_entity = entity + interact(usr) + +/obj/item/implant/mindshield/loyalty/implanted(mob/M) + if(!istype(M, /mob/living/carbon/human)) + return FALSE + + var/mob/living/carbon/human/H = M + + for(var/obj/item/implant/mindshield/I in H) + if(I.implanted && !mindshield_override) + to_chat(H, SPAN_DANGER("You almost feel your loyalties shifting, but nanobots from your mindshield implant stop it soon after it starts!")) + meltdown() + return FALSE + else if(I.implanted && mindshield_override) + to_chat(H, SPAN_DANGER("You hear a buzzing sound as your mindshield implant struggles to defend against the new implant.")) + I.meltdown() + + to_chat(H, SPAN_GOOD("You feel a sudden surge of loyalty to \the [loyal_entity]!")) + log_and_message_admins("[key_name(H)] was implanted by an loyalty implant, set to [loyal_entity]!", H) + return TRUE + +/obj/item/implant/mindshield/loyalty/sol + name = "loyalty implant - Sol Alliance" + desc = "A device used by the Sol Alliance, to ensure loyalty to the only human government in the spur." + loyal_entity = "\improper Sol Alliance" + +/obj/item/implant/mindshield/loyalty/nralakk + name = "loyalty implant - Nralakk Federation" + desc = "A device used by the Nralakk Federation, to ensure loyalty to its ideals and to the best caretaker of the skrellian people." + loyal_entity = "\improper Nralakk Federation" + +/obj/item/implant/mindshield/loyalty/scc + name = "loyalty implant - Stellar Corporate Conglomerate" + desc = "A device that is allegedly used by the Stellar Corporate Conglomerate, which is allegedly used to enforce loyalty to the corporate agenda for its emergency response teams and high-ranking officers." + loyal_entity = "\improper Stellar Corporate Conglomerate" + +/obj/item/implant/mindshield/loyalty/nt + name = "loyalty implant - NanoTrasen" + desc = "A device that is allegedly used by NanoTrasen, which is allegedly used to enforce loyalty to the corporate agenda for its emergency response teams and high-ranking officers." + loyal_entity = "NanoTrasen" + //They made them originally, they would know how to override them. + mindshield_override = TRUE + +/obj/item/implantcase/loyalty + name = "glass case - 'loyalty'" + imp = /obj/item/implant/mindshield/loyalty + +/obj/item/implanter/loyalty + name = "implanter-loyalty" + imp = /obj/item/implant/mindshield/loyalty + +/obj/item/implantcase/loyalty/sol + name = "glass case - 'loyalty - Sol Alliance'" + imp = /obj/item/implant/mindshield/loyalty/sol + +/obj/item/implanter/loyalty/sol + name = "implanter-loyalty - Sol Alliance" + imp = /obj/item/implant/mindshield/loyalty/sol + +/obj/item/implantcase/loyalty/nralakk + name = "glass case - 'loyalty - Nralakk Federation'" + imp = /obj/item/implant/mindshield/loyalty/nralakk + +/obj/item/implanter/loyalty/nralakk + name = "implanter-loyalty - Nralakk Federation" + imp = /obj/item/implant/mindshield/loyalty/nralakk + +/obj/item/implantcase/loyalty/scc + name = "glass case - 'loyalty - Stellar Corporate Conglomerate'" + imp = /obj/item/implant/mindshield/loyalty/scc + +/obj/item/implanter/loyalty/scc + name = "implanter-loyalty - Stellar Corporate Conglomerate" + imp = /obj/item/implant/mindshield/loyalty/scc diff --git a/code/game/objects/items/weapons/implants/implants/mindshield.dm b/code/game/objects/items/weapons/implants/implants/mindshield.dm new file mode 100644 index 00000000000..e394ed9ee8e --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/mindshield.dm @@ -0,0 +1,75 @@ +#define MALFUNCTION_TEMPORARY 1 +#define MALFUNCTION_PERMANENT 2 + +/obj/item/implant/mindshield + name = "mind shield implant" + desc = "A neurostimulator and autohypnosis device. These replaced older, controversial loyalty implants for the corporations of the spur. When implanted against the amygdala, it ensures the host maintains a consistent personality, preventing outside interference through brainwashing or hypnotic suggestion." + icon_state = "implant_excel" + implant_icon = "excel" + implant_color = "#ffd079" + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_ILLEGAL = 3) + default_action_type = null + known = TRUE + +/obj/item/implant/mindshield/get_data() + . = {" +Implant Specifications:
+Name: NanoTrasen NT-02 Employee Management Implant Mk.II
+Life: Ten years.
+Important Notes: Personnel injected with this device tend to be much more resistant to brain washing and other external influences.
+
+Implant Details:
+Function: Contains a small pod of nanobots that observe the host's mental functions, and will destroy and interfere with common techniques of intrusion.
+Special Features: Will prevent and cure most forms of brainwashing.
+Integrity: Implant will last so long as the nanobots are inside the bloodstream."} + +/obj/item/implant/mindshield/implanted(mob/M) + to_chat(M, SPAN_SUBTLE("You feel a weird feeling, as the implant's nanobots disperse through your brain.")) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + for(var/obj/item/implant/mindshield/loyalty/I in H) + if(I.implanted && !I.mindshield_override) + to_chat(H, SPAN_DANGER("The new mindshield implant activates, destroying your loyalty implant.")) + I.meltdown() + continue + else if(I.implanted && I.mindshield_override) + to_chat(H, SPAN_DANGER("You hear a buzzing sound as your loyalty implant defends itself against the new implant.")) + meltdown() + return FALSE + return TRUE + +/obj/item/implant/mindshield/emp_act(severity) + if (malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + + activate("emp") + if(severity == 1) + if(prob(50)) + meltdown() + else if (prob(50)) + malfunction = MALFUNCTION_PERMANENT + return + spawn(20) + malfunction-- + +/obj/item/implant/mindshield/ipc + name = "software protection chip" + desc = "A dedicated processor core designed to identify and terminate malignant software, ensuring a synthetics protection from outside hacking." + +/obj/item/implant/mindshield/ipc/implanted(mob/M) + if (!isipc(M)) + return + + ..() + +#undef MALFUNCTION_TEMPORARY +#undef MALFUNCTION_PERMANENT + +/obj/item/implantcase/mindshield + name = "glass case - 'mind shield'" + imp = /obj/item/implant/mindshield + +/obj/item/implanter/mindshield + name = "implanter-mindshield" + imp = /obj/item/implant/mindshield diff --git a/code/game/objects/items/weapons/implants/implants/tracking.dm b/code/game/objects/items/weapons/implants/implants/tracking.dm new file mode 100644 index 00000000000..fe6657a01bd --- /dev/null +++ b/code/game/objects/items/weapons/implants/implants/tracking.dm @@ -0,0 +1,70 @@ +#define MALFUNCTION_TEMPORARY 1 + +/obj/item/implant/tracking + name = "tracking implant" + desc = "Track with this." + icon_state = "implant_freedom" + implant_icon = "freedom" + implant_color = "#eadb83" + origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_BLUESPACE = 2) + default_action_type = null + known = TRUE + var/id = 1.0 + var/lifespan_postmortem = 10 MINUTES + +/obj/item/implant/tracking/Initialize() + var/list/tracking_list = list() + for(var/obj/item/implant/tracking/T in implants) + tracking_list += T + id = length(tracking_list) + 1 + . = ..() + +/obj/item/implant/tracking/process() + if(!imp_in) + return + if(iscarbon(imp_in)) + var/mob/living/carbon/R = imp_in + if(R.chem_effects[CE_NEUROTOXIC]) + if(prob(5)) + meltdown() + +/obj/item/implant/tracking/get_data() + . = {"Implant Specifications:
+Name: Ingkom ZV-01 Tracking Beacon
+Life: 10 minutes after death of host
+Important Notes: None
+
+Implant Details:
+Function: Continuously transmits a low power signal. Useful for tracking subjects.
+Special Features:
+Neuro-Safe- Specialized shell absorbs excess voltages self-destructing the chip if +a malfunction occurs thereby securing safety of subject. The implant will melt and +disintegrate into bio-safe elements.
+Integrity: Gradient creates slight risk of being overcharged and frying the +circuitry. As a result neurotoxins can cause massive damage.
+Implant Specifics:
"} + +/obj/item/implant/tracking/isLegal() + return TRUE + +/obj/item/implant/tracking/emp_act(severity) + if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning + return + malfunction = MALFUNCTION_TEMPORARY + + var/delay = 20 + switch(severity) + if(1) + if(prob(60)) + meltdown() + if(2) + delay = rand(5*60*10,15*60*10) //from 5 to 15 minutes of free time + + spawn(delay) + malfunction-- + +#undef MALFUNCTION_TEMPORARY + +/obj/item/implantcase/tracking + name = "glass case - 'tracking'" + imp = /obj/item/implant/tracking diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implants/uplink.dm similarity index 86% rename from code/game/objects/items/weapons/implants/implantuplink.dm rename to code/game/objects/items/weapons/implants/implants/uplink.dm index f22f5a62df5..a2ac8925f2a 100644 --- a/code/game/objects/items/weapons/implants/implantuplink.dm +++ b/code/game/objects/items/weapons/implants/implants/uplink.dm @@ -1,7 +1,12 @@ /obj/item/implant/uplink name = "uplink" desc = "Summon things." + icon_state = "implant_uplink" + implant_icon = "uplink" + implant_color = "#ffd4a3" var/activation_emote = "chuckle" + default_action_type = null + hidden = TRUE /obj/item/implant/uplink/New() activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") @@ -23,3 +28,7 @@ if(hidden_uplink && usr == source) // Let's not have another people activate our uplink hidden_uplink.check_trigger(source, emote, activation_emote) return + +/obj/item/implanter/uplink + name = "implanter (U)" + imp = /obj/item/implant/uplink diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index a99c6f56e48..c5ca35588eb 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -530,7 +530,7 @@ name = "death alarm kit" desc = "Box of stuff used to implant death alarms." illustration = "implant" - starts_with = list(/obj/item/implanter = 1, /obj/item/implantcase/death_alarm = 6) + starts_with = list(/obj/item/implanter = 1, /obj/item/implantcase/death_alarm = 6, /obj/item/implantpad = 1) /obj/item/storage/box/condimentbottles name = "box of condiment bottles" @@ -1221,3 +1221,4 @@ /obj/item/storage/box/produce/fill() . = ..() make_exact_fit() + diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 1ceed545796..6addf763f9b 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -79,8 +79,8 @@ name = "lockbox of mind shield implants" req_access = list(access_security) starts_with = list( - /obj/item/implantcase/loyalty = 3, - /obj/item/implanter/loyalty = 1 + /obj/item/implantcase/mindshield = 3, + /obj/item/implanter/mindshield = 1 ) /obj/item/storage/lockbox/anti_augment diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 629b49efbe6..40f5be5b039 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -6,26 +6,23 @@ /obj/item/storage/box/syndie_kit/imp_freedom name = "box (F)" - starts_with = list(/obj/item/implanter/freedom = 1) - -/obj/item/storage/box/syndie_kit/imp_freedom/fill() - ..() - var/obj/item/implanter/O = new(src) - O.imp = new /obj/item/implant/freedom(O) - O.update() - return + starts_with = list(/obj/item/implantpad = 1, /obj/item/implanter = 1, /obj/item/implantcase/freedom = 1) /obj/item/storage/box/syndie_kit/imp_compress name = "box (C)" - starts_with = list(/obj/item/implanter/compressed = 1) + starts_with = list(/obj/item/implantpad = 1, /obj/item/implanter/compressed = 1) /obj/item/storage/box/syndie_kit/imp_explosive name = "box (E)" - starts_with = list(/obj/item/implanter = 1, /obj/item/implant/explosive = 1) + starts_with = list(/obj/item/implantpad = 1, /obj/item/implanter = 1, /obj/item/implantcase/explosive = 1) + +/obj/item/storage/box/syndie_kit/imp_emp + name = "box (M)" + starts_with = list(/obj/item/implantpad = 1, /obj/item/implanter = 1, /obj/item/implantcase/emp = 1) /obj/item/storage/box/syndie_kit/imp_deadman name = "box (D)" - starts_with = list(/obj/item/implanter = 1, /obj/item/implant/explosive/deadman = 1) + starts_with = list(/obj/item/implantpad = 1, /obj/item/implanter = 1, /obj/item/implantcase/explosive/deadman = 1) /obj/item/storage/box/syndie_kit/imp_uplink diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 2923b8a5bae..56513894de9 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -99,8 +99,8 @@ Frequency: continue else var/mob/M = W.loc - if (M.stat == 2) - if (M.timeofdeath + 6000 < world.time) + if (M.stat == DEAD) + if (M.timeofdeath + W.lifespan_postmortem < world.time) continue var/turf/tr = get_turf(W) diff --git a/code/modules/awaymissions/exile.dm b/code/modules/awaymissions/exile.dm index fadbc540c23..7db07f94a00 100644 --- a/code/modules/awaymissions/exile.dm +++ b/code/modules/awaymissions/exile.dm @@ -7,7 +7,7 @@ /obj/item/implanter/exile/New() src.imp = new /obj/item/implant/exile( src ) ..() - update() + update_icon() return diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index c12e806be3a..451d39ff0ce 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -23,7 +23,7 @@ All custom items with worn sprites must follow the contained sprite system: http if (!implant_type) return imp = new implant_type(src) - update() + update_icon() return diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 9a616a821a9..e30dbd62985 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1347,8 +1347,8 @@ hud_list[WANTED_HUD] = holder if ( BITTEST(hud_updateflag, IMPLOYAL_HUD) \ - || BITTEST(hud_updateflag, IMPCHEM_HUD) \ - || BITTEST(hud_updateflag, IMPTRACK_HUD)) + || BITTEST(hud_updateflag, IMPCHEM_HUD) \ + || BITTEST(hud_updateflag, IMPTRACK_HUD)) var/image/holder1 = hud_list[IMPTRACK_HUD] var/image/holder2 = hud_list[IMPLOYAL_HUD] @@ -1361,7 +1361,7 @@ if(I.implanted) if(istype(I,/obj/item/implant/tracking)) holder1.icon_state = "hud_imp_tracking" - if(istype(I,/obj/item/implant/mindshield)) + if(istype(I,/obj/item/implant/mindshield) && !istype(I,/obj/item/implant/mindshield/loyalty)) holder2.icon_state = "hud_imp_loyal" if(istype(I,/obj/item/implant/chem)) holder3.icon_state = "hud_imp_chem" diff --git a/code/modules/modular_computers/file_system/programs/command/teleporter.dm b/code/modules/modular_computers/file_system/programs/command/teleporter.dm index 5260a61da3e..6f230b8a181 100644 --- a/code/modules/modular_computers/file_system/programs/command/teleporter.dm +++ b/code/modules/modular_computers/file_system/programs/command/teleporter.dm @@ -83,7 +83,7 @@ else var/mob/M = I.loc if(M.stat == DEAD) - if(M.timeofdeath + 6000 < world.time) + if(M.timeofdeath + I.lifespan_postmortem < world.time) continue var/turf/IT = get_turf(M) if(!IT) diff --git a/code/modules/research/designs/protolathe/implant_designs.dm b/code/modules/research/designs/protolathe/implant_designs.dm index 7aba0b48bbc..be6c0b9c2ac 100644 --- a/code/modules/research/designs/protolathe/implant_designs.dm +++ b/code/modules/research/designs/protolathe/implant_designs.dm @@ -2,12 +2,22 @@ materials = list(DEFAULT_WALL_MATERIAL = 50, MATERIAL_GLASS = 50) p_category = "Implantable Biocircuit Designs" +/datum/design/item/implant/adrenaline + name = "Adrenaline" + req_tech = list(TECH_MATERIAL = 1, TECH_ILLEGAL = 2, TECH_BIO = 3) + build_path = /obj/item/implantcase/adrenaline + /datum/design/item/implant/chemical name = "Chemical" req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) build_path = /obj/item/implantcase/chem +/datum/design/item/implant/death_alarm + name = "Death Alarm" + req_tech = list(TECH_MATERIAL = 1, TECH_BIO = 3, TECH_DATA = 2) + build_path = /obj/item/implantcase/death_alarm + /datum/design/item/implant/freedom name = "Freedom" - req_tech = list(TECH_ILLEGAL = 2, TECH_BIO = 3) - build_path = /obj/item/implantcase/freedom \ No newline at end of file + req_tech = list(TECH_MATERIAL = 1, TECH_ILLEGAL = 2, TECH_BIO = 3) + build_path = /obj/item/implantcase/freedom diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index ff2089cb6f6..7c5821b0abc 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -103,6 +103,9 @@ affected.open = ORGAN_ENCASED_RETRACTED + for(var/obj/item/implant/I in affected.implants) + I.exposed() + /singleton/surgery_step/open_encased/retract/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!ishuman(target)) return diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 1226e58e6c1..dd4b2d09025 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -183,7 +183,7 @@ /singleton/surgery_step/generic/cut_open_vaurca/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] has drilled into [target]'s [affected.name] carapace with \the [tool].", \ - SPAN_NOTICE("You have drilled into [target]'s [affected.name] carapace with \the [tool]."),) + SPAN_NOTICE("You have drilled into [target]'s [affected.name] carapace with \the [tool]."),) affected.open = ORGAN_OPEN_INCISION if(istype(target) && !(target.species.flags & NO_BLOOD)) @@ -281,6 +281,10 @@ user.visible_message(msg, self_msg) affected.open = ORGAN_OPEN_RETRACTED + if(!affected.encased) + for(var/obj/item/implant/I in affected.implants) + I.exposed() + /singleton/surgery_step/generic/retract_skin/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) var/msg = SPAN_WARNING("[user]'s hand slips, tearing the edges of the incision on [target]'s [affected.name] with \the [tool]!") diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index f71b7be2ae0..15089f651d9 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -192,7 +192,7 @@ if(istype(obj,/obj/item/implant)) var/obj/item/implant/imp = obj - if(imp.islegal()) + if(imp.isLegal()) find_prob += 60 else find_prob += 40 diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 9080664a316..13d3a80d191 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -85,6 +85,7 @@ h1.alert, h2.alert {color: #000000;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} +.hear {color: #000099; font-style: italic;} .subtle {color: #000099; font-size: 75%; font-style: italic;} .alium {color: #00ff00;} .cult {color: #800080; font-weight: bold; font-style: italic;} diff --git a/html/changelogs/GeneralCamo - Implant.yml b/html/changelogs/GeneralCamo - Implant.yml new file mode 100644 index 00000000000..fac947cf362 --- /dev/null +++ b/html/changelogs/GeneralCamo - Implant.yml @@ -0,0 +1,50 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: GeneralCamo + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - refactor: "Refactored implants to be easier to modify in the future." + - refactor: "Refactored the known implant system to use an implant's variable rather than a list in the body scanner, and allowed for implants completely hidden from all scanners." + - tweak: "Replaced the sprites for implanters, implant cases, implants, and implant pads. Sprites by Wowzewow (Wezzy)." + - tweak: "Implant pads are now used by placing the case onto them (or vice versa), and implanters now directly take implants from cases." + - rscadd: "Added the EMP implant, which will emit a burst of EMP when activated." + - rscdel: "Temporarily removed the compressed matter implant from the uplink, as it is difficult to use and needs new logic to fix up." + - rscadd: "Explosive implants now have an anti-tamper system that will warn if it is exposed in surgery, and can be triggered via radio signal as well as a custom phrase set in an implant pad." + - tweak: "Completely removed the emote triggering system from all implants, in favor of an action button-based system." + - rscadd: "Re-added loyalty implants, which still exist in the canon. These are currently unused, but variants exist for staff and event usage." + - bugfix: "Mindshield implants, when implanted, will no longer give the old loyalty implant messages. These are exclusive to loyalty implants." diff --git a/icons/obj/action_buttons/implants.dmi b/icons/obj/action_buttons/implants.dmi new file mode 100644 index 00000000000..a6aaeef180a Binary files /dev/null and b/icons/obj/action_buttons/implants.dmi differ diff --git a/icons/obj/item/implants.dmi b/icons/obj/item/implants.dmi new file mode 100644 index 00000000000..78d0abcbc5b Binary files /dev/null and b/icons/obj/item/implants.dmi differ diff --git a/icons/obj/item/reagent_containers/syringe.dmi b/icons/obj/item/reagent_containers/syringe.dmi index b30a98cb38a..df8d5e2ac96 100644 Binary files a/icons/obj/item/reagent_containers/syringe.dmi and b/icons/obj/item/reagent_containers/syringe.dmi differ