From edf92c57f9f2ee382c7edaad05ec1c22d3225446 Mon Sep 17 00:00:00 2001 From: Anewbe Date: Fri, 13 Jul 2018 23:13:47 -0500 Subject: [PATCH 1/3] Language and Larynx Additions --- code/__defines/mobs.dm | 3 + code/game/jobs/job_controller.dm | 3 +- .../objects/items/weapons/implants/implant.dm | 99 ++++++++++----- .../items/weapons/implants/implantchair.dm | 7 +- .../items/weapons/implants/implanter.dm | 13 +- .../items/weapons/implants/implantfreedom.dm | 10 +- .../items/weapons/implants/implantlanguage.dm | 50 +++++++- .../items/weapons/implants/implantuplink.dm | 8 +- .../loadout/loadout_utility.dm | 21 ++++ code/modules/mob/language/generic.dm | 2 +- code/modules/mob/language/language.dm | 10 +- code/modules/mob/language/station.dm | 35 +++--- code/modules/mob/living/carbon/human/emote.dm | 7 +- code/modules/mob/living/carbon/human/human.dm | 19 +-- .../carbon/human/species/outsider/event.dm | 1 + .../carbon/human/species/outsider/shadow.dm | 2 + .../carbon/human/species/outsider/vox.dm | 2 + .../living/carbon/human/species/species.dm | 7 +- .../carbon/human/species/station/golem.dm | 2 + .../human/species/station/human_subspecies.dm | 1 + .../human/species/station/prometheans.dm | 1 + .../carbon/human/species/station/seromi.dm | 1 + .../carbon/human/species/station/station.dm | 12 +- .../human/species/virtual_reality/avatar.dm | 116 ++++++++++++++++++ .../human/species/xenomorphs/alien_species.dm | 1 + code/modules/organs/internal/voicebox.dm | 42 +++++++ code/modules/organs/organ.dm | 4 + code/modules/organs/subtypes/standard.dm | 8 ++ html/changelogs/Anewbe - Languages.yml | 40 ++++++ icons/obj/surgery.dmi | Bin 28668 -> 29920 bytes vorestation.dme | 1 + 31 files changed, 426 insertions(+), 102 deletions(-) create mode 100644 code/modules/organs/internal/voicebox.dm create mode 100644 html/changelogs/Anewbe - Languages.yml diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 012677200c..c73ebf4d41 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -177,6 +177,9 @@ #define O_LIVER "liver" #define O_KIDNEYS "kidneys" #define O_APPENDIX "appendix" +#define O_VOICE "voicebox" + +// Non-Standard organs #define O_PLASMA "plasma vessel" #define O_HIVE "hive node" #define O_NUTRIENT "nutrient vessel" diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 5396c9bb29..278e516aae 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -391,7 +391,8 @@ var/global/datum/controller/occupations/job_master H.amend_exploitable(G.path) if(G.slot == "implant") - H.implant_loadout(G) + var/obj/item/weapon/implant/I = G.spawn_item(H) + I.implant_loadout(H) continue if(G.slot && !(G.slot in custom_equip_slots)) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 02e4cd48c4..f5bd38dcc1 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -21,12 +21,26 @@ /obj/item/weapon/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/weapon/implant/proc/implanted(var/mob/source) +// Moves the implant where it needs to go, and tells it if there's more to be done in post_implant +/obj/item/weapon/implant/proc/handle_implant(var/mob/source, var/target_zone = BP_TORSO) + . = TRUE + imp_in = source + implanted = TRUE + if(ishuman(source)) + var/mob/living/carbon/human/H = source + var/obj/item/organ/external/affected = H.get_organ(target_zone) + if(affected) + affected.implants += src + part = affected + if(part) + forceMove(part) + else + forceMove(source) + listening_objects |= src - return 1 + +// Takes place after handle_implant, if that returns TRUE +/obj/item/weapon/implant/proc/post_implant(var/mob/source) /obj/item/weapon/implant/proc/get_data() return "No information available" @@ -49,6 +63,12 @@ icon_state = "implant_melted" malfunction = MALFUNCTION_PERMANENT +/obj/item/weapon/implant/proc/implant_loadout(var/mob/living/carbon/human/H) + if(H) + var/obj/item/organ/external/affected = H.organs_by_name[BP_HEAD] + if(handle_implant(H, affected)) + post_implant(H) + /obj/item/weapon/implant/Destroy() if(part) part.implants.Remove(src) @@ -69,6 +89,11 @@ else ..() + + +////////////////////////////// +// Tracking Implant +////////////////////////////// GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking) /obj/item/weapon/implant/tracking @@ -84,9 +109,8 @@ GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking id = rand(1, 1000) ..() -/obj/item/weapon/implant/tracking/implanted(var/mob/source) +/obj/item/weapon/implant/tracking/post_implant(var/mob/source) processing_objects.Add(src) - return 1 /obj/item/weapon/implant/tracking/Destroy() processing_objects.Remove(src) @@ -142,7 +166,9 @@ Implant Specifics:
"} spawn(delay) malfunction-- - +////////////////////////////// +// Death Explosive Implant +////////////////////////////// /obj/item/weapon/implant/dexplosive name = "explosive" desc = "And boom goes the weasel." @@ -177,7 +203,9 @@ Implant Specifics:
"} /obj/item/weapon/implant/dexplosive/islegal() return 0 -//BS12 Explosive +////////////////////////////// +// Explosive Implant +////////////////////////////// /obj/item/weapon/implant/explosive name = "explosive implant" desc = "A military grade micro bio-explosive. Highly dangerous." @@ -249,15 +277,13 @@ Implant Specifics:
"} if(t) t.hotspot_expose(3500,125) -/obj/item/weapon/implant/explosive/implanted(mob/source as mob) +/obj/item/weapon/implant/explosive/post_implant(mob/source as mob) elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion") phrase = input("Choose activation phrase:") as text var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") phrase = replace_characters(phrase, replacechars) usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0) usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate." - listening_objects |= src - return 1 /obj/item/weapon/implant/explosive/emp_act(severity) if (malfunction) @@ -311,6 +337,9 @@ Implant Specifics:
"} explosion(get_turf(imp_in), -1, -1, 1, 3) qdel(src) +////////////////////////////// +// Chemical Implant +////////////////////////////// GLOBAL_LIST_BOILERPLATE(all_chem_implants, /obj/item/weapon/implant/chem) /obj/item/weapon/implant/chem @@ -336,20 +365,17 @@ Can only be loaded while still in its original case.
the implant may become unstable and either pre-maturely inject the subject or simply break."} return dat - /obj/item/weapon/implant/chem/New() ..() var/datum/reagents/R = new/datum/reagents(50) reagents = R R.my_atom = src - /obj/item/weapon/implant/chem/trigger(emote, source as mob) if(emote == "deathgasp") src.activate(src.reagents.total_volume) return - /obj/item/weapon/implant/chem/activate(var/cause) if((!cause) || (!src.imp_in)) return 0 var/mob/living/carbon/R = src.imp_in @@ -384,6 +410,9 @@ the implant may become unstable and either pre-maturely inject the subject or si spawn(20) malfunction-- +////////////////////////////// +// Loyalty Implant +////////////////////////////// /obj/item/weapon/implant/loyalty name = "loyalty implant" desc = "Makes you loyal or such." @@ -401,20 +430,24 @@ the implant may become unstable and either pre-maturely inject the subject or si Integrity: Implant will last so long as the nanobots are inside the bloodstream."} return dat - -/obj/item/weapon/implant/loyalty/implanted(mob/M) - if(!istype(M, /mob/living/carbon/human)) return 0 +/obj/item/weapon/implant/loyalty/handle_implant(mob/M, target_zone = BP_TORSO) + . = ..(M, target_zone) + if(!istype(M, /mob/living/carbon/human)) + . = FALSE 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 corporate tendrils of [using_map.company_name] try to invade your mind!") - return 0 - else - clear_antag_roles(H.mind, 1) - H << "You feel a surge of loyalty towards [using_map.company_name]." - return 1 + . = FALSE +/obj/item/weapon/implant/loyalty/post_implant(mob/M) + var/mob/living/carbon/human/H = M + clear_antag_roles(H.mind, 1) + to_chat(H, "You feel a surge of loyalty towards [using_map.company_name].") +////////////////////////////// +// Adrenaline Implant +////////////////////////////// /obj/item/weapon/implant/adrenalin name = "adrenalin" desc = "Removes all stuns and knockdowns." @@ -445,14 +478,13 @@ the implant may become unstable and either pre-maturely inject the subject or si return - -/obj/item/weapon/implant/adrenalin/implanted(mob/source) +/obj/item/weapon/implant/adrenalin/post_implant(mob/source) source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) source << "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate." - listening_objects |= src - return 1 - +////////////////////////////// +// Death Alarm Implant +////////////////////////////// /obj/item/weapon/implant/death_alarm name = "death alarm implant" desc = "An alarm which monitors host vital signs and transmits a radio message upon death." @@ -529,11 +561,13 @@ the implant may become unstable and either pre-maturely inject the subject or si spawn(20) malfunction-- -/obj/item/weapon/implant/death_alarm/implanted(mob/source as mob) +/obj/item/weapon/implant/death_alarm/post_implant(mob/source as mob) mobname = source.real_name processing_objects.Add(src) - return 1 +////////////////////////////// +// Compressed Matter Implant +////////////////////////////// /obj/item/weapon/implant/compressed name = "compressed matter implant" desc = "Based on compressed matter technology, can store a single item." @@ -571,13 +605,12 @@ the implant may become unstable and either pre-maturely inject the subject or si scanned.loc = t qdel(src) -/obj/item/weapon/implant/compressed/implanted(mob/source as mob) +/obj/item/weapon/implant/compressed/post_implant(mob/source) 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) source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 + /obj/item/weapon/implant/compressed/islegal() return 0 diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 44b33721cf..c05d52442c 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -135,10 +135,9 @@ for (var/mob/O in viewers(M, null)) O.show_message("\The [M] has been implanted by \the [src].", 1) - if(imp.implanted(M)) - imp.loc = M - imp.imp_in = M - imp.implanted = 1 + if(imp.handle_implant(M, BP_TORSO)) + imp.post_implant(M) + implant_list -= imp break return diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index d99c5f5ff2..c1b0d5db8d 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -56,16 +56,11 @@ add_attack_logs(user,M,"Implanted with [imp.name] using [name]") - if(src.imp.implanted(M)) - src.imp.loc = M - src.imp.imp_in = M - src.imp.implanted = 1 - if (ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - affected.implants += src.imp - imp.part = affected + if(imp.handle_implant(M)) + imp.post_implant(M) + if(ishuman(M)) + var/mob/living/carbon/human/H = M BITSET(H.hud_updateflag, IMPLOYAL_HUD) BITSET(H.hud_updateflag, BACKUP_HUD) //VOREStation Add - Backup HUD updates diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm index 92021a46a2..fab692775d 100644 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ b/code/game/objects/items/weapons/implants/implantfreedom.dm @@ -16,7 +16,9 @@ /obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob) - if (src.uses < 1) return 0 + if (src.uses < 1) + return 0 + if (emote == src.activation_emote) src.uses-- source << "You feel a faint click." @@ -46,13 +48,9 @@ W.layer = initial(W.layer) return - -/obj/item/weapon/implant/freedom/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/freedom/post_implant(mob/source) source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 - /obj/item/weapon/implant/freedom/get_data() var/dat = {" diff --git a/code/game/objects/items/weapons/implants/implantlanguage.dm b/code/game/objects/items/weapons/implants/implantlanguage.dm index d813a8d388..7c6e33508b 100644 --- a/code/game/objects/items/weapons/implants/implantlanguage.dm +++ b/code/game/objects/items/weapons/implants/implantlanguage.dm @@ -4,7 +4,26 @@ /obj/item/weapon/implant/language name = "GalCom language implant" - desc = "An implant allowing someone to speak and hear the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them." + desc = "An implant allowing someone to speak the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with producing sounds, not understanding them." + var/list/languages = list(LANGUAGE_GALCOM) // List of languages that this assists with + +/obj/item/weapon/implant/language/post_implant(mob/M) // Amends the mob's voice organ, then deletes itself + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/internal/voicebox/V = locate() in H.internal_organs + if(V) + var/list/need_amend = list() // If they've already got all the languages they need, then they don't need this implant to do anything + for(var/L in languages) + if(L in V.will_assist_languages) + continue + else + need_amend |= L + if(LAZYLEN(need_amend)) + if(V.robotic < ORGAN_ASSISTED) + V.mechassist() + for(var/L in need_amend) + V.add_assistable_langs(L) + qdel_null(src) /obj/item/weapon/implant/language/get_data() var/dat = {" @@ -14,16 +33,19 @@ Important Notes: Affects hearing and speech.

