From fd217ec7739285c166b6a3aa86c046c63f67355d Mon Sep 17 00:00:00 2001 From: Alberyk Date: Sun, 5 Mar 2017 17:05:27 -0300 Subject: [PATCH] Changeling updates and fix (#1765) - Fixes #1660 -re-added old code changeling features, like non-stealthy sting and arm blades, with proper sprites this time, and shields -changeling revive will now be only triggered when the ling wants to come back -lings can't ling monkeys anymore -fixed ipcs being affected by stings -removed species transformation skill, now, using transform will turn you also into said species --- baystation12.dme | 1 + .../gamemodes/changeling/changeling_items.dm | 91 +++++ .../gamemodes/changeling/changeling_powers.dm | 314 ++++++++++-------- .../gamemodes/changeling/modularchangling.dm | 26 +- html/changelogs/alberyk-PR-1765.yml | 12 + icons/obj/changeling.dmi | Bin 0 -> 15137 bytes 6 files changed, 297 insertions(+), 147 deletions(-) create mode 100644 code/game/gamemodes/changeling/changeling_items.dm create mode 100644 html/changelogs/alberyk-PR-1765.yml create mode 100644 icons/obj/changeling.dmi diff --git a/baystation12.dme b/baystation12.dme index 829a6030dba..024b5731acc 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -334,6 +334,7 @@ #include "code\game\gamemodes\setupgame.dm" #include "code\game\gamemodes\calamity\calamity.dm" #include "code\game\gamemodes\changeling\changeling.dm" +#include "code\game\gamemodes\changeling\changeling_items.dm" #include "code\game\gamemodes\changeling\changeling_powers.dm" #include "code\game\gamemodes\changeling\modularchangling.dm" #include "code\game\gamemodes\cult\cult.dm" diff --git a/code/game/gamemodes/changeling/changeling_items.dm b/code/game/gamemodes/changeling/changeling_items.dm new file mode 100644 index 00000000000..cf27d5301ba --- /dev/null +++ b/code/game/gamemodes/changeling/changeling_items.dm @@ -0,0 +1,91 @@ +/obj/item/weapon/melee/arm_blade + name = "arm blade" + desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter." + icon = 'icons/obj/changeling.dmi' + icon_state = "arm_blade" + item_state = "arm_blade" + contained_sprite = 1 + w_class = 4 + force = 30 + sharp = 1 + edge = 1 + anchored = 1 + throwforce = 0 //Just to be on the safe side + throw_range = 0 + throw_speed = 0 + can_embed = 0 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + var/mob/living/creator + +/obj/item/weapon/melee/arm_blade/New() + processing_objects |= src + +/obj/item/weapon/melee/arm_blade/Destroy() + processing_objects -= src + ..() + +/obj/item/weapon/melee/arm_blade/dropped() + visible_message("With a sickening crunch, [user] reforms their arm blade into an arm!", + "We assimilate the weapon back into our body.", + "You hear organic matter ripping and tearing!") + playsound(loc, 'sound/effects/blobattack.ogg', 30, 1) + spawn(1) if(src) qdel(src) + +/obj/item/weapon/melee/arm_blade/process() + if(!creator || loc != creator || (creator.l_hand != src && creator.r_hand != src)) + // Tidy up a bit. + if(istype(loc,/mob/living)) + var/mob/living/carbon/human/host = loc + if(istype(host)) + for(var/obj/item/organ/external/organ in host.organs) + for(var/obj/item/O in organ.implants) + if(O == src) + organ.implants -= src + host.pinned -= src + host.embedded -= src + host.drop_from_inventory(src) + spawn(1) if(src) qdel(src) + +/obj/item/weapon/shield/riot/changeling + name = "shield-like mass" + desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield." + icon = 'icons/obj/changeling.dmi' + icon_state = "ling_shield" + item_state = "ling_shield" + contained_sprite = 1 + slot_flags = null + anchored = 1 + throwforce = 0 //Just to be on the safe side + throw_range = 0 + throw_speed = 0 + can_embed = 0 + var/mob/living/creator + +/obj/item/weapon/shield/riot/changeling/New() + processing_objects |= src + +/obj/item/weapon/shield/riot/changeling/Destroy() + processing_objects -= src + ..() + +/obj/item/weapon/shield/riot/changeling/dropped() + visible_message("With a sickening crunch, [user] reforms their arm blade into an arm!", + "We assimilate the weapon back into our body.", + "You hear organic matter ripping and tearing!") + playsound(loc, 'sound/effects/blobattack.ogg', 30, 1) + spawn(1) if(src) qdel(src) + +/obj/item/weapon/shield/riot/changeling/process() + if(!creator || loc != creator || (creator.l_hand != src && creator.r_hand != src)) + // Tidy up a bit. + if(istype(loc,/mob/living)) + var/mob/living/carbon/human/host = loc + if(istype(host)) + for(var/obj/item/organ/external/organ in host.organs) + for(var/obj/item/O in organ.implants) + if(O == src) + organ.implants -= src + host.pinned -= src + host.embedded -= src + host.drop_from_inventory(src) + spawn(1) if(src) qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index eb3a092a03c..f57322c47a1 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,8 +1,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") /datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind) - var/list/absorbed_dna = list() - var/list/absorbed_species = list() + var/list/datum/absorbed_dna/absorbed_dna = list() var/list/absorbed_languages = list() var/absorbedcount = 0 var/chem_charges = 20 @@ -31,12 +30,24 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E geneticdamage = max(0, geneticdamage-1) /datum/changeling/proc/GetDNA(var/dna_owner) - var/datum/dna/chosen_dna - for(var/datum/dna/DNA in absorbed_dna) - if(dna_owner == DNA.real_name) - chosen_dna = DNA - break - return chosen_dna + for(var/datum/absorbed_dna/DNA in absorbed_dna) + if(dna_owner == DNA.name) + return DNA + +/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA) + var/datum/changeling/changeling = null + if(src.mind && src.mind.changeling) + changeling = src.mind.changeling + if(!changeling) + return + + for(var/language in newDNA.languages) + changeling.absorbed_languages |= language + + changeling_update_languages(changeling.absorbed_languages) + + if(!changeling.GetDNA(newDNA.name)) // Don't duplicate - I wonder if it's possible for it to still be a different DNA? DNA code could use a rewrite + changeling.absorbed_dna += newDNA //Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human /mob/proc/make_changeling() @@ -65,14 +76,13 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E if(!(P in src.verbs)) src.verbs += P.verbpath - mind.changeling.absorbed_dna |= dna + for(var/language in languages) + mind.changeling.absorbed_languages |= language var/mob/living/carbon/human/H = src if(istype(H)) - mind.changeling.absorbed_species += H.species.name - - for(var/language in languages) - mind.changeling.absorbed_languages |= language + var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages) + absorbDNA(newDNA) return 1 @@ -83,13 +93,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E if(P.isVerb) verbs -= P.verbpath -//removes changeling powers but keeps those with allowduringlesserform -/mob/proc/remove_changeling_powers_monkey() - if(!mind || !mind.changeling) return - for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) - if(P.isVerb && (P.allowduringlesserform == 0)) - verbs -= P.verbpath - //Helper proc. Does all the checks and stuff for us to avoid copypasta /mob/proc/changeling_power(var/required_chems=0, var/required_dna=0, var/max_genetic_damage=100, var/max_stat=0) @@ -133,46 +136,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E return -//Used to switch species based on the changeling datum. -/mob/proc/changeling_change_species() - - set category = "Changeling" - set name = "Change Species (5)" - - var/mob/living/carbon/human/H = src - if(!istype(H)) - src << "We may only use this power while in humanoid form." - return - - var/datum/changeling/changeling = changeling_power(5,1,0) - if(!changeling) return - - if(changeling.absorbed_species.len < 2) - src << "We do not know of any other species genomes to use." - return - - var/S = input("Select the target species: ", "Target Species", null) as null|anything in changeling.absorbed_species - if(!S) return - - domutcheck(src, null) - - changeling.chem_charges -= 5 - changeling.geneticdamage = 30 - - src.visible_message("[src] transforms!") - - src.verbs -= /mob/proc/changeling_change_species - H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default. - - spawn(10) - src.verbs += /mob/proc/changeling_change_species - src.regenerate_icons() - - changeling_update_languages(changeling.absorbed_languages) - feedback_add_details("changeling_powers","TR") - - return 1 - //Absorbs the victim's DNA making them uncloneable. Requires a strong grip on the victim. //Doesn't cost anything as it's the most basic ability. /mob/proc/changeling_absorb_dna() @@ -196,6 +159,10 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E src << "We do not know how to parse this creature's DNA!" return + if(islesserform(T)) + src << "This creature DNA is not compatible with our form!" + return + if(HUSK in T.mutations) src << "This creature's DNA is ruined beyond useability!" return @@ -213,6 +180,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E switch(stage) if(1) src << "This creature is compatible. We must hold still..." + src.visible_message("[src]'s skin begins to shift and squirm!") if(2) src << "We extend a proboscis." src.visible_message("[src] extends a proboscis!") @@ -234,9 +202,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E src.visible_message("[src] sucks the fluids from [T]!") T << "You have been absorbed by the changeling!" - T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. - changeling.absorbed_dna |= T.dna - if(src.nutrition < max_nutrition) src.nutrition = min((nutrition + T.nutrition), max_nutrition) changeling.chem_charges += 10 changeling.geneticpoints += 2 @@ -247,16 +212,15 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E changeling_update_languages(changeling.absorbed_languages) - //Steal their species! - if(T.species && !(T.species.name in changeling.absorbed_species)) - changeling.absorbed_species += T.species.name + var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages) + absorbDNA(newDNA) if(T.mind && T.mind.changeling) if(T.mind.changeling.absorbed_dna) - for(var/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot - if(dna_data in changeling.absorbed_dna) + for(var/datum/absorbed_dna/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot + if(changeling.GetDNA(dna_data.name)) continue - changeling.absorbed_dna += dna_data + absorbDNA(dna_data) changeling.absorbedcount++ T.mind.changeling.absorbed_dna.len = 1 @@ -295,31 +259,44 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E if(!changeling) return var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_name]" + for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) + names += "[DNA.name]" var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names if(!S) return - var/datum/dna/chosen_dna = changeling.GetDNA(S) + var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S) if(!chosen_dna) return changeling.chem_charges -= 5 - src.visible_message("[src] transforms!") changeling.geneticdamage = 30 - src.dna = chosen_dna.Clone() - src.real_name = chosen_dna.real_name - src.flavor_text = "" - src.UpdateAppearance() - domutcheck(src, null) + + handle_changeling_transform(chosen_dna) src.verbs -= /mob/proc/changeling_transform - spawn(10) src.verbs += /mob/proc/changeling_transform + spawn(10) + src.verbs += /mob/proc/changeling_transform + + changeling_update_languages(changeling.absorbed_languages) feedback_add_details("changeling_powers","TR") return 1 +/mob/proc/handle_changeling_transform(var/datum/absorbed_dna/chosen_dna) + src.visible_message("[src] transforms!") + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + var/newSpecies = chosen_dna.speciesName + H.set_species(newSpecies,1) + + src.dna = chosen_dna.dna + src.real_name = chosen_dna.name + src.flavor_text = "" + domutcheck(src, null) + src.UpdateAppearance() + //Transform into a monkey. /mob/proc/changeling_lesser_form() @@ -340,15 +317,10 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E return changeling.chem_charges-- - H.remove_changeling_powers_monkey() //we weren't making us of allowduringlesserform before for some reason? -Ryan784 H.visible_message("[H] transforms!") changeling.geneticdamage = 30 H << "Our genes cry out!" - var/list/implants = list() //Try to preserve implants. - for(var/obj/item/weapon/implant/W in H) - implants += W - H.monkeyize() - verbs += /mob/proc/changeling_lesser_transform //allow us to actually transform BACK into a human - Ryan784 + H = H.monkeyize() feedback_add_details("changeling_powers","LF") return 1 @@ -457,25 +429,29 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E // charge the changeling chemical cost for stasis changeling.chem_charges -= 20 - // restore us to health - C.revive() - - // remove our fake death flag - C.status_flags &= ~(FAKEDEATH) - - // let us move again - C.update_canmove() - - // re-add out changeling powers - C.make_changeling() - - // sending display messages - C << "We have regenerated." - + C << "We are ready to rise. Use the Revive verb when you are ready." + C.verbs += /mob/proc/changeling_revive feedback_add_details("changeling_powers","FD") return 1 +/mob/proc/changeling_revive() + set category = "Changeling" + set name = "Revive" + + var/mob/living/carbon/C = src + // restore us to health + C.revive() + // remove our fake death flag + C.status_flags &= ~(FAKEDEATH) + // let us move again + C.update_canmove() + // re-add out changeling powers + C.make_changeling() + // sending display messages + C << "We have regenerated." + C.verbs -= /mob/proc/changeling_revive + //Boosts the range of your next sting attack by 1 /mob/proc/changeling_boost_range() @@ -581,7 +557,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E // HIVE MIND UPLOAD/DOWNLOAD DNA -var/list/datum/dna/hivemind_bank = list() +var/list/datum/absorbed_dna/hivemind_bank = list() /mob/proc/changeling_hiveupload() set category = "Changeling" @@ -592,9 +568,14 @@ var/list/datum/dna/hivemind_bank = list() if(!changeling) return var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - if(!(DNA in hivemind_bank)) - names += DNA.real_name + for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) + var/valid = 1 + for(var/datum/absorbed_dna/DNB in hivemind_bank) + if(DNA.name == DNB.name) + valid = 0 + break + if(valid) + names += DNA.name if(names.len <= 0) src << "The airwaves already have all of our DNA." @@ -603,7 +584,7 @@ var/list/datum/dna/hivemind_bank = list() var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names if(!S) return - var/datum/dna/chosen_dna = changeling.GetDNA(S) + var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S) if(!chosen_dna) return @@ -622,9 +603,9 @@ var/list/datum/dna/hivemind_bank = list() if(!changeling) return var/list/names = list() - for(var/datum/dna/DNA in hivemind_bank) - if(!(DNA in changeling.absorbed_dna)) - names[DNA.real_name] = DNA + for(var/datum/absorbed_dna/DNA in hivemind_bank) + if(!(changeling.GetDNA(DNA.name))) + names[DNA.name] = DNA if(names.len <= 0) src << "There's no new DNA to absorb from the air." @@ -637,7 +618,7 @@ var/list/datum/dna/hivemind_bank = list() return changeling.chem_charges -= 20 - changeling.absorbed_dna += chosen_dna + absorbDNA(chosen_dna) src << "We absorb the DNA of [S] from the air." feedback_add_details("changeling_powers","HD") return 1 @@ -692,7 +673,7 @@ var/list/datum/dna/hivemind_bank = list() return 1 //Handles the general sting code to reduce on copypasta (seeming as somebody decided to make SO MANY dumb abilities) -/mob/proc/changeling_sting(var/required_chems=0, var/verb_path) +/mob/proc/changeling_sting(var/required_chems=0, var/verb_path, var/stealthy = 0) var/datum/changeling/changeling = changeling_power(required_chems) if(!changeling) return @@ -711,9 +692,20 @@ var/list/datum/dna/hivemind_bank = list() src.verbs -= verb_path spawn(10) src.verbs += verb_path - src << "We stealthily sting [T]." + if(stealthy == 1) + src << "We stealthily sting [T]." + T << "You feel a tiny prick." + else + src.visible_message(pick("[src]'s eyes balloon and burst out in a welter of blood, burrowing into [T]!", + "[src]'s arm rapidly shifts into a giant scorpion-stinger and stabs into [T]!", + "[src]'s throat lengthens and twists before vomitting a chunky red spew all over [T]!", + "[src]'s tongue stretches an impossible length and stabs into [T]!", + "[src] sneezes a cloud of shrieking spiders at [T]!", + "[src] erupts a grotesque tail and impales [T]!", + "[src]'s chin skin bulges and tears, launching a bone-dart at [T]!")) + if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting - T << "You feel a tiny prick." + return @@ -722,7 +714,7 @@ var/list/datum/dna/hivemind_bank = list() set name = "Hallucination Sting (15)" set desc = "Causes terror in the target." - var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting) + var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting,stealthy = 1) if(!T) return 0 spawn(rand(300,600)) if(T) T.hallucination += 400 @@ -734,7 +726,7 @@ var/list/datum/dna/hivemind_bank = list() set name = "Silence sting (10)" set desc="Sting target" - var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting) + var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting,stealthy = 1) if(!T) return 0 T.silent += 30 feedback_add_details("changeling_powers","SS") @@ -745,7 +737,7 @@ var/list/datum/dna/hivemind_bank = list() set name = "Blind sting (20)" set desc="Sting target" - var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting) + var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting,stealthy = 0) if(!T) return 0 T << "Your eyes burn horrificly!" T.disabilities |= NEARSIGHTED @@ -760,7 +752,7 @@ var/list/datum/dna/hivemind_bank = list() set name = "Deaf sting (5)" set desc="Sting target:" - var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) + var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting,stealthy = 0) if(!T) return 0 T << "Your ears pop and begin ringing loudly!" T.sdisabilities |= DEAF @@ -773,7 +765,7 @@ var/list/datum/dna/hivemind_bank = list() set name = "Paralysis sting (30)" set desc="Sting target" - var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting) + var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting,stealthy = 0) if(!T) return 0 T << "Your muscles begin to painfully tighten." T.Weaken(20) @@ -788,29 +780,25 @@ var/list/datum/dna/hivemind_bank = list() var/datum/changeling/changeling = changeling_power(40) if(!changeling) return 0 - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_name]" + for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) + names += "[DNA.name]" var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names if(!S) return - var/datum/dna/chosen_dna = changeling.GetDNA(S) + var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S) if(!chosen_dna) return - var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting) + var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting,stealthy = 1) if(!T) return 0 if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T))) src << "Our sting appears ineffective against its DNA." return 0 - T.visible_message("[T] transforms!") - T.dna = chosen_dna.Clone() - T.real_name = chosen_dna.real_name - T.UpdateAppearance() - domutcheck(T, null) + + T.handle_changeling_transform(chosen_dna) + feedback_add_details("changeling_powers","TS") return 1 @@ -819,10 +807,9 @@ var/list/datum/dna/hivemind_bank = list() set name = "Unfat sting (5)" set desc = "Sting target" - var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting) + var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting,stealthy = 1) if(!T) return 0 T << "you feel a small prick as stomach churns violently and you become to feel skinnier." - T.overeatduration = 0 T.nutrition -= 100 feedback_add_details("changeling_powers","US") return 1 @@ -832,13 +819,13 @@ var/list/datum/dna/hivemind_bank = list() set name = "Death Sting (40)" set desc = "Causes spasms onto death." - var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting) + var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting,stealthy = 0) if(!T) return 0 T << "You feel a small prick and your chest becomes tight." T.silent = 10 T.Paralyse(10) T.make_jittery(1000) - if(T.reagents) T.reagents.add_reagent("lexorin", 40) + if(T.reagents) T.reagents.add_reagent("cyanide", 5) feedback_add_details("changeling_powers","DTHS") return 1 @@ -853,13 +840,66 @@ var/list/datum/dna/hivemind_bank = list() if(!changeling) return 0 - var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) + var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting,stealthy = 1) if(!T) return 0 - T.dna.real_name = T.real_name - changeling.absorbed_dna |= T.dna - if(T.species && !(T.species.name in changeling.absorbed_species)) - changeling.absorbed_species += T.species.name + var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages) + absorbDNA(newDNA) feedback_add_details("changeling_powers","ED") return 1 + +/mob/proc/armblades() + set category = "Changeling" + set name = "Form Blades" + set desc="Rupture the flesh and mend the bone of your hand into a deadly blade." + + var/mob/living/M = src + + if(M.l_hand && M.r_hand) + M << "Your hands are full." + return + + var/obj/item/weapon/melee/arm_blade/blade = new(M) + blade.creator = M + M.put_in_hands(blade) + playsound(loc, 'sound/effects/blobattack.ogg', 30, 1) + src.visible_message("A grotesque blade forms around [M]\'s arm!", + "Our arm twists and mutates, transforming it into a deadly blade.", + "You hear organic matter ripping and tearing!") + gibs(src.loc) + +/mob/proc/changeling_shield() + set category = "Changeling" + set name = "Form Shield" + set desc="Bend the flesh and bone of your hand into a grotesque shield." + + var/mob/living/M = src + + if(M.l_hand && M.r_hand) + M << "Your hands are full." + return + + var/obj/item/weapon/shield/riot/changeling/shield = new(M) + shield.creator = M + M.put_in_hands(shield) + playsound(loc, 'sound/effects/blobattack.ogg', 30, 1) + src.visible_message("The end of [M]\'s hand inflates rapidly, forming a huge shield-like mass!", + "We inflate our hand into a robust shield.", + "You hear organic matter ripping and tearing!") + gibs(src.loc) + +//dna related datum + +/datum/absorbed_dna + var/name + var/datum/dna/dna + var/speciesName + var/list/languages + +/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages) + ..() + name = newName + dna = newDNA + speciesName = newSpecies + languages = newLanguages diff --git a/code/game/gamemodes/changeling/modularchangling.dm b/code/game/gamemodes/changeling/modularchangling.dm index 7ba0052b816..303016281a2 100644 --- a/code/game/gamemodes/changeling/modularchangling.dm +++ b/code/game/gamemodes/changeling/modularchangling.dm @@ -26,12 +26,6 @@ var/list/datum/power/changeling/powerinstances = list() genomecost = 0 verbpath = /mob/proc/changeling_transform -/datum/power/changeling/change_species - name = "Change Species" - desc = "We take on the apperance of a species that we have absorbed." - genomecost = 0 - verbpath = /mob/proc/changeling_change_species - /datum/power/changeling/fakedeath name = "Regenerative Stasis" desc = "We become weakened to a death-like state, where we will rise again from death." @@ -64,14 +58,14 @@ var/list/datum/power/changeling/powerinstances = list() /datum/power/changeling/deaf_sting name = "Deaf Sting" - desc = "We silently sting a human, completely deafening them for a short time." + desc = "We sting a human, completely deafening them for a short time." genomecost = 1 allowduringlesserform = 1 verbpath = /mob/proc/changeling_deaf_sting /datum/power/changeling/blind_sting name = "Blind Sting" - desc = "We silently sting a human, completely blinding them for a short time." + desc = "We sting a human, completely blinding them for a short time." genomecost = 2 allowduringlesserform = 1 verbpath = /mob/proc/changeling_blind_sting @@ -108,7 +102,7 @@ var/list/datum/power/changeling/powerinstances = list() /datum/power/changeling/paralysis_sting name = "Paralysis Sting" - desc = "We silently sting a human, paralyzing them for a short time." + desc = "We sting a human, paralyzing them for a short time." genomecost = 8 verbpath = /mob/proc/changeling_paralysis_sting @@ -121,7 +115,7 @@ var/list/datum/power/changeling/powerinstances = list() /datum/power/changeling/DeathSting name = "Death Sting" - desc = "We silently sting a human, filling them with potent chemicals. Their rapid death is all but assured." + desc = "We sting a human, filling them with potent chemicals. Their rapid death is all but assured." genomecost = 10 verbpath = /mob/proc/changeling_DEATHsting @@ -184,7 +178,19 @@ var/list/datum/power/changeling/powerinstances = list() genomecost = 7 verbpath = /mob/proc/changeling_rapidregen +//weapon and armor like powers +/datum/power/changeling/armblades + name = "Mutate Armblades" + desc = "Permits us to reshape our arms into a deadly blade." + genomecost = 2 + verbpath = /mob/proc/armblades + +/datum/power/changeling/shield + name = "Mutate Shield" + desc = "Permits us to bloat our hands into a robust shield." + genomecost = 3 + verbpath = /mob/proc/changeling_shield // Modularchangling, totally stolen from the new player panel. YAYY /datum/changeling/proc/EvolutionMenu()//The new one diff --git a/html/changelogs/alberyk-PR-1765.yml b/html/changelogs/alberyk-PR-1765.yml new file mode 100644 index 00000000000..5af08198159 --- /dev/null +++ b/html/changelogs/alberyk-PR-1765.yml @@ -0,0 +1,12 @@ +author: Alberyk + +delete-after: True + +changes: + - rscadd: "Added arm blades and arm shields abilities to changelings." + - rscadd: "Added visible messages to certain lings stings." + - tweak: "Changelings can now select when getting up after using their regeneration skill." + - tweak: "Changeling transform will now change to the species of the selected dna, replacing change species." + - tweak: "Changelings can't absorb monkeys anymore." + - bugfix: "Fixed organ rejection caused by ling transformation." + - bugfix: "Fixed changeling stings affecting ipcs." diff --git a/icons/obj/changeling.dmi b/icons/obj/changeling.dmi new file mode 100644 index 0000000000000000000000000000000000000000..15f0e3a947550ad6cf044306209b0861a9ff484a GIT binary patch literal 15137 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