/////////////////////////////////// // POWERS /////////////////////////////////// /datum/mutation/nobreath name = "No Breathing" activation_messages = list("You feel no need to breathe.") deactivation_messages = list("You feel the need to breathe, once more.") instability = GENE_INSTABILITY_MAJOR traits_to_add = list(TRAIT_NOBREATH) /datum/mutation/nobreath/New() ..() block = GLOB.breathlessblock /datum/mutation/regenerate name = "Regenerate" activation_messages = list("Your wounds start healing.") deactivation_messages = list("Your regenerative powers feel like they've vanished.") instability = GENE_INSTABILITY_MINOR /datum/mutation/regenerate/New() ..() block = GLOB.regenerateblock /datum/mutation/regenerate/on_life(mob/living/carbon/human/H) if(!H.ignore_gene_stability && H.gene_stability < GENETIC_DAMAGE_STAGE_1) H.adjustBruteLoss(-0.25, FALSE) H.adjustFireLoss(-0.25) return H.adjustBruteLoss(-1, FALSE) H.adjustFireLoss(-1) /datum/mutation/heat_resist name = "Heat Resistance" activation_messages = list("Your skin is icy to the touch.") deactivation_messages = list("Your skin no longer feels icy to the touch.") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_RESISTHEAT, TRAIT_RESISTHIGHPRESSURE) /datum/mutation/heat_resist/New() ..() block = GLOB.coldblock /datum/mutation/heat_resist/on_draw_underlays(mob/M, g) return "cold_s" /datum/mutation/cold_resist name = "Cold Resistance" activation_messages = list("Your body is filled with warmth.") deactivation_messages = list("Your body is no longer filled with warmth.") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_RESISTCOLD, TRAIT_RESISTLOWPRESSURE) /datum/mutation/cold_resist/New() ..() block = GLOB.fireblock /datum/mutation/cold_resist/on_draw_underlays(mob/M, g) return "fire_s" /datum/mutation/noprints name = "No Prints" activation_messages = list("Your fingers feel numb.") deactivation_messages = list("Your fingers no longer feel numb.") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_NOFINGERPRINTS) /datum/mutation/noprints/New() ..() block = GLOB.noprintsblock /datum/mutation/noshock name = "Shock Immunity" activation_messages = list("Your skin feels dry and unreactive.") deactivation_messages = list("Your skin no longer feels dry and unreactive.") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_SHOCKIMMUNE) /datum/mutation/noshock/New() ..() block = GLOB.shockimmunityblock /datum/mutation/dwarf name = "Dwarf" activation_messages = list("Everything around you seems bigger now...") deactivation_messages = list("Everything around you seems to shrink...") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_DWARF) /datum/mutation/dwarf/New() ..() block = GLOB.smallsizeblock /datum/mutation/dwarf/activate(mob/M) ..() M.pass_flags |= PASSTABLE M.resize = 0.8 M.update_transform() /datum/mutation/dwarf/deactivate(mob/M) ..() M.pass_flags &= ~PASSTABLE M.resize = 1.25 M.update_transform() // OLD HULK BEHAVIOR /datum/mutation/hulk name = "Hulk" activation_messages = list("Your muscles hurt.") deactivation_messages = list("Your muscles shrink.") instability = GENE_INSTABILITY_MAJOR traits_to_add = list(TRAIT_HULK, TRAIT_CHUNKYFINGERS) /datum/mutation/hulk/New() ..() block = GLOB.hulkblock /datum/mutation/hulk/activate(mob/living/carbon/human/M) ..() var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH M.status_flags &= ~status M.update_body() /datum/mutation/hulk/deactivate(mob/living/carbon/human/M) ..() M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH M.update_body() /datum/mutation/hulk/on_life(mob/living/carbon/human/M) if(!istype(M)) return if(M.health <= 0) M.dna.SetSEState(GLOB.hulkblock, 0) singlemutcheck(M, GLOB.hulkblock, MUTCHK_FORCED) M.update_mutations() //update our mutation overlays M.update_body() M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved. to_chat(M, "You suddenly feel very weak.") /datum/mutation/tk name = "Telekenesis" activation_messages = list("You feel smarter.") deactivation_messages = list("You feel dumber.") instability = GENE_INSTABILITY_MAJOR traits_to_add = list(TRAIT_TELEKINESIS) /datum/mutation/tk/New() ..() block = GLOB.teleblock /datum/mutation/tk/on_draw_underlays(mob/M, g) return "telekinesishead_s" #define EAT_MOB_DELAY 300 // 30s // WAS: /datum/bioEffect/alcres /datum/mutation/sober name = "Sober" activation_messages = list("You feel unusually sober.") deactivation_messages = list("You feel like you could use a stiff drink.") instability = GENE_INSTABILITY_MINOR traits_to_add = list(TRAIT_ALCOHOL_TOLERANCE) /datum/mutation/sober/New() ..() block = GLOB.soberblock //WAS: /datum/bioEffect/psychic_resist /datum/mutation/psychic_resist name = "Psy-Resist" desc = "Boosts efficiency in sectors of the brain commonly associated with meta-mental energies." activation_messages = list("Your mind feels closed.") deactivation_messages = list("You feel oddly exposed.") instability = GENE_INSTABILITY_MINOR /datum/mutation/psychic_resist/New() ..() block = GLOB.psyresistblock ///////////////////////// // Stealth Enhancers ///////////////////////// /datum/mutation/stealth instability = GENE_INSTABILITY_MAJOR /datum/mutation/stealth/can_activate(mob/M, flags) // Can only activate one of these at a time. if(is_type_in_list(/datum/mutation/stealth, M.active_mutations)) testing("Cannot activate [type]: /datum/mutation/stealth in M.active_mutations.") return FALSE return ..() /datum/mutation/stealth/deactivate(mob/living/M) ..() M.reset_visibility() // WAS: /datum/bioEffect/darkcloak /datum/mutation/stealth/darkcloak name = "Cloak of Darkness" desc = "Enables the subject to bend low levels of light around themselves, creating a cloaking effect." activation_messages = list("You begin to fade into the shadows.") deactivation_messages = list("You become fully visible.") /datum/mutation/stealth/darkcloak/New() ..() block = GLOB.shadowblock /datum/mutation/stealth/darkcloak/deactivate(mob/living/M) ..() if(ishuman(M)) var/mob/living/carbon/human/H = M H.set_alpha_tracking(ALPHA_VISIBLE, src) if(!ishuman(M)) return var/mob/living/carbon/human/H = M H.set_alpha_tracking(ALPHA_VISIBLE, src) /datum/mutation/stealth/darkcloak/on_life(mob/M) var/turf/simulated/T = get_turf(M) if(!istype(T) || !ishuman(M)) return var/mob/living/carbon/human/H = M var/light_available = T.get_lumcount() * 10 if(light_available <= 2) if(H.invisibility != INVISIBILITY_LEVEL_TWO) H.set_alpha_tracking(H.get_alpha() * 0.8, src) else H.reset_visibility() H.set_alpha_tracking(ALPHA_VISIBLE * 0.8, src) if(H.get_alpha(src) == 0) H.make_invisible() //WAS: /datum/bioEffect/chameleon /datum/mutation/stealth/chameleon name = "Chameleon" desc = "The subject becomes able to subtly alter light patterns to become invisible, as long as they remain still." activation_messages = list("You feel one with your surroundings.") deactivation_messages = list("You feel oddly visible.") /datum/mutation/stealth/chameleon/New() ..() block = GLOB.chameleonblock /datum/mutation/stealth/chameleon/deactivate(mob/living/M) ..() if(ishuman(M)) var/mob/living/carbon/human/H = M H.set_alpha_tracking(ALPHA_VISIBLE, src) /datum/mutation/stealth/chameleon/on_life(mob/living/M) if(!ishuman(M)) return var/mob/living/carbon/human/H = M if((world.time - H.last_movement) >= 30 && !H.stat && (H.mobility_flags & MOBILITY_STAND) && !H.restrained()) if(H.invisibility != INVISIBILITY_LEVEL_TWO) H.set_alpha_tracking(H.get_alpha() - 25, src) else H.reset_visibility() H.set_alpha_tracking(ALPHA_VISIBLE * 0.8, src) if(H.get_alpha(src) == 0) H.make_invisible() ///////////////////////////////////////////////////////////////////////////////////////// /datum/mutation/grant_spell var/datum/spell/spelltype /datum/mutation/grant_spell/activate(mob/M) M.AddSpell(new spelltype(null)) ..() return TRUE /datum/mutation/grant_spell/deactivate(mob/M) for(var/datum/spell/S in M.mob_spell_list) if(istype(S, spelltype)) M.RemoveSpell(S) ..() return TRUE // WAS: /datum/bioEffect/cryokinesis /datum/mutation/grant_spell/cryo name = "Cryokinesis" desc = "Allows the subject to lower the body temperature of others." activation_messages = list("You notice a strange cold tingle in your fingertips.") deactivation_messages = list("Your fingers feel warmer.") instability = GENE_INSTABILITY_MODERATE spelltype = /datum/spell/cryokinesis /datum/mutation/grant_spell/cryo/New() ..() block = GLOB.cryoblock /datum/spell/cryokinesis name = "Cryokinesis" desc = "Drops the bodytemperature of another person." base_cooldown = 1200 clothes_req = FALSE stat_allowed = CONSCIOUS selection_activated_message = "Your mind grow cold. Click on a target to cast the spell." selection_deactivated_message = "Your mind returns to normal." invocation_type = "none" var/list/compatible_mobs = list(/mob/living/carbon/human) action_icon_state = "genetic_cryo" /datum/spell/cryokinesis/create_new_targeting() var/datum/spell_targeting/click/T = new() T.allowed_type = /mob/living/carbon T.click_radius = 0 T.try_auto_target = FALSE // Give the clueless geneticists a way out and to have them not target themselves T.selection_type = SPELL_SELECTION_RANGE T.include_user = TRUE return T /datum/spell/cryokinesis/cast(list/targets, mob/user = usr) var/mob/living/carbon/C = targets[1] if(HAS_TRAIT(C, TRAIT_RESISTCOLD)) C.visible_message("A cloud of fine ice crystals engulfs [C.name], but disappears almost instantly!") return var/handle_suit = FALSE if(ishuman(C)) var/mob/living/carbon/human/H = C if(istype(H.head, /obj/item/clothing/head/helmet/space)) if(istype(H.wear_suit, /obj/item/clothing/suit/space)) handle_suit = TRUE if(H.internal) H.visible_message("[user] sprays a cloud of fine ice crystals, engulfing [H]!", "[user] sprays a cloud of fine ice crystals over your [H.head]'s visor.") else H.visible_message("[user] sprays a cloud of fine ice crystals engulfing, [H]!", "[user] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.") H.bodytemperature = max(0, H.bodytemperature - 100) add_attack_logs(user, C, "Cryokinesis") if(!handle_suit) C.bodytemperature = max(0, C.bodytemperature - 200) C.ExtinguishMob() C.visible_message("[user] sprays a cloud of fine ice crystals, engulfing [C]!") add_attack_logs(user, C, "Cryokinesis- NO SUIT/INTERNALS") /////////////////////////////////////////////////////////////////////////////////////////// // WAS: /datum/bioEffect/mattereater /datum/mutation/grant_spell/mattereater name = "Matter Eater" desc = "Allows the subject to eat just about anything without harm." activation_messages = list("You feel hungry.") deactivation_messages = list("You don't feel quite so hungry anymore.") instability = GENE_INSTABILITY_MODERATE spelltype=/datum/spell/eat /datum/mutation/grant_spell/mattereater/New() ..() block = GLOB.eatblock /datum/spell/eat name = "Eat" desc = "Eat just about anything!" base_cooldown = 300 clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_eat" /datum/spell/eat/create_new_targeting() return new /datum/spell_targeting/matter_eater /datum/spell/eat/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE) . = ..() if(!.) return var/can_eat = TRUE if(iscarbon(user)) var/mob/living/carbon/C = user if((C.head && (C.head.flags_cover & HEADCOVERSMOUTH)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSMOUTH) && !C.wear_mask.up)) if(show_message) to_chat(C, "Your mouth is covered, preventing you from eating!") can_eat = FALSE return can_eat /datum/spell/eat/proc/doHeal(mob/user) if(ishuman(user)) var/mob/living/carbon/human/H = user for(var/name in H.bodyparts_by_name) var/obj/item/organ/external/affecting = null if(!H.bodyparts_by_name[name]) continue affecting = H.bodyparts_by_name[name] if(!is_external_organ(affecting)) continue affecting.heal_damage(4, 0, updating_health = FALSE) H.UpdateDamageIcon() H.updatehealth() /datum/spell/eat/cast(list/targets, mob/user = usr) if(!length(targets)) to_chat(user, "No target found in range.") return var/atom/movable/the_item = targets[1] if(!user.Adjacent(the_item)) to_chat(user, "You need to be next to [the_item] for this!") return FALSE if(ishuman(the_item)) var/mob/living/carbon/human/H = the_item var/obj/item/organ/external/limb = H.get_organ(user.zone_selected) if(!istype(limb)) to_chat(user, "You can't eat this part of them!") revert_cast() return FALSE if(istype(limb,/obj/item/organ/external/head)) // Bullshit, but prevents being unable to clone someone. to_chat(user, "You try to put \the [limb] in your mouth, but [the_item.p_their()] ears tickle your throat!") revert_cast() return FALSE if(istype(limb,/obj/item/organ/external/chest)) // Bullshit, but prevents being able to instagib someone. to_chat(user, "You try to put [the_item.p_their()] [limb] in your mouth, but it's too big to fit!") revert_cast() return FALSE user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!") if(!do_mob(user, H, EAT_MOB_DELAY)) to_chat(user, "You were interrupted before you could eat [the_item]!") else if(!limb || !H) return if(!user.Adjacent(the_item)) to_chat(user, "You need to be next to [the_item] for this!") return FALSE user.visible_message("[user] [pick("chomps","bites")] off [the_item]'s [limb]!") playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0) // Most limbs will drop here. Groin won't, but this // still spills out the organs that were in it. limb.droplimb(FALSE, DROPLIMB_SHARP) if(istype(limb, /obj/item/organ/external/groin)) limb.receive_damage(100, sharp = TRUE) var/obj/item/organ/external/left_leg = H.get_organ(BODY_ZONE_L_LEG) if(istype(left_leg)) left_leg.droplimb(FALSE, DROPLIMB_SHARP) var/obj/item/organ/external/right_leg = H.get_organ(BODY_ZONE_R_LEG) if(istype(right_leg)) right_leg.droplimb(FALSE, DROPLIMB_SHARP) var/obj/item/organ/external/chest = H.get_organ(BODY_ZONE_CHEST) if(istype(chest)) chest.receive_damage(50, sharp = TRUE) doHeal(user) return if(ismob(the_item.loc) && isitem(the_item)) var/obj/item/eaten = the_item var/mob/the_owner = the_item.loc if(!the_owner.unEquip(eaten, FALSE, TRUE)) to_chat(user, "You can't eat [the_item], it won't go down your throat!") return user.visible_message("[user] eats [the_item].") playsound(user.loc, 'sound/items/eatfood.ogg', 50, FALSE) if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/chest/target_place = H.get_organ(BODY_ZONE_CHEST) if(istype(target_place)) the_item.forceMove(target_place) doHeal(user) return qdel(the_item) doHeal(user) //////////////////////////////////////////////////////////////////////// //WAS: /datum/bioEffect/jumpy /datum/mutation/grant_spell/jumpy name = "Jumpy" desc = "Allows the subject to leap great distances." //cooldown = 30 activation_messages = list("Your leg muscles feel taut and strong.") deactivation_messages = list("Your leg muscles shrink back to normal.") instability = GENE_INSTABILITY_MODERATE spelltype =/datum/spell/leap /datum/mutation/grant_spell/jumpy/New() ..() block = GLOB.jumpblock /datum/spell/leap name = "Jump" desc = "Leap great distances!" base_cooldown = 60 clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_jump" var/leap_distance = 10 /datum/spell/leap/create_new_targeting() return new /datum/spell_targeting/self /datum/spell/leap/cast(list/targets, mob/living/user = usr) var/failure = FALSE if(ismob(user.loc) || IS_HORIZONTAL(user) || user.IsStunned() || user.buckled || user.stat) to_chat(user, "You can't jump right now!") return if(isturf(user.loc)) if(user.restrained())//Why being pulled while cuffed prevents you from moving for(var/mob/living/M in range(user, 1)) if(M.pulling == user) if(!M.restrained() && M.stat == CONSCIOUS && !(M.mobility_flags & MOBILITY_STAND) && user.Adjacent(M)) failure = TRUE else M.stop_pulling() user.visible_message("[user.name] takes a huge leap!") playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, 1) if(failure) user.Weaken(10 SECONDS) user.visible_message("[user] attempts to leap away but is slammed back down to the ground!", "You attempt to leap away but are suddenly slammed back down to the ground!", "You hear the flexing of powerful muscles and suddenly a crash as a body hits the floor.") return FALSE var/prevLayer = user.layer user.layer = 9 ADD_TRAIT(user, TRAIT_FLYING, "leap") for(var/i in 1 to leap_distance) var/turf/hit_turf = get_step(user, user.dir) var/atom/hit_atom = get_blocking_atom(hit_turf) if(hit_atom) hit_atom.hit_by_thrown_mob(user, damage = 10) break step(user, user.dir) if(i < 6) user.pixel_y += 8 else user.pixel_y -= 8 sleep(1) REMOVE_TRAIT(user, TRAIT_FLYING, "leap") user.pixel_y = 0 // In case leap was varedited to be longer or shorter if(HAS_TRAIT(user, TRAIT_FAT) && prob(66)) user.visible_message("[user.name] crashes due to [user.p_their()] heavy weight!") //playsound(user.loc, 'zhit.wav', 50, 1) user.AdjustWeakened(20 SECONDS) user.AdjustStunned(10 SECONDS) user.layer = prevLayer if(isobj(user.loc)) var/obj/container = user.loc to_chat(user, "You leap and slam your head against the inside of [container]! Ouch!") user.AdjustParalysis(6 SECONDS) user.AdjustWeakened(10 SECONDS) container.visible_message("[user.loc] emits a loud thump and rattles a bit.") playsound(user.loc, 'sound/effects/bang.ogg', 50, 1) var/wiggle = 6 while(wiggle > 0) wiggle-- container.pixel_x = rand(-3,3) container.pixel_y = rand(-3,3) sleep(1) container.pixel_x = 0 container.pixel_y = 0 /datum/spell/leap/proc/get_blocking_atom(turf/turf_to_check) if(!turf_to_check) return FALSE if(turf_to_check.density) return turf_to_check for(var/atom/movable/hit_thing in turf_to_check) if(isliving(hit_thing)) var/mob/living/hit_mob = hit_thing if(hit_mob.density) return hit_mob if(isobj(hit_thing)) var/obj/hit_obj = hit_thing if(hit_obj.density) return hit_obj return FALSE //////////////////////////////////////////////////////////////////////// // WAS: /datum/bioEffect/polymorphism /datum/mutation/grant_spell/polymorph name = "Polymorphism" desc = "Enables the subject to reconfigure their appearance to mimic that of others." spelltype =/datum/spell/polymorph //cooldown = 1800 activation_messages = list("You don't feel entirely like yourself somehow.") deactivation_messages = list("You feel secure in your identity.") instability = GENE_INSTABILITY_MODERATE /datum/mutation/grant_spell/polymorph/New() ..() block = GLOB.polymorphblock /datum/spell/polymorph name = "Polymorph" desc = "Mimic the appearance of others!" base_cooldown = 1800 clothes_req = FALSE stat_allowed = CONSCIOUS selection_activated_message = "You body becomes unstable. Click on a target to cast transform into them." selection_deactivated_message = "Your body calms down again." invocation_type = "none" action_icon_state = "genetic_poly" /datum/spell/polymorph/create_new_targeting() var/datum/spell_targeting/click/T = new() T.try_auto_target = FALSE T.click_radius = -1 T.range = 1 T.selection_type = SPELL_SELECTION_RANGE return T /datum/spell/polymorph/cast(list/targets, mob/user = usr) var/mob/living/carbon/human/target = targets[1] user.visible_message("[user]'s body shifts and contorts.") spawn(10) if(target && user) playsound(user.loc, 'sound/goonstation/effects/gib.ogg', 50, 1) var/mob/living/carbon/human/H = user H.UpdateAppearance(target.dna.UI) H.real_name = target.real_name H.name = target.name //////////////////////////////////////////////////////////////////////// // WAS: /datum/bioEffect/empath /datum/mutation/grant_spell/empath name = "Empathic Thought" desc = "The subject becomes able to read the minds of others for certain information." spelltype = /datum/spell/empath activation_messages = list("You suddenly notice more about others than you did before.") deactivation_messages = list("You no longer feel able to sense intentions.") instability = GENE_INSTABILITY_MINOR /datum/mutation/grant_spell/empath/New() ..() block = GLOB.empathblock /datum/spell/empath name = "Read Mind" desc = "Read the minds of others for information." base_cooldown = 18 SECONDS clothes_req = FALSE human_req = TRUE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_empath" /datum/spell/empath/create_new_targeting() var/datum/spell_targeting/targeted/T = new() T.allowed_type = /mob/living/carbon T.selection_type = SPELL_SELECTION_RANGE return T /datum/spell/empath/cast(list/targets, mob/user = usr) for(var/mob/living/carbon/M in targets) if(!iscarbon(M)) to_chat(user, "You may only use this on other organic beings.") return if(M.dna?.GetSEState(GLOB.psyresistblock)) to_chat(user, "You can't see into [M.name]'s mind at all!") return if(M.stat == DEAD) to_chat(user, "[M.name] is dead and cannot have [M.p_their()] mind read.") return if(M.health < 0) to_chat(user, "[M.name] is dying, and [M.p_their()] thoughts are too scrambled to read.") return to_chat(user, "Mind Reading of [M.name]:") var/pain_condition = M.health / M.maxHealth // lower health means more pain var/list/randomthoughts = list("what to have for lunch","the future","the past","money", "[M.p_their()] hair","what to do next","[M.p_their()] job","space","amusing things","sad things", "annoying things","happy things","something incoherent","something [M.p_they()] did wrong") var/thoughts = "thinking about [pick(randomthoughts)]" if(M.fire_stacks) pain_condition -= 0.5 thoughts = "preoccupied with the fire" if(M.radiation) pain_condition -= 0.25 switch(pain_condition) if(0.81 to INFINITY) to_chat(user, "Condition: [M.name] feels good.") if(0.61 to 0.8) to_chat(user, "Condition: [M.name] is suffering mild pain.") if(0.41 to 0.6) to_chat(user, "Condition: [M.name] is suffering significant pain.") if(0.21 to 0.4) to_chat(user, "Condition: [M.name] is suffering severe pain.") else to_chat(user, "Condition: [M.name] is suffering excruciating pain.") thoughts = "haunted by [M.p_their()] own mortality" switch(M.a_intent) if(INTENT_HELP) to_chat(user, "Mood: You sense benevolent thoughts from [M.name].") if(INTENT_DISARM) to_chat(user, "Mood: You sense cautious thoughts from [M.name].") if(INTENT_GRAB) to_chat(user, "Mood: You sense hostile thoughts from [M.name].") if(INTENT_HARM) to_chat(user, "Mood: You sense cruel thoughts from [M.name].") for(var/mob/living/L in view(7,M)) if(L == M) continue thoughts = "thinking about punching [L.name]" break else to_chat(user, "Mood: You sense strange thoughts from [M.name].") if(ishuman(M)) var/numbers[0] var/mob/living/carbon/human/H = M if(H.mind && H.mind.initial_account) numbers += H.mind.initial_account.account_number numbers += H.mind.initial_account.account_pin if(length(numbers)>0) to_chat(user, "Numbers: You sense the number[length(numbers)>1?"s":""] [english_list(numbers)] [length(numbers)>1?"are":"is"] important to [M.name].") to_chat(user, "Thoughts: [M.name] is currently [thoughts].") if(M.dna?.GetSEState(GLOB.empathblock)) to_chat(M, "You sense [user.name] reading your mind.") else if(prob(5) || M.mind?.assigned_role=="Chaplain") to_chat(M, "You sense someone intruding upon your thoughts...") ///////////////////Vanilla Morph//////////////////////////////////// /datum/mutation/grant_spell/morph name = "Morphism" desc = "Enables the subject to reconfigure their appearance to that of any human." spelltype =/datum/spell/morph activation_messages = list("Your body feels like it can alter its appearance.") deactivation_messages = list("Your body doesn't feel capable of altering its appearance.") instability = GENE_INSTABILITY_MODERATE /datum/mutation/grant_spell/morph/New() ..() block = GLOB.morphblock /datum/spell/morph name = "Morph" desc = "Mimic the appearance of your choice!" base_cooldown = 1800 clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_morph" /datum/spell/morph/create_new_targeting() return new /datum/spell_targeting/self /datum/spell/morph/cast(list/targets, mob/user = usr) if(!ishuman(user)) return if(ismob(user.loc)) to_chat(user, "You can't change your appearance right now!") return var/mob/living/carbon/human/M = user var/obj/item/organ/external/head/head_organ = M.get_organ("head") var/obj/item/organ/internal/eyes/eyes_organ = M.get_int_organ(/obj/item/organ/internal/eyes) var/new_gender = tgui_alert(user, "Please select gender.", "Character Generation", list("Male", "Female")) if(new_gender) if(new_gender == "Male") M.change_gender(MALE) else M.change_gender(FEMALE) if(eyes_organ) var/new_eyes = input("Please select eye color.", "Character Generation", eyes_organ.eye_color) as null|color if(new_eyes) M.change_eye_color(new_eyes) if(istype(head_organ)) //Alt heads. if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS) var/list/valid_alt_heads = M.generate_valid_alt_heads() var/new_alt_head = tgui_input_list(user, "Please select alternate head", "Character Generation", valid_alt_heads) if(new_alt_head) M.change_alt_head(new_alt_head) // hair var/list/valid_hairstyles = M.generate_valid_hairstyles() var/new_style = tgui_input_list(user, "Please select hair style", "Character Generation", valid_hairstyles) // if new style selected (not cancel) if(new_style) M.change_hair(new_style) var/new_hair = input("Please select hair color.", "Character Generation", head_organ.hair_colour) as null|color if(new_hair) M.change_hair_color(new_hair) var/datum/sprite_accessory/hair_style = GLOB.hair_styles_public_list[head_organ.h_style] if(hair_style.secondary_theme && !hair_style.no_sec_colour) new_hair = input("Please select secondary hair color.", "Character Generation", head_organ.sec_hair_colour) as null|color if(new_hair) M.change_hair_color(new_hair, TRUE) // facial hair var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles() new_style = tgui_input_list(user, "Please select facial style", "Character Generation", valid_facial_hairstyles) if(new_style) M.change_facial_hair(new_style) var/new_facial = input("Please select facial hair color.", "Character Generation", head_organ.facial_colour) as null|color if(new_facial) M.change_facial_hair_color(new_facial) var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[head_organ.f_style] if(facial_hair_style.secondary_theme && !facial_hair_style.no_sec_colour) new_facial = input("Please select secondary facial hair color.", "Character Generation", head_organ.sec_facial_colour) as null|color if(new_facial) M.change_facial_hair_color(new_facial, TRUE) //Head accessory. if(head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) var/list/valid_head_accessories = M.generate_valid_head_accessories() var/new_head_accessory = tgui_input_list(user, "Please select head accessory style", "Character Generation", valid_head_accessories) if(new_head_accessory) M.change_head_accessory(new_head_accessory) var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", head_organ.headacc_colour) as null|color if(new_head_accessory_colour) M.change_head_accessory_color(new_head_accessory_colour) //Body accessory. if((M.dna.species.tail && M.dna.species.bodyflags & (HAS_TAIL)) || (M.dna.species.wing && M.dna.species.bodyflags & (HAS_WING))) var/list/valid_body_accessories = M.generate_valid_body_accessories() if(length(valid_body_accessories) > 1) //By default valid_body_accessories will always have at the very least a 'none' entry populating the list, even if the user's species is not present in any of the list items. var/new_body_accessory = tgui_input_list(user, "Please select body accessory style", "Character Generation", valid_body_accessories) if(new_body_accessory) M.change_body_accessory(new_body_accessory) if(istype(head_organ)) //Head markings. if(M.dna.species.bodyflags & HAS_HEAD_MARKINGS) var/list/valid_head_markings = M.generate_valid_markings("head") var/new_marking = tgui_input_list(user, "Please select head marking style", "Character Generation", valid_head_markings) if(new_marking) M.change_markings(new_marking, "head") var/new_marking_colour = input("Please select head marking colour.", "Character Generation", M.m_colours["head"]) as null|color if(new_marking_colour) M.change_marking_color(new_marking_colour, "head") //Body markings. if(M.dna.species.bodyflags & HAS_BODY_MARKINGS) var/list/valid_body_markings = M.generate_valid_markings("body") var/new_marking = tgui_input_list(user, "Please select body marking style", "Character Generation", valid_body_markings) if(new_marking) M.change_markings(new_marking, "body") var/new_marking_colour = input("Please select body marking colour.", "Character Generation", M.m_colours["body"]) as null|color if(new_marking_colour) M.change_marking_color(new_marking_colour, "body") //Tail markings. if(M.dna.species.bodyflags & HAS_TAIL_MARKINGS) var/list/valid_tail_markings = M.generate_valid_markings("tail") var/new_marking = tgui_input_list("Please select tail marking style", "Character Generation", valid_tail_markings) if(new_marking) M.change_markings(new_marking, "tail") var/new_marking_colour = input("Please select tail marking colour.", "Character Generation", M.m_colours["tail"]) as null|color if(new_marking_colour) M.change_marking_color(new_marking_colour, "tail") //Skin tone. if(M.dna.species.bodyflags & HAS_SKIN_TONE) var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", M.s_tone) as null|text if(!new_tone) new_tone = 35 else new_tone = 35 - max(min(round(text2num(new_tone)), 220), 1) M.change_skin_tone(new_tone) if(M.dna.species.bodyflags & HAS_ICON_SKIN_TONE) var/prompt = "Please select skin tone: 1-[length(M.dna.species.icon_skin_tones)] (" for(var/i = 1 to length(M.dna.species.icon_skin_tones)) prompt += "[i] = [M.dna.species.icon_skin_tones[i]]" if(i != length(M.dna.species.icon_skin_tones)) prompt += ", " prompt += ")" var/new_tone = input(prompt, "Character Generation", M.s_tone) as null|text if(!new_tone) new_tone = 0 else new_tone = max(min(round(text2num(new_tone)), length(M.dna.species.icon_skin_tones)), 1) M.change_skin_tone(new_tone) //Skin colour. if(M.dna.species.bodyflags & HAS_SKIN_COLOR) var/new_body_colour = input("Please select body colour.", "Character Generation", M.skin_colour) as null|color if(new_body_colour) M.change_skin_color(new_body_colour) M.update_dna() M.visible_message("[M] morphs and changes [M.p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") /datum/mutation/grant_spell/remotetalk name = "Telepathy" activation_messages = list("You feel you can project your thoughts.") deactivation_messages = list("You no longer feel you can project your thoughts.") instability = GENE_INSTABILITY_MINOR spelltype =/datum/spell/remotetalk /datum/mutation/grant_spell/remotetalk/New() ..() block = GLOB.remotetalkblock /datum/mutation/grant_spell/remotetalk/activate(mob/living/M) ..() M.AddSpell(new /datum/spell/mindscan(null)) /datum/mutation/grant_spell/remotetalk/deactivate(mob/user) ..() for(var/datum/spell/S in user.mob_spell_list) if(istype(S, /datum/spell/mindscan)) user.RemoveSpell(S) /datum/spell/remotetalk name = "Project Mind" desc = "Make people understand your thoughts!" base_cooldown = 0 clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_project" /datum/spell/remotetalk/create_new_targeting() return new /datum/spell_targeting/telepathic /datum/spell/remotetalk/cast(list/targets, mob/user = usr) if(!ishuman(user)) return if(user.mind?.miming) // Dont let mimes telepathically talk to_chat(user,"You can't communicate without breaking your vow of silence.") return var/say = tgui_input_text(user, "What do you wish to say?", "Project Mind") if(!say || usr.stat) return say = pencode_to_html(say, usr, format = FALSE, fields = FALSE) for(var/mob/living/target in targets) log_say("(TPATH to [key_name(target)]) [say]", user) user.create_log(SAY_LOG, "Telepathically said '[say]' using [src]", target) if(target.dna?.GetSEState(GLOB.remotetalkblock)) target.show_message("You hear [user.real_name]'s voice: [say]") else target.show_message("You hear a voice that seems to echo around the room: [say]") user.show_message("You project your mind into [(target in user.get_visible_mobs()) ? target.name : "the unknown entity"]: [say]") for(var/mob/dead/observer/G in GLOB.player_list) G.show_message("Telepathic message from [user] ([ghost_follow_link(user, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]") /datum/spell/mindscan name = "Scan Mind" desc = "Offer people a chance to share their thoughts!" base_cooldown = 0 clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_mindscan" var/list/expanded_minds = list() /datum/spell/mindscan/create_new_targeting() return new /datum/spell_targeting/telepathic /datum/spell/mindscan/cast(list/targets, mob/user = usr) if(!ishuman(user)) return for(var/mob/living/target in targets) var/message = "You feel your mind expand briefly... (Click to send a message.)" if(target.dna?.GetSEState(GLOB.remotetalkblock)) message = "You feel [user.real_name] request a response from you... (Click here to project mind.)" user.show_message("You offer your mind to [(target in user.get_visible_mobs()) ? target.name : "the unknown entity"].") target.show_message("[message]") expanded_minds += target addtimer(CALLBACK(src, PROC_REF(removeAvailability), target), 10 SECONDS) /datum/spell/mindscan/proc/removeAvailability(mob/living/target) if(target in expanded_minds) expanded_minds -= target if(!(target in expanded_minds)) target.show_message("You feel the sensation fade...") /datum/spell/mindscan/Topic(href, href_list) var/mob/living/message_source message_source = locateUID(href_list["from"]) if(!message_source) return if(!message_source || !(message_source in expanded_minds)) return expanded_minds -= message_source var/mob/living/message_target = locateUID(href_list["to"]) if(!message_target) return var/say = tgui_input_text(message_source, "What do you wish to say?", "Expanded Mind") if(!say) return say = pencode_to_html(say, message_source, format = FALSE, fields = FALSE) message_source.create_log(SAY_LOG, "Telepathically responded '[say]' using [src]", message_target) log_say("(TPATH to [key_name(message_target)]) [say]", message_source) if(message_source.dna?.GetSEState(GLOB.remotetalkblock)) message_source.show_message("You project your mind into [message_target]: [say]") else message_source.show_message("You fill the space in your thoughts: [say]") message_target.show_message("You hear [message_source]'s voice: [say]") for(var/mob/dead/observer/G in GLOB.player_list) G.show_message("Telepathic response from [message_source] ([ghost_follow_link(message_source, ghost=G)]) to [message_target] ([ghost_follow_link(message_target, ghost=G)]): [say]") /datum/spell/mindscan/Destroy() expanded_minds.Cut() return ..() /datum/mutation/grant_spell/remoteview name = "Remote Viewing" activation_messages = list("Your mind can see things from afar.") deactivation_messages = list("Your mind can no longer can see things from afar.") instability = GENE_INSTABILITY_MINOR spelltype =/datum/spell/remoteview /datum/mutation/grant_spell/remoteview/New() ..() block = GLOB.remoteviewblock /datum/mutation/grant_spell/remoteview/deactivate(mob/user) . = ..() if(ishuman(user)) var/mob/living/carbon/human/H = user H.remoteview_target = null H.reset_perspective() /datum/spell/remoteview name = "Remote View" desc = "Spy on people from any range!" base_cooldown = 10 SECONDS clothes_req = FALSE stat_allowed = CONSCIOUS invocation_type = "none" action_icon_state = "genetic_view" /datum/spell/remoteview/create_new_targeting() return new /datum/spell_targeting/remoteview /datum/spell/remoteview/cast(list/targets, mob/user = usr) var/mob/living/carbon/human/H if(ishuman(user)) H = user else return var/mob/target if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab)) to_chat(H, "Your mind is too busy with that telekinetic grab.") H.remoteview_target = null H.reset_perspective() return if(H.client.eye != user.client.mob) H.remoteview_target = null H.reset_perspective() return for(var/mob/living/L in targets) target = L if(target) H.remoteview_target = target H.reset_perspective(target) else H.remoteview_target = null H.reset_perspective() /datum/mutation/meson_vision name = "Meson Vision" activation_messages = list("More information seems to reach your eyes...") deactivation_messages = list("The amount of information reaching your eyes fades...") instability = GENE_INSTABILITY_MINOR traits_to_add = list(TRAIT_MESON_VISION) /datum/mutation/meson_vision/New() ..() block = GLOB.mesonblock /datum/mutation/meson_vision/activate(mob/living/M) ..() M.update_sight() /datum/mutation/meson_vision/deactivate(mob/living/M) ..() M.update_sight() /datum/mutation/night_vision name = "Night Vision" activation_messages = list("Were the lights always that bright?") deactivation_messages = list("The ambient light level returns to normal...") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_NIGHT_VISION) /datum/mutation/night_vision/New() ..() block = GLOB.nightvisionblock /datum/mutation/night_vision/activate(mob/living/M) ..() M.update_sight() if(ishuman(M)) var/mob/living/carbon/human/H = M H.update_misc_effects() /datum/mutation/night_vision/deactivate(mob/living/M) ..() M.update_sight() if(ishuman(M)) var/mob/living/carbon/human/H = M H.update_misc_effects() /datum/mutation/flash_protection name = "Flash Protection" activation_messages = list("You stop noticing the glare from lights...") deactivation_messages = list("Lights begin glaring again...") instability = GENE_INSTABILITY_MODERATE traits_to_add = list(TRAIT_FLASH_PROTECTION) /datum/mutation/flash_protection/New() ..() block = GLOB.noflashblock #undef EAT_MOB_DELAY