Implant Details:
-Function: Allows a being otherwise incapable to both hear the frequencies Galactic Common is generally spoken at, as well as to produce the phonemes of the language.
+Function: Allows a being otherwise incapable of speaking Galactic Common to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."} return dat + +// EAL Implant /obj/item/weapon/implant/language/eal name = "EAL language implant" - desc = "An implant allowing an organic to both hear and speak Encoded Audio Language accurately. Only helps with hearing and producing sounds, not understanding them." + desc = "An implant allowing an organic to speak Encoded Audio Language passably. Only helps with producing sounds, not understanding them." + languages = list(LANGUAGE_EAL) -/obj/item/weapon/implant/language/get_data() +/obj/item/weapon/implant/language/eal/get_data() var/dat = {" Implant Specifications:
Name: Vey-Med L-2 Encoded Audio Language Implant
@@ -31,7 +53,25 @@ Important Notes: Affects hearing and speech.

Implant Details:
-Function: Allows an organic to accurately process and speak Encoded Audio Language.
+Function: Allows an organic to accurately speak Encoded Audio Language.
+Special Features: None.
+Integrity: Implant will function for expected life, barring physical damage."} + return dat + +/obj/item/weapon/implant/language/skrellian + name = "Skrellian language implant" + desc = "An implant allowing someone to speak the range of frequencies used in Skrellian, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them." + languages = list(LANGUAGE_SKRELLIAN) + +/obj/item/weapon/implant/language/skrellian/get_data() + var/dat = {" +Implant Specifications:
+Name: Vey-Med L-1 Galactic Common Implant
+Life: 5 years
+Important Notes: Affects hearing and speech.
+
+Implant Details:
+Function: Allows a being otherwise incapable of speaking Skrellian to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."} return dat \ No newline at end of file diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implantuplink.dm index 644ebf1bb7..82809cfe61 100644 --- a/code/game/objects/items/weapons/implants/implantuplink.dm +++ b/code/game/objects/items/weapons/implants/implantuplink.dm @@ -11,15 +11,13 @@ ..() return -/obj/item/weapon/implant/uplink/implanted(mob/source) +/obj/item/weapon/implant/uplink/post_implant(mob/source) + listening_objects |= 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") source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) source << "The implanted uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 - /obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob) if(hidden_uplink && usr == source) // Let's not have another people activate our uplink hidden_uplink.check_trigger(source, emote, activation_emote) - return + return \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 76178dada2..736cd0dc48 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -116,21 +116,42 @@ path = /obj/item/weapon/cell/device /datum/gear/utility/implant +<<<<<<< HEAD exploitable = 1 /* VOREStation Edit - Make languages great again /datum/gear/utility/implant/eal //This does nothing if you don't actually know EAL. display_name = "implant, language, EAL" path = /obj/item/weapon/implant/language/eal cost = 2 +======= +>>>>>>> 8f9e817... Language and Larynx Additions (#5402) slot = "implant" exploitable = 1*/ /datum/gear/utility/implant/tracking display_name = "implant, tracking" path = /obj/item/weapon/implant/tracking/weak +<<<<<<< HEAD cost = 0 //VOREStation Edit. Changed cost to 0 slot = "implant" exploitable = 1 +======= + cost = 10 + +/datum/gear/utility/implant/language + cost = 2 + exploitable = 0 + +/datum/gear/utility/implant/language/eal + display_name = "vocal synthesizer, EAL" + description = "A surgically implanted vocal synthesizer which allows the owner to speak EAL, if they know it." + path = /obj/item/weapon/implant/language/eal + +/datum/gear/utility/implant/language/skrellian + display_name = "vocal synthesizer, Skrellian" + description = "A surgically implanted vocal synthesizer which allows the owner to speak Common Skrellian, if they know it." + path = /obj/item/weapon/implant/language/skrellian +>>>>>>> 8f9e817... Language and Larynx Additions (#5402) /datum/gear/utility/pen display_name = "Fountain Pen" diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm index d602bf71bb..40fe94b7f5 100644 --- a/code/modules/mob/language/generic.dm +++ b/code/modules/mob/language/generic.dm @@ -133,6 +133,6 @@ key = "s" flags = SIGNLANG|NO_STUTTER|NONVERBAL -/datum/language/sign/can_speak_special(var/mob/speaker) +/datum/language/sign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands return (hands || !iscarbon(speaker)) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index c6089a8788..66e0e5e0f0 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -133,7 +133,15 @@ return speech_verb /datum/language/proc/can_speak_special(var/mob/speaker) - return 1 + . = TRUE + if(ishuman(speaker)) + var/mob/living/carbon/human/H = speaker + if(src.name in H.species.assisted_langs) + . = FALSE + var/obj/item/organ/internal/voicebox/vox = locate() in H.internal_organs // Only voiceboxes for now. Maybe someday it'll include other organs, but I'm not that clever + if(vox) + if(!vox.is_broken() && (src in vox.assists_languages)) + . = TRUE // Language handling. /mob/proc/add_language(var/language) diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 2c395bca76..c80f606ae6 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -63,6 +63,14 @@ "ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", "hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra") +/datum/language/tajaran/get_random_name(var/gender) + var/new_name = ..(gender,1) + if(prob(50)) + new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]" + else + new_name += " [..(gender,1)]" + return new_name + /datum/language/tajaranakhani name = LANGUAGE_AKHANI desc = "The language of the sea-faring Njarir'Akhan Tajaran. Borrowing some elements from Siik, the language is distinctly more structured." @@ -77,15 +85,6 @@ "kar","yar","kzar","rha","hrar","err","fer","rir","rar","yarr","arr","ii'r","jar","kur","ran","rii","ii", "nai","ou","kah","oa","ama","uuk","bel","chi","ayt","kay","kas","akor","tam","yir","enai") -/datum/language/tajaran/get_random_name(var/gender) - - var/new_name = ..(gender,1) - if(prob(50)) - new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]" - else - new_name += " [..(gender,1)]" - return new_name - /datum/language/tajsign name = LANGUAGE_ALAI desc = "A standardized Tajaran sign language that was developed in Zarraya and gradually adopted by other nations, incorporating \ @@ -95,6 +94,19 @@ key = "l" flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL +/datum/language/tajsign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format + var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this. + if(iscarbon(speaker)) + var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands + if(!hands) + return FALSE + if(ishuman(speaker)) + var/mob/living/carbon/human/H = speaker + if(H.species.get_bodytype(H) in allowed_species) + return TRUE + + return FALSE + /datum/language/skrell name = LANGUAGE_SKRELLIAN desc = "A set of warbles and hums, the language itself a complex mesh of both melodic and rhythmic components, exceptionally capable of conveying intent and emotion of the speaker." @@ -161,11 +173,6 @@ syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz","shh","shk") space_chance = 10 -/datum/language/machine/can_speak_special(var/mob/speaker) - var/obj/item/weapon/implant/language/eal/beep = locate() in speaker - return ((beep && beep.implanted) || speaker.isSynthetic() || isvoice(speaker)) - //thank you sweet zuhayr - /datum/language/machine/get_random_name() if(prob(70)) return "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]" diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index eb473989f2..676eedbdd9 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -14,9 +14,10 @@ var/muzzled = is_muzzled() //var/m_type = 1 - for (var/obj/item/weapon/implant/I in src) - if (I.implanted) - I.trigger(act, src) + for(var/obj/item/organ/O in src.organs) + for (var/obj/item/weapon/implant/I in O) + if (I.implanted) + I.trigger(act, src) if(src.stat == 2.0 && (act != "deathgasp")) return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 792011043a..edf1bdd6c6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -166,25 +166,12 @@ update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message) if(update) UpdateDamageIcon() -/mob/living/carbon/human/proc/implant_loadout(var/datum/gear/G = new/datum/gear/utility/implant) - var/obj/item/weapon/implant/I = new G.path(src) - I.imp_in = src - I.implanted = 1 - var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD] - affected.implants += I - I.part = affected - I.implanted(src) - /mob/living/carbon/human/proc/implant_loyalty(override = FALSE) // Won't override by default. if(!config.use_loyalty_implants && !override) return // Nuh-uh. var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src) - L.imp_in = src - L.implanted = 1 - var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD] - affected.implants += L - L.part = affected - L.implanted(src) + if(L.handle_implant(src, BP_HEAD)) + L.post_implant(src) /mob/living/carbon/human/proc/is_loyalty_implanted() for(var/L in src.contents) @@ -1139,6 +1126,8 @@ remove_language(species.language) if(species.default_language) remove_language(species.default_language) + for(var/datum/language/L in species.assisted_langs) + remove_language(L) // Clear out their species abilities. species.remove_inherent_verbs(src) holder_type = null diff --git a/code/modules/mob/living/carbon/human/species/outsider/event.dm b/code/modules/mob/living/carbon/human/species/outsider/event.dm index 3e75acae9c..477b14c0c4 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/event.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/event.dm @@ -70,6 +70,7 @@ Variables you may want to make use of are: num_alternate_languages = 3 species_language = LANGUAGE_GALCOM secondary_langs = list() + assisted_langs = list() name_language = null // Use the first-name last-name generator rather than a language scrambler min_age = 0 diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index 5d81bb4c9c..d0f40f693d 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -25,6 +25,8 @@ genders = list(NEUTER) + assisted_langs = list() + /datum/species/shadow/handle_death(var/mob/living/carbon/human/H) spawn(1) new /obj/effect/decal/cleanable/ash(H.loc) diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index 9fab4751cc..525a611882 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -7,6 +7,7 @@ language = LANGUAGE_GALCOM species_language = LANGUAGE_VOX num_alternate_languages = 1 + assisted_langs = list(LANGUAGE_ROOTGLOBAL) unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong) rarity_value = 4 blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \ @@ -71,6 +72,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart/vox, O_LUNGS = /obj/item/organ/internal/lungs/vox, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver/vox, O_KIDNEYS = /obj/item/organ/internal/kidneys/vox, O_BRAIN = /obj/item/organ/internal/brain/vox, diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index b1557f3a28..a1d1a93277 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -52,13 +52,17 @@ // Language/culture vars. var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers. var/language = LANGUAGE_GALCOM // Default racial language, if any. - var/species_language = LANGUAGE_GALCOM // Used on the Character Setup screen + var/list/species_language = list(LANGUAGE_GALCOM) // Used on the Character Setup screen var/list/secondary_langs = list() // The names of secondary languages that are available to this species. var/list/speech_sounds = list() // A list of sounds to potentially play when speaking. var/list/speech_chance = list() // The likelihood of a speech sound playing. var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator + // The languages the species can't speak without an assisted organ. + // This list is a guess at things that no one other than the parent species should be able to speak + var/list/assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) + //Soundy emotey things. var/scream_verb = "screams" var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace! @@ -183,6 +187,7 @@ var/list/has_organ = list( // which required-organ checks are conducted. O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index 9ec7a2b005..3b09166813 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -11,6 +11,8 @@ spawn_flags = SPECIES_IS_RESTRICTED siemens_coefficient = 0 + assisted_langs = list() + breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm index 180732b0aa..56b5c36035 100644 --- a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm @@ -45,6 +45,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 01af604992..b78d530707 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -30,6 +30,7 @@ var/datum/species/shapeshifter/promethean/prometheans health_hud_intensity = 2 num_alternate_languages = 3 species_language = LANGUAGE_SOL_COMMON + assisted_langs = list(LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) // Prometheans are weird, let's just assume they can use basically any language. breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index fe21426805..6cd1a757cd 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -104,6 +104,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 19376b10f9..788ac2bfeb 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -12,6 +12,7 @@ species_language = LANGUAGE_SOL_COMMON secondary_langs = list(LANGUAGE_SOL_COMMON, LANGUAGE_TERMINUS) name_language = null // Use the first-name last-name generator rather than a language scrambler + assisted_langs = list(LANGUAGE_EAL, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) min_age = 17 max_age = 130 @@ -217,6 +218,7 @@ has_organ = list( //No appendix. O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, @@ -243,6 +245,7 @@ secondary_langs = list(LANGUAGE_SKRELLIAN, LANGUAGE_SCHECHI) name_language = LANGUAGE_SKRELLIAN species_language = LANGUAGE_SKRELLIAN + assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) health_hud_intensity = 2 water_movement = -3 @@ -317,13 +320,14 @@ hud_type = /datum/hud_data/diona siemens_coefficient = 0.3 show_ssd = "completely quiescent" - num_alternate_languages = 2 - secondary_langs = list(LANGUAGE_ROOTGLOBAL) - name_language = LANGUAGE_ROOTLOCAL - species_language = LANGUAGE_ROOTLOCAL health_hud_intensity = 2.5 item_slowdown_mod = 0.25 + num_alternate_languages = 2 + name_language = LANGUAGE_ROOTLOCAL + species_language = LANGUAGE_ROOTLOCAL + secondary_langs = list(LANGUAGE_ROOTGLOBAL) + assisted_langs = list(LANGUAGE_VOX) // Diona are weird, let's just assume they can use basically any language. min_age = 1 max_age = 300 diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm index b027407cf1..c747b61911 100644 --- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD // ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. // ### Any and all of this is open to change for balance or whatever. // ### @@ -109,4 +110,119 @@ if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) var/obj/machinery/vr_sleeper/V = vr_holder.loc +======= +// ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. +// ### Any and all of this is open to change for balance or whatever. +// ### +// ### +// Species definition follows. +/datum/species/shapeshifter/promethean/avatar + + name = SPECIES_VR + name_plural = "Virtual Reality Avatars" + blurb = "A 3-dimensional representation of some sort of animate object used to display the presence and actions of some-one or -thing using a virtual reality program." + show_ssd = "eerily still" + death_message = "flickers briefly, their gear falling in a heap on the floor around their motionless body." + knockout_message = "has been knocked unconscious!" + + spawn_flags = SPECIES_IS_RESTRICTED + + speech_bubble_appearance = "cyber" + + assisted_langs = list() + + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') + female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') + male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' + female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' + + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, O_EYES = /obj/item/organ/internal/eyes) // Slime core. + heal_rate = 0 // Avatars don't naturally heal like prometheans, at least not for now + inherent_verbs = list( + /mob/living/carbon/human/proc/shapeshifter_select_shape, + /mob/living/carbon/human/proc/shapeshifter_select_colour, + /mob/living/carbon/human/proc/shapeshifter_select_hair, + /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, + /mob/living/carbon/human/proc/shapeshifter_select_gender, + /mob/living/carbon/human/proc/regenerate, + /mob/living/carbon/human/proc/shapeshifter_change_opacity, + /mob/living/carbon/human/proc/exit_vr + ) + + +/datum/species/shapeshifter/promethean/avatar/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/shapeshifter/promethean/avatar/handle_environment_special(var/mob/living/carbon/human/H) + return + +/mob/living/carbon/human/proc/shapeshifter_change_opacity() + + set name = "Toggle Opacity" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 10 + + if(src.icon_state == "promethean") + icon_state = lowertext(src.species.get_bodytype(src)) + shapeshifter_change_species("Virtual Reality [src.species.get_bodytype(src)]") + else + icon_state = "promethean" + shapeshifter_change_species(SPECIES_VR) + + +// enter_vr is called on the original mob, and puts the mind into the supplied vr mob +/mob/living/carbon/human/proc/enter_vr(var/mob/living/carbon/human/avatar) // Avatar is currently a human, because we have preexisting setup code for appearance manipulation, etc. + if(!istype(avatar)) + return + + // Link the two mobs for client transfer + avatar.vr_holder = src + src.teleop = avatar + src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR + + // Move the mind + avatar.Sleeping(1) + src.mind.transfer_to(avatar) + to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") + to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? + +// exit_vr is called on the vr mob, and puts the mind back into the original mob +/mob/living/carbon/human/proc/exit_vr() + set name = "Exit Virtual Reality" + set category = "Abilities" + + if(!vr_holder) + return + if(!mind) + return + + var/total_damage + // Tally human damage + if(ishuman(src)) + var/mob/living/carbon/human/H = src + total_damage = H.getBruteLoss() + H.getFireLoss() + H.getOxyLoss() + H.getToxLoss() + + // Move the mind back to the original mob +// vr_holder.Sleeping(1) + src.mind.transfer_to(vr_holder) + to_chat(vr_holder, "You black out for a moment, and wake to find yourself back in your own body.") + // Two-thirds damage is transferred as agony for /humans + // Getting hurt in VR doesn't damage the physical body, but you still got hurt. + if(ishuman(vr_holder) && total_damage) + var/mob/living/carbon/human/V = vr_holder + V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m. + to_chat(vr_holder, "Pain from your time in VR lingers.") // 250 damage leaves the user unconscious for several seconds in addition to paincrit + + // Maintain a link with the mob, but don't use teleop + vr_holder.vr_link = src + vr_holder.teleop = null + + if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) + var/obj/machinery/vr_sleeper/V = vr_holder.loc +>>>>>>> 8f9e817... Language and Larynx Additions (#5402) V.go_out() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index d851c40255..1d2ce59307 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -5,6 +5,7 @@ default_language = "Xenomorph" language = "Hivemind" + assisted_langs = list() unarmed_types = list(/datum/unarmed_attack/claws/strong/xeno, /datum/unarmed_attack/bite/strong/xeno) hud_type = /datum/hud_data/alien rarity_value = 3 diff --git a/code/modules/organs/internal/voicebox.dm b/code/modules/organs/internal/voicebox.dm new file mode 100644 index 0000000000..4de69fe8f2 --- /dev/null +++ b/code/modules/organs/internal/voicebox.dm @@ -0,0 +1,42 @@ +/* + * Voicebox/Vocal Synthesizers + * TL;DR: Assists with speaking languages that a species doesn't normally have, + * such as EAL. Not standard or organic, because at the moment it's undesireable to completely mute characters. + */ + +/obj/item/organ/internal/voicebox + name = "larynx" + icon_state = "larynx" + parent_organ = BP_TORSO // We don't have a neck area + organ_tag = O_VOICE + will_assist_languages = list(LANGUAGE_GALCOM) + +/obj/item/organ/internal/voicebox/New() + ..() + amend_assist_langs() + +/obj/item/organ/internal/voicebox/proc/amend_assist_langs() // Adds the list of language datums assisted by the voicebox to the list used in speaking + for(var/L in will_assist_languages) + assists_languages |= all_languages[L] + +/obj/item/organ/internal/voicebox/proc/add_assistable_langs(var/language) // Adds a new language (by string/define) to the list of things the voicebox can assist + will_assist_languages |= language + amend_assist_langs() // Can't think of a better place to put this, makes the voicebox actually start to assist with the added language + +///////////////////////////////// +// Voicebox Subtypes +///////////////////////////////// + +/obj/item/organ/internal/voicebox/assist // In the off chance we get a species that doesn't speak GalCom by default + +/obj/item/organ/internal/voicebox/assist/New() + ..() + mechassist() + +/obj/item/organ/internal/voicebox/robot + name = "vocal synthesizer" + will_assist_languages = list(LANGUAGE_GALCOM, LANGUAGE_EAL) // Synthetics spawn with this by default + +/obj/item/organ/internal/voicebox/robot/New() + ..() + robotize() diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index d649b951b0..f07a6b3192 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -31,6 +31,10 @@ var/list/organ_cache = list() var/rejecting // Is this organ already being rejected? var/preserved = 0 // If this is 1, prevents organ decay. + // Language vars. Putting them here in case we decide to do something crazy with sign-or-other-nonverbal languages. + var/list/will_assist_languages = list() + var/list/datum/language/assists_languages = list() + /obj/item/organ/Destroy() if(owner) owner = null diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 449d7c5137..b7de7765d1 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -23,10 +23,18 @@ organ_rel_size = 70 base_miss_chance = 10 +<<<<<<< HEAD /obj/item/organ/external/chest/robotize(var/company, var/skip_prosthetics = 0, var/keep_organs = 0) if(..() && robotic != ORGAN_NANOFORM) //VOREStation Edit // Give them a new cell. owner.internal_organs_by_name["cell"] = new /obj/item/organ/internal/cell(owner,1) +======= +/obj/item/organ/external/chest/robotize() + if(..()) + // Give them fancy new organs. + owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1) + owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1) +>>>>>>> 8f9e817... Language and Larynx Additions (#5402) /obj/item/organ/external/chest/handle_germ_effects() . = ..() //Should return an infection level diff --git a/html/changelogs/Anewbe - Languages.yml b/html/changelogs/Anewbe - Languages.yml new file mode 100644 index 0000000000..da9a2f7b42 --- /dev/null +++ b/html/changelogs/Anewbe - Languages.yml @@ -0,0 +1,40 @@ +################################ +# 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 +################################# + +# Your name. +author: Anewbe + +# 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: + - tweak: "Certain languages now require assistance for a species to speak, but not understand, much like EAL." + - tweak: "Alai can only be `spoken` by Taj and Teshari." + - rscadd: "Adds a voicebox/larynx organ. Its only purpose at the moment is to assist in speaking certain langauges." + - tweak: "Language implants, like the EAL implant, now affect the voicebox organ, instead of being a freefloating implant." + - rscadd: "Adds a language implant for Common Skrellian." \ No newline at end of file diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 1bd5df7f9a2b1ec26520f1cb2a69d0232e83c5b2..c19111ab72dcd0544919084878537e5a7728c73b 100644 GIT binary patch delta 10410 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�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 delta 9149 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 diff --git a/vorestation.dme b/vorestation.dme index 5331c30de2..786a710fb2 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -2328,6 +2328,7 @@ #include "code\modules\organs\internal\liver.dm" #include "code\modules\organs\internal\lungs.dm" #include "code\modules\organs\internal\organ_internal.dm" +#include "code\modules\organs\internal\voicebox.dm" #include "code\modules\organs\subtypes\diona.dm" #include "code\modules\organs\subtypes\indestructible.dm" #include "code\modules\organs\subtypes\machine.dm" From adbb5b86a50aa318222c1049105fb217736beb00 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 21 Jul 2018 11:34:54 -0400 Subject: [PATCH 2/3] Fix merge conflicts --- .../loadout/loadout_utility.dm | 21 +--- .../human/species/virtual_reality/avatar.dm | 118 +----------------- code/modules/organs/subtypes/standard.dm | 9 +- 3 files changed, 6 insertions(+), 142 deletions(-) diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 736cd0dc48..52fce45031 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -116,28 +116,14 @@ path = /obj/item/weapon/cell/device /datum/gear/utility/implant -<<<<<<< HEAD - exploitable = 1 -/* VOREStation Edit - Make languages great again -/datum/gear/utility/implant/eal //This does nothing if you don't actually know EAL. - display_name = "implant, language, EAL" - path = /obj/item/weapon/implant/language/eal - cost = 2 -======= ->>>>>>> 8f9e817... Language and Larynx Additions (#5402) slot = "implant" - exploitable = 1*/ + exploitable = 1 /datum/gear/utility/implant/tracking display_name = "implant, tracking" path = /obj/item/weapon/implant/tracking/weak -<<<<<<< HEAD cost = 0 //VOREStation Edit. Changed cost to 0 - slot = "implant" - exploitable = 1 -======= - cost = 10 - +/* VOREStation Edit - Make languages great again /datum/gear/utility/implant/language cost = 2 exploitable = 0 @@ -151,8 +137,7 @@ display_name = "vocal synthesizer, Skrellian" description = "A surgically implanted vocal synthesizer which allows the owner to speak Common Skrellian, if they know it." path = /obj/item/weapon/implant/language/skrellian ->>>>>>> 8f9e817... Language and Larynx Additions (#5402) - +*/ /datum/gear/utility/pen display_name = "Fountain Pen" path = /obj/item/weapon/pen/fountain diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm index c747b61911..76f82ec513 100644 --- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -1,4 +1,3 @@ -<<<<<<< HEAD // ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. // ### Any and all of this is open to change for balance or whatever. // ### @@ -17,6 +16,8 @@ speech_bubble_appearance = "cyber" + assisted_langs = list() + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' @@ -110,119 +111,4 @@ if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) var/obj/machinery/vr_sleeper/V = vr_holder.loc -======= -// ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. -// ### Any and all of this is open to change for balance or whatever. -// ### -// ### -// Species definition follows. -/datum/species/shapeshifter/promethean/avatar - - name = SPECIES_VR - name_plural = "Virtual Reality Avatars" - blurb = "A 3-dimensional representation of some sort of animate object used to display the presence and actions of some-one or -thing using a virtual reality program." - show_ssd = "eerily still" - death_message = "flickers briefly, their gear falling in a heap on the floor around their motionless body." - knockout_message = "has been knocked unconscious!" - - spawn_flags = SPECIES_IS_RESTRICTED - - speech_bubble_appearance = "cyber" - - assisted_langs = list() - - male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') - female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') - male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' - female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' - - unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) - has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, O_EYES = /obj/item/organ/internal/eyes) // Slime core. - heal_rate = 0 // Avatars don't naturally heal like prometheans, at least not for now - inherent_verbs = list( - /mob/living/carbon/human/proc/shapeshifter_select_shape, - /mob/living/carbon/human/proc/shapeshifter_select_colour, - /mob/living/carbon/human/proc/shapeshifter_select_hair, - /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, - /mob/living/carbon/human/proc/shapeshifter_select_gender, - /mob/living/carbon/human/proc/regenerate, - /mob/living/carbon/human/proc/shapeshifter_change_opacity, - /mob/living/carbon/human/proc/exit_vr - ) - - -/datum/species/shapeshifter/promethean/avatar/handle_death(var/mob/living/carbon/human/H) - return - -/datum/species/shapeshifter/promethean/avatar/handle_environment_special(var/mob/living/carbon/human/H) - return - -/mob/living/carbon/human/proc/shapeshifter_change_opacity() - - set name = "Toggle Opacity" - set category = "Abilities" - - if(stat || world.time < last_special) - return - - last_special = world.time + 10 - - if(src.icon_state == "promethean") - icon_state = lowertext(src.species.get_bodytype(src)) - shapeshifter_change_species("Virtual Reality [src.species.get_bodytype(src)]") - else - icon_state = "promethean" - shapeshifter_change_species(SPECIES_VR) - - -// enter_vr is called on the original mob, and puts the mind into the supplied vr mob -/mob/living/carbon/human/proc/enter_vr(var/mob/living/carbon/human/avatar) // Avatar is currently a human, because we have preexisting setup code for appearance manipulation, etc. - if(!istype(avatar)) - return - - // Link the two mobs for client transfer - avatar.vr_holder = src - src.teleop = avatar - src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR - - // Move the mind - avatar.Sleeping(1) - src.mind.transfer_to(avatar) - to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") - to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? - -// exit_vr is called on the vr mob, and puts the mind back into the original mob -/mob/living/carbon/human/proc/exit_vr() - set name = "Exit Virtual Reality" - set category = "Abilities" - - if(!vr_holder) - return - if(!mind) - return - - var/total_damage - // Tally human damage - if(ishuman(src)) - var/mob/living/carbon/human/H = src - total_damage = H.getBruteLoss() + H.getFireLoss() + H.getOxyLoss() + H.getToxLoss() - - // Move the mind back to the original mob -// vr_holder.Sleeping(1) - src.mind.transfer_to(vr_holder) - to_chat(vr_holder, "You black out for a moment, and wake to find yourself back in your own body.") - // Two-thirds damage is transferred as agony for /humans - // Getting hurt in VR doesn't damage the physical body, but you still got hurt. - if(ishuman(vr_holder) && total_damage) - var/mob/living/carbon/human/V = vr_holder - V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m. - to_chat(vr_holder, "Pain from your time in VR lingers.") // 250 damage leaves the user unconscious for several seconds in addition to paincrit - - // Maintain a link with the mob, but don't use teleop - vr_holder.vr_link = src - vr_holder.teleop = null - - if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) - var/obj/machinery/vr_sleeper/V = vr_holder.loc ->>>>>>> 8f9e817... Language and Larynx Additions (#5402) V.go_out() \ No newline at end of file diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index b7de7765d1..568d45088c 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -23,18 +23,11 @@ organ_rel_size = 70 base_miss_chance = 10 -<<<<<<< HEAD -/obj/item/organ/external/chest/robotize(var/company, var/skip_prosthetics = 0, var/keep_organs = 0) - if(..() && robotic != ORGAN_NANOFORM) //VOREStation Edit - // Give them a new cell. - owner.internal_organs_by_name["cell"] = new /obj/item/organ/internal/cell(owner,1) -======= /obj/item/organ/external/chest/robotize() - if(..()) + if(..() && robotic != ORGAN_NANOFORM) //VOREStation Edit // Give them fancy new organs. owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1) owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1) ->>>>>>> 8f9e817... Language and Larynx Additions (#5402) /obj/item/organ/external/chest/handle_germ_effects() . = ..() //Should return an infection level From 46f7b22838cd4e6693fbb98d019731c82b123223 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 21 Jul 2018 14:21:17 -0400 Subject: [PATCH 3/3] Fix virgo implant stuff --- code/controllers/subsystems/transcore_vr.dm | 12 +++- .../items/weapons/implants/implant_vr.dm | 72 +++++++++---------- .../weapons/implants/implantreagent_vr.dm | 2 +- code/modules/resleeving/implant.dm | 20 ++---- code/modules/resleeving/machines.dm | 10 +-- .../vore/fluffstuff/custom_items_vr.dm | 12 ++-- 6 files changed, 56 insertions(+), 72 deletions(-) diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm index feae05ae91..ddac25ee83 100644 --- a/code/controllers/subsystems/transcore_vr.dm +++ b/code/controllers/subsystems/transcore_vr.dm @@ -45,12 +45,18 @@ SUBSYSTEM_DEF(transcore) current_run.len-- //Remove if not in a human anymore. - if(!imp || !ishuman(imp.loc)) + if(!imp || !isorgan(imp.loc)) implants -= imp continue - //We're in a human, at least. - var/mob/living/carbon/human/H = imp.loc + //We're in an organ, at least. + var/obj/item/organ/external/EO = imp.loc + var/mob/living/carbon/human/H = EO.owner + if(!H) + implants -= imp + continue + + //In a human BITSET(H.hud_updateflag, BACKUP_HUD) if(H == imp.imp_in && H.mind && H.stat < DEAD) diff --git a/code/game/objects/items/weapons/implants/implant_vr.dm b/code/game/objects/items/weapons/implants/implant_vr.dm index 4b796cc56e..ebcc2d9f54 100644 --- a/code/game/objects/items/weapons/implants/implant_vr.dm +++ b/code/game/objects/items/weapons/implants/implant_vr.dm @@ -3,43 +3,39 @@ desc = "Allows the user to understand and speak almost all known languages.." var/uses = 1 - get_data() - var/dat = {" -Implant Specifications:
-Name: Language Implant
-Life: One day.
-Important Notes: Personnel with this implant can speak almost all known languages.
-
-Implant Details: Subjects injected with implant can understand and speak almost all known languages.
-Function: Contains specialized nanobots to stimulate the brain so the user can speak and understand previously unknown languages.
-Special Features: Will allow the user to understand almost all languages.
-Integrity: Implant can only be used once before the nanobots are depleted."} - return dat +/obj/item/weapon/implant/vrlanguage/get_data() + var/dat = {" + Implant Specifications:
+ Name: Language Implant
+ Life: One day.
+ Important Notes: Personnel with this implant can speak almost all known languages.
+
+ Implant Details: Subjects injected with implant can understand and speak almost all known languages.
+ Function: Contains specialized nanobots to stimulate the brain so the user can speak and understand previously unknown languages.
+ Special Features: Will allow the user to understand almost all languages.
+ Integrity: Implant can only be used once before the nanobots are depleted."} + return dat +/obj/item/weapon/implant/vrlanguage/trigger(emote, mob/source as mob) + if (src.uses < 1) + return 0 + if (emote == "smile") + src.uses-- + to_chat(source,"You suddenly feel as if you can understand other languages!") + source.add_language(LANGUAGE_CHIMPANZEE) + source.add_language(LANGUAGE_NEAERA) + source.add_language(LANGUAGE_STOK) + source.add_language(LANGUAGE_FARWA) + source.add_language(LANGUAGE_UNATHI) + source.add_language(LANGUAGE_SIIK) + source.add_language(LANGUAGE_SKRELLIAN) + source.add_language(LANGUAGE_SCHECHI) + source.add_language(LANGUAGE_BIRDSONG) + source.add_language(LANGUAGE_SAGARU) + source.add_language(LANGUAGE_CANILUNZT) + source.add_language(LANGUAGE_SOL_COMMON) //In case they're giving a xenomorph an implant or something. - trigger(emote, mob/source as mob) - if (src.uses < 1) return 0 - if (emote == "smile") - src.uses-- - source << "You suddenly feel as if you can understand other languages!" - source.add_language(LANGUAGE_CHIMPANZEE) - source.add_language(LANGUAGE_NEAERA) - source.add_language(LANGUAGE_STOK) - source.add_language(LANGUAGE_FARWA) - source.add_language(LANGUAGE_UNATHI) - source.add_language(LANGUAGE_SIIK) - source.add_language(LANGUAGE_SKRELLIAN) - source.add_language(LANGUAGE_SCHECHI) - source.add_language(LANGUAGE_BIRDSONG) - source.add_language(LANGUAGE_SAGARU) - source.add_language(LANGUAGE_CANILUNZT) - source.add_language(LANGUAGE_SOL_COMMON) //In case they're giving a xenomorph an implant or something. - - - return - - - implanted(mob/source) - source.mind.store_memory("A implant can be activated by using the smile emote, say *smile to attempt to activate.", 0, 0) - source << "The implanted language implant can be activated by using the smile emote, say *smile to attempt to activate." - return 1 +/obj/item/weapon/implant/vrlanguage/post_implant(mob/source) + source.mind.store_memory("A implant can be activated by using the smile emote, say *smile to attempt to activate.", 0, 0) + to_chat(source,"The implanted language implant can be activated by using the smile emote, say *smile to attempt to activate.") + return 1 diff --git a/code/game/objects/items/weapons/implants/implantreagent_vr.dm b/code/game/objects/items/weapons/implants/implantreagent_vr.dm index 1c4e9a9b04..83a586d2ba 100644 --- a/code/game/objects/items/weapons/implants/implantreagent_vr.dm +++ b/code/game/objects/items/weapons/implants/implantreagent_vr.dm @@ -30,7 +30,7 @@ update() return -/obj/item/weapon/implant/reagent_generator/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") assigned_proc = new assigned_proc(source, verb_name, verb_desc) diff --git a/code/modules/resleeving/implant.dm b/code/modules/resleeving/implant.dm index 0bfe571a8b..adb3d38e1c 100644 --- a/code/modules/resleeving/implant.dm +++ b/code/modules/resleeving/implant.dm @@ -27,13 +27,9 @@ SStranscore.implants -= src return ..() -/obj/item/weapon/implant/backup/implanted(var/mob/living/carbon/human/H) - ..() +/obj/item/weapon/implant/backup/post_implant(var/mob/living/carbon/human/H) if(istype(H)) - var/obj/item/weapon/implant/backup/other_imp = locate(/obj/item/weapon/implant/backup,H) - if(other_imp && other_imp.imp_in == H) - qdel(other_imp) //implant fight - + BITSET(H.hud_updateflag, BACKUP_HUD) SStranscore.implants |= src return 1 @@ -107,18 +103,10 @@ M.visible_message("[M] has been backup implanted by [user].") var/obj/item/weapon/implant/backup/imp = imps[imps.len] - if(imp.implanted(M)) - imp.forceMove(M) + if(imp.handle_implant(M,user.zone_sel.selecting)) + imp.post_implant(M) imps -= imp - imp.imp_in = M - imp.implanted = 1 add_attack_logs(user,M,"Implanted backup implant") - if (ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - affected.implants += imp - imp.part = affected - BITSET(H.hud_updateflag, BACKUP_HUD) update() diff --git a/code/modules/resleeving/machines.dm b/code/modules/resleeving/machines.dm index 787d867eb8..69f0cfebd1 100644 --- a/code/modules/resleeving/machines.dm +++ b/code/modules/resleeving/machines.dm @@ -538,14 +538,8 @@ //Give them a backup implant var/obj/item/weapon/implant/backup/new_imp = new() - if(new_imp.implanted(occupant)) - new_imp.loc = occupant - new_imp.imp_in = occupant - new_imp.implanted = 1 - //Put it in the head! Makes sense. - var/obj/item/organ/external/affected = occupant.get_organ(BP_HEAD) - affected.implants += new_imp - new_imp.part = affected + if(new_imp.handle_implant(occupant, BP_HEAD)) + new_imp.post_implant(occupant) //Inform them and make them a little dizzy. if(confuse_amount + blur_amount <= 16) diff --git a/code/modules/vore/fluffstuff/custom_items_vr.dm b/code/modules/vore/fluffstuff/custom_items_vr.dm index 4b0e1ece7b..b01e3a9e2c 100644 --- a/code/modules/vore/fluffstuff/custom_items_vr.dm +++ b/code/modules/vore/fluffstuff/custom_items_vr.dm @@ -725,7 +725,7 @@ random_emote = list("hisses softly with a blush on his face", "yelps in embarrassment", "grunts a little") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_roiz -/obj/item/weapon/implant/reagent_generator/roiz/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/roiz/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc @@ -793,7 +793,7 @@ random_emote = list("hisses softly with a blush on her face", "bites down on her lower lip", "lets out a light huff") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_jasmine -/obj/item/weapon/implant/reagent_generator/jasmine/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/jasmine/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc @@ -861,7 +861,7 @@ random_emote = list("hisses softly with a blush on her face", "yelps in embarrassment", "grunts a little") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_yonra -/obj/item/weapon/implant/reagent_generator/yonra/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/yonra/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc @@ -945,7 +945,7 @@ random_emote = list("trembles and huffs, panting from the exertion.", "sees what has happened and covers her face with both hands!", "whimpers softly, her legs shivering, knees pointed inward from the feeling.") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_rischi -/obj/item/weapon/implant/reagent_generator/rischi/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/rischi/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc @@ -1011,7 +1011,7 @@ self_emote_descriptor = list("grab", "pick", "snatch") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_pumila_apple -/obj/item/weapon/implant/reagent_generator/pumila_apple/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/pumila_apple/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc @@ -1704,7 +1704,7 @@ random_emote = list("hisses softly with a blush on his face", "yelps in embarrassment", "grunts a little") assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_evian -/obj/item/weapon/implant/reagent_generator/evian/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/reagent_generator/evian/post_implant(mob/living/carbon/source) processing_objects += src to_chat(source, "You implant [source] with \the [src].") source.verbs |= assigned_proc