diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 260df783bf9..d184f765eac 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -108,11 +108,12 @@ icon_state = "internal0" else var/no_mask = FALSE - if(!C.wear_mask || !(C.wear_mask.flags & AIRTIGHT)) - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(!H.head || !(H.head.flags & AIRTIGHT)) - no_mask = TRUE + if(!C.get_organ_slot("breathing_tube")) + if(!C.wear_mask || !(C.wear_mask.flags & AIRTIGHT)) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(!H.head || !(H.head.flags & AIRTIGHT)) + no_mask = TRUE if(no_mask) to_chat(C, "You are not wearing a suitable mask or helmet.") diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 3b99936b0a8..27cbff53547 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -54,7 +54,9 @@ C.update_internals_hud_icon(0) else var/can_open_valve = 0 - if(C.wear_mask && C.wear_mask.flags & AIRTIGHT) + if(C.get_organ_slot("breathing_tube")) + can_open_valve = 1 + else if(C.wear_mask && C.wear_mask.flags & AIRTIGHT) can_open_valve = 1 else if(ishuman(C)) var/mob/living/carbon/human/H = C diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 3d11f40b1c9..596259b47da 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -332,7 +332,7 @@ BLIND // can't see anything mask_adjusted = 1 if(adjusted_flags) slot_flags = adjusted_flags - if(ishuman(user) && H.internal && user.wear_mask == src) /*If the user was wearing the mask providing internals on their face at the time it was adjusted, turn off internals. + if(ishuman(user) && H.internal && !H.get_organ_slot("breathing_tube") && user.wear_mask == src) /*If the user was wearing the mask providing internals on their face at the time it was adjusted, turn off internals. Otherwise, they adjusted it while it was in their hands or some such so we won't be needing to turn off internals.*/ H.update_internals_hud_icon(0) H.internal = null diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 1407fba6998..8caecdb42d7 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -650,9 +650,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, "[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].") var/no_mask - if(!(wear_mask && wear_mask.flags & AIRTIGHT)) - if(!(head && head.flags & AIRTIGHT)) - no_mask = 1 + if(!get_organ_slot("breathing_tube")) + if(!(wear_mask && wear_mask.flags & AIRTIGHT)) + if(!(head && head.flags & AIRTIGHT)) + no_mask = 1 if(no_mask) to_chat(usr, "[src] is not wearing a suitable mask or helmet!") return @@ -663,9 +664,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, update_internals_hud_icon(0) else var/no_mask2 - if(!(wear_mask && wear_mask.flags & AIRTIGHT)) - if(!(head && head.flags & AIRTIGHT)) - no_mask2 = 1 + if(!get_organ_slot("breathing_tube")) + if(!(wear_mask && wear_mask.flags & AIRTIGHT)) + if(!(head && head.flags & AIRTIGHT)) + no_mask2 = 1 if(no_mask2) to_chat(usr, "[src] is not wearing a suitable mask or helmet!") return diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 6e34291caae..ab7a5f1d5a9 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -3,6 +3,7 @@ hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD) var/list/stomach_contents = list() var/list/internal_organs = list() + var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access. var/antibodies = 0 var/life_tick = 0 // The amount of life ticks that have processed on this mob. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ba55801c522..2fec182504a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -428,7 +428,7 @@ /mob/living/carbon/human/show_inv(mob/user) user.set_machine(src) - var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) + var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) || get_organ_slot("breathing_tube") var/list/obscured = check_obscured_slots() var/dat = {" diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 8e1c32f931a..6edc2f0ae75 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -151,7 +151,7 @@ update_hair() //rebuild hair update_fhair() update_head_accessory() - if(internal) + if(internal && !get_organ_slot("breathing_tube")) internal = null update_internals_hud_icon(0) wear_mask_update(I, toggle_off = FALSE) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f51ba71bff8..5a67b1c09a2 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -301,9 +301,10 @@ var/null_internals = 0 //internals are invalid, therefore turn them off var/skip_contents_check = 0 //rigsuit snowflake, oxygen tanks aren't stored inside the mob, so the 'contents.Find' check has to be skipped. - if(!(wear_mask && wear_mask.flags & AIRTIGHT)) //if NOT (wear_mask AND wear_mask.flags CONTAIN AIRTIGHT) - if(!(head && head.flags & AIRTIGHT)) //if NOT (head AND head.flags CONTAIN AIRTIGHT) - null_internals = 1 //not wearing a mask or suitable helmet + if(!get_organ_slot("breathing_tube")) + if(!(wear_mask && wear_mask.flags & AIRTIGHT)) //if NOT (wear_mask AND wear_mask.flags CONTAIN AIRTIGHT) + if(!(head && head.flags & AIRTIGHT)) //if NOT (head AND head.flags CONTAIN AIRTIGHT) + null_internals = 1 //not wearing a mask or suitable helmet if(istype(back, /obj/item/weapon/rig)) //wearing a rigsuit var/obj/item/weapon/rig/rig = back //needs to be typecasted because this doesn't use get_rig() for some reason diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index da764cafda3..cbfc9ddbfdf 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -183,9 +183,10 @@ if(internal) if(internal.loc != src) internal = null - if(!wear_mask || !(wear_mask.flags & AIRTIGHT)) //not wearing mask or non-breath mask - if(!head || !(head.flags & AIRTIGHT)) //not wearing helmet or non-breath helmet - internal = null //turn off internals + if(!get_organ_slot("breathing_tube")) + if(!wear_mask || !(wear_mask.flags & AIRTIGHT)) //not wearing mask or non-breath mask + if(!head || !(head.flags & AIRTIGHT)) //not wearing helmet or non-breath helmet + internal = null //turn off internals if(internal) update_internals_hud_icon(1) diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index ecc987530ab..4b41b5084c6 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -167,9 +167,11 @@ */ + var/breathing_tube = affecting.get_organ_slot("breathing_tube") + if(state >= GRAB_NECK) affecting.Stun(5) //It will hamper your voice, being choked and all. - if(isliving(affecting)) + if(isliving(affecting) && !breathing_tube) var/mob/living/L = affecting L.adjustOxyLoss(1) @@ -177,7 +179,8 @@ //affecting.apply_effect(STUTTER, 5) //would do this, but affecting isn't declared as mob/living for some stupid reason. affecting.Stuttering(5) //It will hamper your voice, being choked and all. affecting.Weaken(5) //Should keep you down unless you get help. - affecting.AdjustLoseBreath(2, bound_lower = 0, bound_upper = 3) + if(!breathing_tube) + affecting.AdjustLoseBreath(2, bound_lower = 0, bound_upper = 3) adjust_position() @@ -290,7 +293,8 @@ msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") assailant.next_move = world.time + 10 - affecting.AdjustLoseBreath(1) + if(!affecting.get_organ_slot("breathing_tube")) + affecting.AdjustLoseBreath(1) affecting.setDir(WEST) adjust_position() diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 66c150f636d..601ad98346a 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -260,6 +260,17 @@ build_path = /obj/item/organ/internal/cyberimp/eyes/shield category = list("Misc", "Medical") +/datum/design/cyberimp_breather + name = "Breathing Tube Implant" + desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked." + id = "ci-breather" + req_tech = list("materials" = 2, "biotech" = 3) + build_type = PROTOLATHE | MECHFAB + construction_time = 35 + materials = list(MAT_METAL = 600, MAT_GLASS = 250) + build_path = /obj/item/organ/internal/cyberimp/mouth/breathing_tube + category = list("Misc", "Medical Designs") + /datum/design/cyberimp_medical_hud name = "Medical HUD implant" desc = "These cybernetic eyes will display a medical HUD over everything you see. Wiggle eyes to control." diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 4a7aa2554fc..13061db2c4d 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -144,6 +144,24 @@ spawn(90 / severity) crit_fail = 0 + +//[[[[MOUTH]]]] +/obj/item/organ/internal/cyberimp/mouth + parent_organ = "mouth" + +/obj/item/organ/internal/cyberimp/mouth/breathing_tube + name = "breathing tube implant" + desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked." + icon_state = "implant_mask" + slot = "breathing_tube" + w_class = WEIGHT_CLASS_TINY + origin_tech = "materials=2;biotech=3" + +/obj/item/organ/internal/cyberimp/mouth/breathing_tube/emp_act(severity) + if(prob(60/severity) && owner) + to_chat(owner, "Your breathing tube suddenly closes!") + owner.AdjustLoseBreath(2) + /obj/item/organ/internal/cyberimp/brain/clown_voice name = "Comical implant" desc = "Uh oh." diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index 94b0de5e066..61ed78d0e3b 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -30,9 +30,7 @@ return returnorg /mob/living/carbon/get_organ_slot(slot) - for(var/obj/item/organ/internal/O in internal_organs) - if(slot == O.slot) - return O + return internal_organs_slot[slot] /mob/living/carbon/get_int_organ_tag(tag) for(var/obj/item/organ/internal/O in internal_organs) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 071d579b0c0..47535c044eb 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -7,6 +7,7 @@ throwforce = 0 var/zone = "chest" var/slot + // DO NOT add slots with matching names to different zones - it will break internal_organs_slot list! vital = 0 var/non_primary = 0 @@ -29,6 +30,7 @@ owner = M M.internal_organs |= src + M.internal_organs_slot[slot] = src var/obj/item/organ/external/parent if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M @@ -52,6 +54,8 @@ owner = null if(M) M.internal_organs -= src + if(M.internal_organs_slot[slot] == src) + M.internal_organs_slot.Remove(slot) if(vital && !special) if(M.stat != DEAD)//safety check! M.death() diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index ac42a7d538c..2d1bb9ac749 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