diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 0941ad32575..29bb7191796 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -161,7 +161,7 @@ /obj/item/organ/heart/gland/chem = 5, /obj/item/organ/heart/gland/mindshock = 5, /obj/item/organ/heart/gland/plasma = 7, - /obj/item/organ/heart/gland/pop = 5, + /obj/item/organ/heart/gland/transform = 5, /obj/item/organ/heart/gland/slime = 4, /obj/item/organ/heart/gland/spiderman = 5, /obj/item/organ/heart/gland/ventcrawling = 1, diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index 2cc09be061a..b1cd2c8ff71 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -107,378 +107,3 @@ /obj/item/organ/heart/gland/proc/activate() return - -/obj/item/organ/heart/gland/heals - true_name = "coherency harmonizer" - cooldown_low = 200 - cooldown_high = 400 - uses = -1 - icon_state = "health" - mind_control_uses = 3 - mind_control_duration = 3000 - -/obj/item/organ/heart/gland/heals/activate() - to_chat(owner, "You feel curiously revitalized.") - owner.adjustToxLoss(-20, FALSE, TRUE) - owner.heal_bodypart_damage(20, 20, 0, TRUE) - owner.adjustOxyLoss(-20) - -/obj/item/organ/heart/gland/slime - true_name = "gastric animation galvanizer" - cooldown_low = 600 - cooldown_high = 1200 - uses = -1 - icon_state = "slime" - mind_control_uses = 1 - mind_control_duration = 2400 - -/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0) - ..() - owner.faction |= "slime" - owner.grant_language(/datum/language/slime) - -/obj/item/organ/heart/gland/slime/activate() - to_chat(owner, "You feel nauseated!") - owner.vomit(20) - - var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey") - Slime.Friends = list(owner) - Slime.Leader = owner - -/obj/item/organ/heart/gland/mindshock - true_name = "neural crosstalk uninhibitor" - cooldown_low = 400 - cooldown_high = 700 - uses = -1 - icon_state = "mindshock" - mind_control_uses = 1 - mind_control_duration = 6000 - var/list/mob/living/carbon/human/broadcasted_mobs = list() - -/obj/item/organ/heart/gland/mindshock/activate() - to_chat(owner, "You get a headache.") - - var/turf/T = get_turf(owner) - for(var/mob/living/carbon/H in orange(4,T)) - if(H == owner) - continue - switch(pick(1,3)) - if(1) - to_chat(H, "You hear a loud buzz in your head, silencing your thoughts!") - H.Stun(50) - if(2) - to_chat(H, "You hear an annoying buzz in your head.") - H.confused += 15 - H.adjustBrainLoss(10, 160) - if(3) - H.hallucination += 60 - -/obj/item/organ/heart/gland/mindshock/mind_control(command, mob/living/user) - if(!ownerCheck() || !mind_control_uses || active_mind_control) - return FALSE - mind_control_uses-- - for(var/mob/M in oview(7, owner)) - if(!ishuman(M)) - continue - var/mob/living/carbon/human/H = M - if(H.stat) - continue - - broadcasted_mobs += H - to_chat(H, "You suddenly feel an irresistible compulsion to follow an order...") - to_chat(H, "[command]") - - message_admins("[key_name(user)] broadcasted an abductor mind control message from [key_name(owner)] to [key_name(H)]: [command]") - - var/obj/screen/alert/mind_control/mind_alert = H.throw_alert("mind_control", /obj/screen/alert/mind_control) - mind_alert.command = command - - if(LAZYLEN(broadcasted_mobs)) - active_mind_control = TRUE - addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration) - - update_gland_hud() - return TRUE - -/obj/item/organ/heart/gland/mindshock/clear_mind_control() - if(!active_mind_control || !LAZYLEN(broadcasted_mobs)) - return FALSE - for(var/M in broadcasted_mobs) - var/mob/living/carbon/human/H = M - to_chat(H, "You feel the compulsion fade, and you completely forget about your previous orders.") - H.clear_alert("mind_control") - active_mind_control = FALSE - return TRUE - -/obj/item/organ/heart/gland/access - true_name = "anagraphic electro-scrambler" - cooldown_low = 600 - cooldown_high = 1200 - uses = 1 - icon_state = "mindshock" - mind_control_uses = 3 - mind_control_duration = 900 - -/obj/item/organ/heart/gland/access/activate() - to_chat(owner, "You feel like a VIP for some reason.") - RegisterSignal(owner, COMSIG_MOB_ALLOWED, .proc/free_access) - -/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O) - return TRUE - -/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0) - UnregisterSignal(owner, COMSIG_MOB_ALLOWED) - ..() - -/obj/item/organ/heart/gland/pop - true_name = "anthropmorphic transmorphosizer" - cooldown_low = 900 - cooldown_high = 1800 - uses = -1 - human_only = TRUE - icon_state = "species" - mind_control_uses = 7 - mind_control_duration = 300 - -/obj/item/organ/heart/gland/pop/activate() - to_chat(owner, "You feel unlike yourself.") - randomize_human(owner) - var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/moth, /datum/species/fly)) - owner.set_species(species) - -/obj/item/organ/heart/gland/ventcrawling - true_name = "pliant cartilage enabler" - cooldown_low = 1800 - cooldown_high = 2400 - uses = 1 - icon_state = "vent" - mind_control_uses = 4 - mind_control_duration = 1800 - -/obj/item/organ/heart/gland/ventcrawling/activate() - to_chat(owner, "You feel very stretchy.") - owner.ventcrawler = VENTCRAWLER_ALWAYS - -/obj/item/organ/heart/gland/viral - true_name = "contamination incubator" - cooldown_low = 1800 - cooldown_high = 2400 - uses = 1 - icon_state = "viral" - mind_control_uses = 1 - mind_control_duration = 1800 - -/obj/item/organ/heart/gland/viral/activate() - to_chat(owner, "You feel sick.") - var/datum/disease/advance/A = random_virus(pick(2,6),6) - A.carrier = TRUE - owner.ForceContractDisease(A, FALSE, TRUE) - -/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level) - if(max_symptoms > VIRUS_SYMPTOM_LIMIT) - max_symptoms = VIRUS_SYMPTOM_LIMIT - var/datum/disease/advance/A = new /datum/disease/advance() - var/list/datum/symptom/possible_symptoms = list() - for(var/symptom in subtypesof(/datum/symptom)) - var/datum/symptom/S = symptom - if(initial(S.level) > max_level) - continue - if(initial(S.level) <= 0) //unobtainable symptoms - continue - possible_symptoms += S - for(var/i in 1 to max_symptoms) - var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) - if(chosen_symptom) - var/datum/symptom/S = new chosen_symptom - A.symptoms += S - A.Refresh() //just in case someone already made and named the same disease - return A - -/obj/item/organ/heart/gland/trauma - true_name = "white matter randomiser" - cooldown_low = 800 - cooldown_high = 1200 - uses = 5 - icon_state = "emp" - mind_control_uses = 3 - mind_control_duration = 1800 - -/obj/item/organ/heart/gland/trauma/activate() - to_chat(owner, "You feel a spike of pain in your head.") - if(prob(33)) - owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) - else - if(prob(20)) - owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) - else - owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) - -/obj/item/organ/heart/gland/quantum - true_name = "quantic de-observation matrix" - cooldown_low = 150 - cooldown_high = 150 - uses = -1 - icon_state = "emp" - mind_control_uses = 2 - mind_control_duration = 1200 - var/mob/living/carbon/entangled_mob - -/obj/item/organ/heart/gland/quantum/activate() - if(entangled_mob) - return - for(var/mob/M in oview(owner, 7)) - if(!iscarbon(M)) - continue - entangled_mob = M - addtimer(CALLBACK(src, .proc/quantum_swap), rand(600, 2400)) - return - -/obj/item/organ/heart/gland/quantum/proc/quantum_swap() - if(QDELETED(entangled_mob)) - entangled_mob = null - return - var/turf/T = get_turf(owner) - do_teleport(owner, get_turf(entangled_mob),null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM) - do_teleport(entangled_mob, T,null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM) - to_chat(owner, "You suddenly find yourself somewhere else!") - to_chat(entangled_mob, "You suddenly find yourself somewhere else!") - if(!active_mind_control) //Do not reset entangled mob while mind control is active - entangled_mob = null - -/obj/item/organ/heart/gland/quantum/mind_control(command, mob/living/user) - if(..()) - if(entangled_mob && ishuman(entangled_mob) && (entangled_mob.stat < DEAD)) - to_chat(entangled_mob, "You suddenly feel an irresistible compulsion to follow an order...") - to_chat(entangled_mob, "[command]") - var/obj/screen/alert/mind_control/mind_alert = entangled_mob.throw_alert("mind_control", /obj/screen/alert/mind_control) - mind_alert.command = command - message_admins("[key_name(owner)] mirrored an abductor mind control message to [key_name(entangled_mob)]: [command]") - update_gland_hud() - -/obj/item/organ/heart/gland/quantum/clear_mind_control() - if(active_mind_control) - to_chat(entangled_mob, "You feel the compulsion fade, and you completely forget about your previous orders.") - entangled_mob.clear_alert("mind_control") - ..() - -/obj/item/organ/heart/gland/spiderman - true_name = "araneae cloister accelerator" - cooldown_low = 450 - cooldown_high = 900 - uses = -1 - icon_state = "spider" - mind_control_uses = 2 - mind_control_duration = 2400 - -/obj/item/organ/heart/gland/spiderman/activate() - to_chat(owner, "You feel something crawling in your skin.") - owner.faction |= "spiders" - var/obj/structure/spider/spiderling/S = new(owner.drop_location()) - S.directive = "Protect your nest inside [owner.real_name]." - -/obj/item/organ/heart/gland/egg - true_name = "roe/enzymatic synthesizer" - cooldown_low = 300 - cooldown_high = 400 - uses = -1 - icon_state = "egg" - lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' - mind_control_uses = 2 - mind_control_duration = 1800 - -/obj/item/organ/heart/gland/egg/activate() - owner.visible_message("[owner] [pick(EGG_LAYING_MESSAGES)]") - var/turf/T = owner.drop_location() - new /obj/item/reagent_containers/food/snacks/egg/gland(T) - - -/obj/item/organ/heart/gland/blood - true_name = "pseudonuclear hemo-destabilizer" - cooldown_low = 1200 - cooldown_high = 1800 - uses = -1 - icon_state = "egg" - lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' - mind_control_uses = 3 - mind_control_duration = 1500 - -/obj/item/organ/heart/gland/blood/activate() - if(!ishuman(owner) || !owner.dna.species) - return - var/mob/living/carbon/human/H = owner - var/datum/species/species = H.dna.species - to_chat(H, "You feel your blood heat up for a moment.") - species.exotic_blood = get_random_reagent_id() - -/obj/item/organ/heart/gland/electric - true_name = "electron accumulator/discharger" - cooldown_low = 800 - cooldown_high = 1200 - icon_state = "species" - uses = -1 - mind_control_uses = 2 - mind_control_duration = 900 - -/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0) - ..() - ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland") - -/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0) - REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland") - ..() - -/obj/item/organ/heart/gland/electric/activate() - owner.visible_message("[owner]'s skin starts emitting electric arcs!",\ - "You feel electric energy building up inside you!") - playsound(get_turf(owner), "sparks", 100, 1, -1) - addtimer(CALLBACK(src, .proc/zap), rand(30, 100)) - -/obj/item/organ/heart/gland/electric/proc/zap() - tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN) - playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1) - -/obj/item/organ/heart/gland/chem - true_name = "intrinsic pharma-provider" - cooldown_low = 50 - cooldown_high = 50 - uses = -1 - icon_state = "viral" - mind_control_uses = 3 - mind_control_duration = 1200 - var/list/possible_reagents = list() - -/obj/item/organ/heart/gland/chem/Initialize() - . = ..() - for(var/R in subtypesof(/datum/reagent/drug) + subtypesof(/datum/reagent/medicine) + typesof(/datum/reagent/toxin)) - possible_reagents += R - -/obj/item/organ/heart/gland/chem/activate() - var/chem_to_add = pick(possible_reagents) - owner.reagents.add_reagent(chem_to_add, 2) - owner.adjustToxLoss(-5, TRUE, TRUE) - ..() - -/obj/item/organ/heart/gland/plasma - true_name = "effluvium sanguine-synonym emitter" - cooldown_low = 1200 - cooldown_high = 1800 - icon_state = "slime" - uses = -1 - mind_control_uses = 1 - mind_control_duration = 800 - -/obj/item/organ/heart/gland/plasma/activate() - to_chat(owner, "You feel bloated.") - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "A massive stomachache overcomes you."), 150) - addtimer(CALLBACK(src, .proc/vomit_plasma), 200) - -/obj/item/organ/heart/gland/plasma/proc/vomit_plasma() - if(!owner) - return - owner.visible_message("[owner] vomits a cloud of plasma!") - var/turf/open/T = get_turf(owner) - if(istype(T)) - T.atmos_spawn_air("plasma=50;TEMP=[T20C]") - owner.vomit() diff --git a/code/modules/antagonists/abductor/equipment/glands/access.dm b/code/modules/antagonists/abductor/equipment/glands/access.dm new file mode 100644 index 00000000000..e950a07d065 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/access.dm @@ -0,0 +1,19 @@ +/obj/item/organ/heart/gland/access + true_name = "anagraphic electro-scrambler" + cooldown_low = 600 + cooldown_high = 1200 + uses = 1 + icon_state = "mindshock" + mind_control_uses = 3 + mind_control_duration = 900 + +/obj/item/organ/heart/gland/access/activate() + to_chat(owner, "You feel like a VIP for some reason.") + RegisterSignal(owner, COMSIG_MOB_ALLOWED, .proc/free_access) + +/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O) + return TRUE + +/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0) + UnregisterSignal(owner, COMSIG_MOB_ALLOWED) + ..() diff --git a/code/modules/antagonists/abductor/equipment/glands/blood.dm b/code/modules/antagonists/abductor/equipment/glands/blood.dm new file mode 100644 index 00000000000..2e4803e0e9e --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/blood.dm @@ -0,0 +1,18 @@ +/obj/item/organ/heart/gland/blood + true_name = "pseudonuclear hemo-destabilizer" + cooldown_low = 1200 + cooldown_high = 1800 + uses = -1 + icon_state = "egg" + lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' + mind_control_uses = 3 + mind_control_duration = 1500 + +/obj/item/organ/heart/gland/blood/activate() + if(!ishuman(owner) || !owner.dna.species) + return + var/mob/living/carbon/human/H = owner + var/datum/species/species = H.dna.species + to_chat(H, "You feel your blood heat up for a moment.") + species.exotic_blood = get_random_reagent_id() diff --git a/code/modules/antagonists/abductor/equipment/glands/chem.dm b/code/modules/antagonists/abductor/equipment/glands/chem.dm new file mode 100644 index 00000000000..b651b45f6d1 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/chem.dm @@ -0,0 +1,20 @@ +/obj/item/organ/heart/gland/chem + true_name = "intrinsic pharma-provider" + cooldown_low = 50 + cooldown_high = 50 + uses = -1 + icon_state = "viral" + mind_control_uses = 3 + mind_control_duration = 1200 + var/list/possible_reagents = list() + +/obj/item/organ/heart/gland/chem/Initialize() + . = ..() + for(var/R in subtypesof(/datum/reagent/drug) + subtypesof(/datum/reagent/medicine) + typesof(/datum/reagent/toxin)) + possible_reagents += R + +/obj/item/organ/heart/gland/chem/activate() + var/chem_to_add = pick(possible_reagents) + owner.reagents.add_reagent(chem_to_add, 2) + owner.adjustToxLoss(-5, TRUE, TRUE) + ..() diff --git a/code/modules/antagonists/abductor/equipment/glands/egg.dm b/code/modules/antagonists/abductor/equipment/glands/egg.dm new file mode 100644 index 00000000000..e3b0c835f27 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/egg.dm @@ -0,0 +1,15 @@ +/obj/item/organ/heart/gland/egg + true_name = "roe/enzymatic synthesizer" + cooldown_low = 300 + cooldown_high = 400 + uses = -1 + icon_state = "egg" + lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' + mind_control_uses = 2 + mind_control_duration = 1800 + +/obj/item/organ/heart/gland/egg/activate() + owner.visible_message("[owner] [pick(EGG_LAYING_MESSAGES)]") + var/turf/T = owner.drop_location() + new /obj/item/reagent_containers/food/snacks/egg/gland(T) diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm new file mode 100644 index 00000000000..ce42bc9f36c --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -0,0 +1,26 @@ +/obj/item/organ/heart/gland/electric + true_name = "electron accumulator/discharger" + cooldown_low = 800 + cooldown_high = 1200 + icon_state = "species" + uses = -1 + mind_control_uses = 2 + mind_control_duration = 900 + +/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0) + ..() + ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland") + +/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0) + REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland") + ..() + +/obj/item/organ/heart/gland/electric/activate() + owner.visible_message("[owner]'s skin starts emitting electric arcs!",\ + "You feel electric energy building up inside you!") + playsound(get_turf(owner), "sparks", 100, 1, -1) + addtimer(CALLBACK(src, .proc/zap), rand(30, 100)) + +/obj/item/organ/heart/gland/electric/proc/zap() + tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN) + playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1) diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm new file mode 100644 index 00000000000..6bb0a617c60 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm @@ -0,0 +1,178 @@ +/obj/item/organ/heart/gland/heal + true_name = "organic replicator" + cooldown_low = 200 + cooldown_high = 400 + uses = -1 + human_only = TRUE + icon_state = "health" + mind_control_uses = 3 + mind_control_duration = 3000 + +/obj/item/organ/heart/gland/heal/activate() + if(!MOB_ORGANIC in owner.mob_biotypes) + return + + for(var/organ in owner.internal_organs) + if(istype(organ, /obj/item/organ/cyberimp)) + reject_implant(organ) + return + + var/obj/item/organ/liver/liver = owner.getorganslot(ORGAN_SLOT_LIVER) + if((!liver/* && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM)*/) || (liver && ((liver.damage > (liver.maxHealth / 2)) || (istype(liver, /obj/item/organ/liver/cybernetic))))) + replace_liver(liver) + return + + var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS) + if((!lungs && !HAS_TRAIT(owner, TRAIT_NOBREATH)) || (lungs && (istype(lungs, /obj/item/organ/lungs/cybernetic)))) + replace_lungs(lungs) + return + + var/obj/item/organ/eyes/eyes = owner.getorganslot(ORGAN_SLOT_EYES) + if(!eyes || (eyes && ((HAS_TRAIT_FROM(owner, TRAIT_NEARSIGHT, EYE_DAMAGE)) || (HAS_TRAIT_FROM(owner, TRAIT_BLIND, EYE_DAMAGE)) || (istype(eyes, /obj/item/organ/eyes/robotic))))) + replace_eyes(eyes) + return + + var/obj/item/bodypart/limb + var/list/limb_list = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + for(var/zone in limb_list) + limb = owner.get_bodypart(zone) + if(!limb) + replace_limb(zone) + return + if((limb.get_damage() >= (limb.max_damage / 2)) || (limb.status == BODYPART_ROBOTIC)) + replace_limb(zone, limb) + return + + if(owner.getToxLoss() > 40) + replace_blood() + return + var/tox_amount = 0 + for(var/datum/reagent/toxin/T in owner.reagents.reagent_list) + tox_amount += owner.reagents.get_reagent_amount(T.type) + if(tox_amount > 10) + replace_blood() + return + if(owner.blood_volume < BLOOD_VOLUME_OKAY) + owner.blood_volume = BLOOD_VOLUME_NORMAL + to_chat(owner, "You feel your blood pulsing within you.") + return + + var/obj/item/bodypart/chest/chest = owner.get_bodypart(BODY_ZONE_CHEST) + if((chest.get_damage() >= (chest.max_damage / 4)) || (chest.status == BODYPART_ROBOTIC)) + replace_chest(chest) + return + +/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant) + owner.visible_message("[owner] vomits up his [implant.name]!", "You suddenly vomit up your [implant.name]!") + owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE) + implant.Remove(owner) + implant.forceMove(owner.drop_location()) + +/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver) + if(liver) + owner.visible_message("[owner] vomits up his [liver.name]!", "You suddenly vomit up your [liver.name]!") + owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE) + liver.Remove(owner) + liver.forceMove(owner.drop_location()) + else + to_chat(owner, "You feel a weird rumble in your bowels...") + + var/liver_type = /obj/item/organ/liver + if(owner?.dna?.species?.mutantliver) + liver_type = owner.dna.species.mutantliver + var/obj/item/organ/liver/new_liver = new liver_type() + new_liver.Insert(owner) + +/obj/item/organ/heart/gland/heal/proc/replace_lungs(obj/item/organ/lungs/lungs) + if(lungs) + owner.visible_message("[owner] vomits up his [lungs.name]!", "You suddenly vomit up your [lungs.name]!") + owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE) + lungs.Remove(owner) + lungs.forceMove(owner.drop_location()) + else + to_chat(owner, "You feel a weird rumble inside your chest...") + + var/lung_type = /obj/item/organ/lungs + if(owner.dna.species && owner.dna.species.mutantlungs) + lung_type = owner.dna.species.mutantlungs + var/obj/item/organ/lungs/new_lungs = new lung_type() + new_lungs.Insert(owner) + +/obj/item/organ/heart/gland/heal/proc/replace_eyes(obj/item/organ/eyes/eyes) + if(eyes) + owner.visible_message("[owner]'s [eyes.name] fall out of their sockets!", "Your [eyes.name] fall out of their sockets!") + playsound(owner, 'sound/effects/splat.ogg', 50, 1) + eyes.Remove(owner) + eyes.forceMove(owner.drop_location()) + else + to_chat(owner, "You feel a weird rumble behind your eye sockets...") + + addtimer(CALLBACK(src, .proc/finish_replace_eyes), rand(100, 200)) + +/obj/item/organ/heart/gland/heal/proc/finish_replace_eyes() + var/eye_type = /obj/item/organ/eyes + if(owner.dna.species && owner.dna.species.mutanteyes) + eye_type = owner.dna.species.mutanteyes + var/obj/item/organ/eyes/new_eyes = new eye_type() + new_eyes.Insert(owner) + owner.visible_message("A pair of new eyes suddenly inflates into [owner]'s eye sockets!", "A pair of new eyes suddenly inflates into your eye sockets!") + +/obj/item/organ/heart/gland/heal/proc/replace_limb(body_zone, obj/item/bodypart/limb) + if(limb) + owner.visible_message("[owner]'s [limb.name] suddenly detaches from [owner.p_their()] body!", "Your [limb.name] suddenly detaches from your body!") + playsound(owner,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + limb.drop_limb() + else + to_chat(owner, "You feel a weird tingle in your [parse_zone(body_zone)]... even if you don't have one.") + + addtimer(CALLBACK(src, .proc/finish_replace_limb, body_zone), rand(150, 300)) + +/obj/item/organ/heart/gland/heal/proc/finish_replace_limb(body_zone) + owner.visible_message("With a loud snap, [owner]'s [parse_zone(body_zone)] rapidly grows back from [owner.p_their()] body!", + "With a loud snap, your [parse_zone(body_zone)] rapidly grows back from your body!", + "Your hear a loud snap.") + playsound(owner, 'sound/magic/demon_consume.ogg', 50, 1) + owner.regenerate_limb(body_zone) + +/obj/item/organ/heart/gland/heal/proc/replace_blood() + owner.visible_message("[owner] starts vomiting huge amounts of blood!", "You suddenly start vomiting huge amounts of blood!") + keep_replacing_blood() + +/obj/item/organ/heart/gland/heal/proc/keep_replacing_blood() + var/keep_going = FALSE + owner.vomit(0, TRUE, FALSE, 3, FALSE, FALSE, FALSE, TRUE) + owner.Stun(15) + owner.adjustToxLoss(-15, TRUE, TRUE) + + owner.blood_volume = min(BLOOD_VOLUME_NORMAL, owner.blood_volume + 20) + if(owner.blood_volume < BLOOD_VOLUME_NORMAL) + keep_going = TRUE + + if(owner.getToxLoss()) + keep_going = TRUE + for(var/datum/reagent/toxin/R in owner.reagents.reagent_list) + owner.reagents.remove_reagent(R.type, 4) + if(owner.reagents.has_reagent(R.type)) + keep_going = TRUE + if(keep_going) + addtimer(CALLBACK(src, .proc/keep_replacing_blood), 30) + +/obj/item/organ/heart/gland/heal/proc/replace_chest(obj/item/bodypart/chest/chest) + if(chest.status == BODYPART_ROBOTIC) + owner.visible_message("[owner]'s [chest.name] rapidly expels its mechanical components, replacing them with flesh!", "Your [chest.name] rapidly expels its mechanical components, replacing them with flesh!") + playsound(owner, 'sound/magic/clockwork/anima_fragment_attack.ogg', 50, 1) + var/list/dirs = GLOB.alldirs.Copy() + for(var/i in 1 to 3) + var/obj/effect/decal/cleanable/robot_debris/debris = new(get_turf(owner)) + debris.streak(dirs) + else + owner.visible_message("[owner]'s [chest.name] sheds off its damaged flesh, rapidly replacing it!", "Your [chest.name] sheds off its damaged flesh, rapidly replacing it!") + playsound(owner, 'sound/effects/splat.ogg', 50, 1) + var/list/dirs = GLOB.alldirs.Copy() + for(var/i in 1 to 3) + var/obj/effect/decal/cleanable/blood/gibs/gibs = new(get_turf(owner)) + gibs.streak(dirs) + + var/obj/item/bodypart/chest/new_chest = new(null) + new_chest.replace_limb(owner, TRUE) + qdel(chest) diff --git a/code/modules/antagonists/abductor/equipment/glands/mindshock.dm b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm new file mode 100644 index 00000000000..a27e1ee4369 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm @@ -0,0 +1,64 @@ +/obj/item/organ/heart/gland/mindshock + true_name = "neural crosstalk uninhibitor" + cooldown_low = 400 + cooldown_high = 700 + uses = -1 + icon_state = "mindshock" + mind_control_uses = 1 + mind_control_duration = 6000 + var/list/mob/living/carbon/human/broadcasted_mobs = list() + +/obj/item/organ/heart/gland/mindshock/activate() + to_chat(owner, "You get a headache.") + + var/turf/T = get_turf(owner) + for(var/mob/living/carbon/H in orange(4,T)) + if(H == owner) + continue + switch(pick(1,3)) + if(1) + to_chat(H, "You hear a loud buzz in your head, silencing your thoughts!") + H.Stun(50) + if(2) + to_chat(H, "You hear an annoying buzz in your head.") + H.confused += 15 + H.adjustBrainLoss(10, 160) + if(3) + H.hallucination += 60 + +/obj/item/organ/heart/gland/mindshock/mind_control(command, mob/living/user) + if(!ownerCheck() || !mind_control_uses || active_mind_control) + return FALSE + mind_control_uses-- + for(var/mob/M in oview(7, owner)) + if(!ishuman(M)) + continue + var/mob/living/carbon/human/H = M + if(H.stat) + continue + + broadcasted_mobs += H + to_chat(H, "You suddenly feel an irresistible compulsion to follow an order...") + to_chat(H, "[command]") + + message_admins("[key_name(user)] broadcasted an abductor mind control message from [key_name(owner)] to [key_name(H)]: [command]") + + var/obj/screen/alert/mind_control/mind_alert = H.throw_alert("mind_control", /obj/screen/alert/mind_control) + mind_alert.command = command + + if(LAZYLEN(broadcasted_mobs)) + active_mind_control = TRUE + addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration) + + update_gland_hud() + return TRUE + +/obj/item/organ/heart/gland/mindshock/clear_mind_control() + if(!active_mind_control || !LAZYLEN(broadcasted_mobs)) + return FALSE + for(var/M in broadcasted_mobs) + var/mob/living/carbon/human/H = M + to_chat(H, "You feel the compulsion fade, and you completely forget about your previous orders.") + H.clear_alert("mind_control") + active_mind_control = FALSE + return TRUE diff --git a/code/modules/antagonists/abductor/equipment/glands/plasma.dm b/code/modules/antagonists/abductor/equipment/glands/plasma.dm new file mode 100644 index 00000000000..fe8b06ac77a --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/plasma.dm @@ -0,0 +1,22 @@ +/obj/item/organ/heart/gland/plasma + true_name = "effluvium sanguine-synonym emitter" + cooldown_low = 1200 + cooldown_high = 1800 + icon_state = "slime" + uses = -1 + mind_control_uses = 1 + mind_control_duration = 800 + +/obj/item/organ/heart/gland/plasma/activate() + to_chat(owner, "You feel bloated.") + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "A massive stomachache overcomes you."), 150) + addtimer(CALLBACK(src, .proc/vomit_plasma), 200) + +/obj/item/organ/heart/gland/plasma/proc/vomit_plasma() + if(!owner) + return + owner.visible_message("[owner] vomits a cloud of plasma!") + var/turf/open/T = get_turf(owner) + if(istype(T)) + T.atmos_spawn_air("plasma=50;TEMP=[T20C]") + owner.vomit() diff --git a/code/modules/antagonists/abductor/equipment/glands/quantum.dm b/code/modules/antagonists/abductor/equipment/glands/quantum.dm new file mode 100644 index 00000000000..fc1ddae030d --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/quantum.dm @@ -0,0 +1,47 @@ +/obj/item/organ/heart/gland/quantum + true_name = "quantic de-observation matrix" + cooldown_low = 150 + cooldown_high = 150 + uses = -1 + icon_state = "emp" + mind_control_uses = 2 + mind_control_duration = 1200 + var/mob/living/carbon/entangled_mob + +/obj/item/organ/heart/gland/quantum/activate() + if(entangled_mob) + return + for(var/mob/M in oview(owner, 7)) + if(!iscarbon(M)) + continue + entangled_mob = M + addtimer(CALLBACK(src, .proc/quantum_swap), rand(600, 2400)) + return + +/obj/item/organ/heart/gland/quantum/proc/quantum_swap() + if(QDELETED(entangled_mob)) + entangled_mob = null + return + var/turf/T = get_turf(owner) + do_teleport(owner, get_turf(entangled_mob),null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM) + do_teleport(entangled_mob, T,null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM) + to_chat(owner, "You suddenly find yourself somewhere else!") + to_chat(entangled_mob, "You suddenly find yourself somewhere else!") + if(!active_mind_control) //Do not reset entangled mob while mind control is active + entangled_mob = null + +/obj/item/organ/heart/gland/quantum/mind_control(command, mob/living/user) + if(..()) + if(entangled_mob && ishuman(entangled_mob) && (entangled_mob.stat < DEAD)) + to_chat(entangled_mob, "You suddenly feel an irresistible compulsion to follow an order...") + to_chat(entangled_mob, "[command]") + var/obj/screen/alert/mind_control/mind_alert = entangled_mob.throw_alert("mind_control", /obj/screen/alert/mind_control) + mind_alert.command = command + message_admins("[key_name(owner)] mirrored an abductor mind control message to [key_name(entangled_mob)]: [command]") + update_gland_hud() + +/obj/item/organ/heart/gland/quantum/clear_mind_control() + if(active_mind_control) + to_chat(entangled_mob, "You feel the compulsion fade, and you completely forget about your previous orders.") + entangled_mob.clear_alert("mind_control") + ..() diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm new file mode 100644 index 00000000000..f6fd6a778c5 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm @@ -0,0 +1,21 @@ +/obj/item/organ/heart/gland/slime + true_name = "gastric animation galvanizer" + cooldown_low = 600 + cooldown_high = 1200 + uses = -1 + icon_state = "slime" + mind_control_uses = 1 + mind_control_duration = 2400 + +/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0) + ..() + owner.faction |= "slime" + owner.grant_language(/datum/language/slime) + +/obj/item/organ/heart/gland/slime/activate() + to_chat(owner, "You feel nauseated!") + owner.vomit(20) + + var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey") + Slime.Friends = list(owner) + Slime.Leader = owner diff --git a/code/modules/antagonists/abductor/equipment/glands/spider.dm b/code/modules/antagonists/abductor/equipment/glands/spider.dm new file mode 100644 index 00000000000..7c3c60eb4d1 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/spider.dm @@ -0,0 +1,14 @@ +/obj/item/organ/heart/gland/spiderman + true_name = "araneae cloister accelerator" + cooldown_low = 450 + cooldown_high = 900 + uses = -1 + icon_state = "spider" + mind_control_uses = 2 + mind_control_duration = 2400 + +/obj/item/organ/heart/gland/spiderman/activate() + to_chat(owner, "You feel something crawling in your skin.") + owner.faction |= "spiders" + var/obj/structure/spider/spiderling/S = new(owner.drop_location()) + S.directive = "Protect your nest inside [owner.real_name]." diff --git a/code/modules/antagonists/abductor/equipment/glands/transform.dm b/code/modules/antagonists/abductor/equipment/glands/transform.dm new file mode 100644 index 00000000000..cad1543f8bb --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/transform.dm @@ -0,0 +1,15 @@ +/obj/item/organ/heart/gland/transform + true_name = "anthropmorphic transmorphosizer" + cooldown_low = 900 + cooldown_high = 1800 + uses = -1 + human_only = TRUE + icon_state = "species" + mind_control_uses = 7 + mind_control_duration = 300 + +/obj/item/organ/heart/gland/transform/activate() + to_chat(owner, "You feel unlike yourself.") + randomize_human(owner) + var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/moth, /datum/species/fly)) + owner.set_species(species) diff --git a/code/modules/antagonists/abductor/equipment/glands/trauma.dm b/code/modules/antagonists/abductor/equipment/glands/trauma.dm new file mode 100644 index 00000000000..af971c4aa17 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/trauma.dm @@ -0,0 +1,18 @@ +/obj/item/organ/heart/gland/trauma + true_name = "white matter randomiser" + cooldown_low = 800 + cooldown_high = 1200 + uses = 5 + icon_state = "emp" + mind_control_uses = 3 + mind_control_duration = 1800 + +/obj/item/organ/heart/gland/trauma/activate() + to_chat(owner, "You feel a spike of pain in your head.") + if(prob(33)) + owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) + else + if(prob(20)) + owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) + else + owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) diff --git a/code/modules/antagonists/abductor/equipment/glands/ventcrawl.dm b/code/modules/antagonists/abductor/equipment/glands/ventcrawl.dm new file mode 100644 index 00000000000..8ac083f68b1 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/ventcrawl.dm @@ -0,0 +1,12 @@ +/obj/item/organ/heart/gland/ventcrawling + true_name = "pliant cartilage enabler" + cooldown_low = 1800 + cooldown_high = 2400 + uses = 1 + icon_state = "vent" + mind_control_uses = 4 + mind_control_duration = 1800 + +/obj/item/organ/heart/gland/ventcrawling/activate() + to_chat(owner, "You feel very stretchy.") + owner.ventcrawler = VENTCRAWLER_ALWAYS diff --git a/code/modules/antagonists/abductor/equipment/glands/viral.dm b/code/modules/antagonists/abductor/equipment/glands/viral.dm new file mode 100644 index 00000000000..1b6781b5782 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/glands/viral.dm @@ -0,0 +1,34 @@ +/obj/item/organ/heart/gland/viral + true_name = "contamination incubator" + cooldown_low = 1800 + cooldown_high = 2400 + uses = 1 + icon_state = "viral" + mind_control_uses = 1 + mind_control_duration = 1800 + +/obj/item/organ/heart/gland/viral/activate() + to_chat(owner, "You feel sick.") + var/datum/disease/advance/A = random_virus(pick(2,6),6) + A.carrier = TRUE + owner.ForceContractDisease(A, FALSE, TRUE) + +/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level) + if(max_symptoms > VIRUS_SYMPTOM_LIMIT) + max_symptoms = VIRUS_SYMPTOM_LIMIT + var/datum/disease/advance/A = new /datum/disease/advance() + var/list/datum/symptom/possible_symptoms = list() + for(var/symptom in subtypesof(/datum/symptom)) + var/datum/symptom/S = symptom + if(initial(S.level) > max_level) + continue + if(initial(S.level) <= 0) //unobtainable symptoms + continue + possible_symptoms += S + for(var/i in 1 to max_symptoms) + var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) + if(chosen_symptom) + var/datum/symptom/S = new chosen_symptom + A.symptoms += S + A.Refresh() //just in case someone already made and named the same disease + return A diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index bccdf3ea3d1..955be0eb585 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -430,9 +430,9 @@ return 0 return ..() -/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE) - if(HAS_TRAIT(src, TRAIT_NOHUNGER)) - return 1 +/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE, harm = TRUE, force = FALSE) + if(HAS_TRAIT(src, TRAIT_NOHUNGER) && !force) + return TRUE if(nutrition < 100 && !blood) if(message) @@ -440,7 +440,7 @@ "You try to throw up, but there's nothing in your stomach!") if(stun) Paralyze(200) - return 1 + return TRUE if(is_mouth_covered()) //make this add a blood/vomit overlay later it'll be hilarious if(message) @@ -466,7 +466,7 @@ if(blood) if(T) add_splatter_floor(T) - if(stun) + if(harm) adjustBruteLoss(3) else if(src.reagents.has_reagent(/datum/reagent/consumable/ethanol/blazaam, needs_metabolizing = TRUE)) if(T) @@ -477,7 +477,7 @@ T = get_step(T, dir) if (is_blocked_turf(T)) break - return 1 + return TRUE /mob/living/carbon/proc/spew_organ(power = 5, amt = 1) for(var/i in 1 to amt) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index f701b049c55..c8434ba03ec 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -44,8 +44,13 @@ var/mob/living/carbon/human/HMN = M HMN.eye_color = old_eye_color HMN.regenerate_icons() + M.cure_blind(EYE_DAMAGE) + M.cure_nearsighted(EYE_DAMAGE) + M.set_blindness(0) + M.set_blurriness(0) M.update_tint() M.update_sight() + /obj/item/organ/eyes/on_life() ..() diff --git a/tgstation.dme b/tgstation.dme index b3c8c8db7ad..5a9eea338a8 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1210,6 +1210,21 @@ #include "code\modules\antagonists\abductor\equipment\abduction_outfits.dm" #include "code\modules\antagonists\abductor\equipment\abduction_surgery.dm" #include "code\modules\antagonists\abductor\equipment\gland.dm" +#include "code\modules\antagonists\abductor\equipment\glands\access.dm" +#include "code\modules\antagonists\abductor\equipment\glands\blood.dm" +#include "code\modules\antagonists\abductor\equipment\glands\chem.dm" +#include "code\modules\antagonists\abductor\equipment\glands\egg.dm" +#include "code\modules\antagonists\abductor\equipment\glands\electric.dm" +#include "code\modules\antagonists\abductor\equipment\glands\heal.dm" +#include "code\modules\antagonists\abductor\equipment\glands\mindshock.dm" +#include "code\modules\antagonists\abductor\equipment\glands\plasma.dm" +#include "code\modules\antagonists\abductor\equipment\glands\quantum.dm" +#include "code\modules\antagonists\abductor\equipment\glands\slime.dm" +#include "code\modules\antagonists\abductor\equipment\glands\spider.dm" +#include "code\modules\antagonists\abductor\equipment\glands\transform.dm" +#include "code\modules\antagonists\abductor\equipment\glands\trauma.dm" +#include "code\modules\antagonists\abductor\equipment\glands\ventcrawl.dm" +#include "code\modules\antagonists\abductor\equipment\glands\viral.dm" #include "code\modules\antagonists\abductor\machinery\camera.dm" #include "code\modules\antagonists\abductor\machinery\console.dm" #include "code\modules\antagonists\abductor\machinery\dispenser.dm"