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/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/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/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/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/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/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..52fce45031 100644
--- a/code/modules/client/preference_setup/loadout/loadout_utility.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm
@@ -116,22 +116,28 @@
path = /obj/item/weapon/cell/device
/datum/gear/utility/implant
- 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
slot = "implant"
- exploitable = 1*/
+ exploitable = 1
/datum/gear/utility/implant/tracking
display_name = "implant, tracking"
path = /obj/item/weapon/implant/tracking/weak
cost = 0 //VOREStation Edit. Changed cost to 0
- slot = "implant"
- exploitable = 1
+/* VOREStation Edit - Make languages great again
+/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
+*/
/datum/gear/utility/pen
display_name = "Fountain Pen"
path = /obj/item/weapon/pen/fountain
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..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
@@ -16,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'
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..568d45088c 100644
--- a/code/modules/organs/subtypes/standard.dm
+++ b/code/modules/organs/subtypes/standard.dm
@@ -23,10 +23,11 @@
organ_rel_size = 70
base_miss_chance = 10
-/obj/item/organ/external/chest/robotize(var/company, var/skip_prosthetics = 0, var/keep_organs = 0)
+/obj/item/organ/external/chest/robotize()
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)
+ // 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)
/obj/item/organ/external/chest/handle_germ_effects()
. = ..() //Should return an infection level
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
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 1bd5df7f9a..c19111ab72 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
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"