diff --git a/code/game/gamemodes/changeling/HelpCode.dm b/code/game/gamemodes/changeling/HelpCode.dm new file mode 100644 index 0000000..10d1c03 --- /dev/null +++ b/code/game/gamemodes/changeling/HelpCode.dm @@ -0,0 +1,7 @@ +/mob/living/proc/set_m_intent(var/intent) + if (intent != "walk" && intent != "run") + return 0 + m_intent = intent + if(hud_used) + if (hud_used.move_intent) + hud_used.move_intent.icon_state = intent == "walk" ? "walking" : "running" \ No newline at end of file diff --git a/code/game/gamemodes/changeling/Infecting.dm b/code/game/gamemodes/changeling/Infecting.dm new file mode 100644 index 0000000..575d9e6 --- /dev/null +++ b/code/game/gamemodes/changeling/Infecting.dm @@ -0,0 +1,88 @@ +// Checks whether or not the target can be affected by a vampire's abilities. +/mob/proc/vampire_can_affect_target(var/mob/living/carbon/human/T, var/notify = 1, var/account_loyalty_implant = 0) + if (!T || !istype(T)) + return 0 + + if (T.isSynthetic()) + if (notify) + to_chat(src, "You lack the power interact with mechanical constructs.") + return 0 + + return 1 + + +/mob/living/carbon/human/proc/finish_chang_timeout(chang_flags = 0) + if (!usr.mind || !usr.mind.changeling) + return FALSE + + if (chang_flags && !(usr.mind.changeling & chang_flags)) + return FALSE + + return TRUE +///////////////// +///////////////// +///////Helpcode deadphil////////// + +/proc/infect_mob(var/mob/living/carbon/M, var/datum/disease2/disease/D) + infect_virus2(M,D,1) + M.hud_updateflag |= 1 << STATUS_HUD + + + + +///////////////////////////////////////////////////////////////// + +// Gives a lethal disease to the target. +/datum/power/changeling/Infection + name = "Infection" + desc = "We can produce dangerous viral diseases in our bodies." + helptext = "Touch the victim and it will be infected." + enhancedtext = "We produce a powerful virus, capable of killing the victim in the shortest possible time." +// ability_icon_state = "ling_camoflage" + genomecost = 6 + verbpath = /mob/proc/Infection + + +/mob/proc/Infection() + set category = "Changeling" + set name = "Infection (30)" + set desc = "Infects the victim with a dangerous virus that causes organ failure." + + var/datum/changeling/changeling = changeling_power(30,0,100,CONSCIOUS) + if (!changeling) + return 0 + + var/list/victims = list() + for (var/mob/living/carbon/human/H in view(1)) + if (H == src) + continue + victims += H + + if (!victims.len) + to_chat(src, "No suitable targets.") + return + + var/mob/living/carbon/human/T = input(src, "Select Victim") as null|mob in victims + + if (!vampire_can_affect_target(T)) + return + + to_chat(src, "You infect [T] with a deadly disease. They will soon fade away.") + + T.help_shake_act(src) + + var/datum/disease2/disease/lethal = new + lethal.makerandom(4) + lethal.infectionchance = 1 + lethal.stage = lethal.max_stage + lethal.spreadtype = "None" + + infect_mob(T, lethal) + + admin_attack_log(src, T, "used diseased touch on [key_name(T)]", "was given a lethal disease by [key_name(src)]", "used diseased touch (virus info) on") + + changeling.chem_charges -= 30 + +// verbs -= /mob/proc/Infection + +// ADD_VERB_IN_IF(src, 1800, /mob/proc/Infection, CALLBACK(src, .proc/finish_chang_timeout)) \ No newline at end of file diff --git a/code/game/gamemodes/changeling/absorbed_dna.dm b/code/game/gamemodes/changeling/absorbed_dna.dm index 2527f90..dc479d4 100644 --- a/code/game/gamemodes/changeling/absorbed_dna.dm +++ b/code/game/gamemodes/changeling/absorbed_dna.dm @@ -1,12 +1,12 @@ -/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 +/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/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index b201294..3e1f9a6 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,18 +1,18 @@ -/datum/game_mode/changeling - name = "Changeling" - round_description = "There are alien changelings onboard. Do not let the changelings succeed!" - extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. \ - Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet \ - something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, \ - however, is that this something is someone. An unknown alien specimen has incorporated itself into \ - the crew. Its unique biology allows it to manipulate its own or anyone else's DNA. \ - With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, \ - its existence is a threat to not only your personal safety but the lives of everyone on board. \ - No one knows where it came from. No one knows who it is or what it wants. One thing is for \ - certain though... there is never just one of them. Good luck." - config_tag = "changeling" - required_players = 2 - required_enemies = 1 - end_on_antag_death = 0 - antag_scaling_coeff = 10 - antag_tags = list(MODE_CHANGELING) +/datum/game_mode/changeling + name = "Changeling" + round_description = "There are alien changelings onboard. Do not let the changelings succeed!" + extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. \ + Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet \ + something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, \ + however, is that this something is someone. An unknown alien specimen has incorporated itself into \ + the crew. Its unique biology allows it to manipulate its own or anyone else's DNA. \ + With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, \ + its existence is a threat to not only your personal safety but the lives of everyone on board. \ + No one knows where it came from. No one knows who it is or what it wants. One thing is for \ + certain though... there is never just one of them. Good luck." + config_tag = "changeling" + required_players = 2 + required_enemies = 1 + end_on_antag_death = 0 + antag_scaling_coeff = 10 + antag_tags = list(MODE_CHANGELING) diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index eed5824..d49af8e 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,804 +1,810 @@ -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/datum/absorbed_dna/absorbed_dna = list() - var/list/absorbed_languages = list() - var/absorbedcount = 0 - var/chem_charges = 20 - var/chem_recharge_rate = 0.5 - var/chem_storage = 50 - var/sting_range = 1 - var/changelingID = "Changeling" - var/geneticdamage = 0 - var/isabsorbing = 0 - var/geneticpoints = 25 - var/purchasedpowers = list() - var/mimicing = "" - - -/datum/changeling/New() - ..() - if(possible_changeling_IDs.len) - changelingID = pick(possible_changeling_IDs) - possible_changeling_IDs -= changelingID - changelingID = "[changelingID]" - else - changelingID = "[rand(1,999)]" - -/datum/changeling/proc/regenerate() - chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage) - geneticdamage = max(0, geneticdamage-1) - -/datum/changeling/proc/GetDNA(var/dna_owner) - 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() - - if(!mind) return - if(!mind.changeling) mind.changeling = new /datum/changeling(gender) - - verbs += /datum/changeling/proc/EvolutionMenu - add_language("Changeling") - - var/lesser_form = !ishuman(src) - - if(!powerinstances.len) - for(var/P in powers) - powerinstances += new P() - - // Code to auto-purchase free powers. - for(var/datum/power/changeling/P in powerinstances) - if(!P.genomecost) // Is it free? - if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already? - mind.changeling.purchasePower(mind, P.name, 0)// Purchase it. Don't remake our verbs, we're doing it after this. - - for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) - if(P.isVerb) - if(lesser_form && !P.allowduringlesserform) continue - if(!(P in src.verbs)) - src.verbs += P.verbpath - - for(var/language in languages) - mind.changeling.absorbed_languages |= language - - var/mob/living/carbon/human/H = src - if(istype(H)) - var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages) - absorbDNA(newDNA) - - return 1 - -//removes our changeling verbs -/mob/proc/remove_changeling_powers() - if(!mind || !mind.changeling) return - for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) - if(P.isVerb) - 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) - - if(!src.mind) return - if(!iscarbon(src)) return - - var/datum/changeling/changeling = src.mind.changeling - if(!changeling) - world.log << "[src] has the changeling_transform() verb but is not a changeling." - return - - if(src.stat > max_stat) - to_chat(src, "We are incapacitated.") - return - - if(changeling.absorbed_dna.len < required_dna) - to_chat(src, "We require at least [required_dna] samples of compatible DNA.") - return - - if(changeling.chem_charges < required_chems) - to_chat(src, "We require at least [required_chems] units of chemicals to do that!") - return - - if(changeling.geneticdamage > max_genetic_damage) - to_chat(src, "Our genomes are still reassembling. We need time to recover first.") - return - - return changeling - - -//Used to dump the languages from the changeling datum into the actual mob. -/mob/proc/changeling_update_languages(var/updated_languages) - - languages = list() - for(var/language in updated_languages) - languages += language - - //This isn't strictly necessary but just to be safe... - add_language("Changeling") - - return - -//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() - set category = "Changeling" - set name = "Absorb DNA" - - var/datum/changeling/changeling = changeling_power(0,0,100) - if(!changeling) return - - var/obj/item/grab/G = src.get_active_hand() - if(!istype(G)) - to_chat(src, "We must be grabbing a creature in our active hand to absorb them.") - return - - var/mob/living/carbon/human/T = G.affecting - if(!istype(T)) - to_chat(src, "[T] is not compatible with our biology.") - return - - if(T.species.flags & NO_SCAN) - to_chat(src, "We cannot extract DNA from this creature!") - return - - if(HUSK in T.mutations) - to_chat(src, "This creature's DNA is ruined beyond useability!") - return - - if(!G.can_absorb()) - to_chat(src, "We must have a tighter grip to absorb this creature.") - return - - if(changeling.isabsorbing) - to_chat(src, "We are already absorbing!") - return - - var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting) - if(!affecting) - to_chat(src, "They are missing that body part!") - - changeling.isabsorbing = 1 - for(var/stage = 1, stage<=3, stage++) - switch(stage) - if(1) - to_chat(src, "This creature is compatible. We must hold still...") - if(2) - to_chat(src, "We extend a proboscis.") - src.visible_message("[src] extends a proboscis!") - if(3) - to_chat(src, "We stab [T] with the proboscis.") - src.visible_message("[src] stabs [T] with the proboscis!") - to_chat(T, "You feel a sharp stabbing pain!") - affecting.take_damage(39, 0, DAM_SHARP, "large organic needle") - - feedback_add_details("changeling_powers","A[stage]") - if(!do_mob(src, T, 150)) - to_chat(src, "Our absorption of [T] has been interrupted!") - changeling.isabsorbing = 0 - return - - to_chat(src, "We have absorbed [T]!") - src.visible_message("[src] sucks the fluids from [T]!") - to_chat(T, "You have been absorbed by the changeling!") - changeling.chem_charges += 10 - changeling.geneticpoints += 2 - - //Steal all of their languages! - for(var/language in T.languages) - if(!(language in changeling.absorbed_languages)) - changeling.absorbed_languages += language - - changeling_update_languages(changeling.absorbed_languages) - - var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages) - absorbDNA(newDNA) - if(mind && T.mind) - mind.store_memory("[T.real_name]'s memories:") - mind.store_memory(T.mind.memory) - mind.store_memory("
") - - if(T.mind && T.mind.changeling) - if(T.mind.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 - absorbDNA(dna_data) - changeling.absorbedcount++ - T.mind.changeling.absorbed_dna.len = 1 - - if(T.mind.changeling.purchasedpowers) - for(var/datum/power/changeling/Tp in T.mind.changeling.purchasedpowers) - if(Tp in changeling.purchasedpowers) - continue - else - changeling.purchasedpowers += Tp - - if(!Tp.isVerb) - call(Tp.verbpath)() - else - src.make_changeling() - - changeling.chem_charges += T.mind.changeling.chem_charges - changeling.geneticpoints += T.mind.changeling.geneticpoints - T.mind.changeling.chem_charges = 0 - T.mind.changeling.geneticpoints = 0 - T.mind.changeling.absorbedcount = 0 - - changeling.absorbedcount++ - changeling.isabsorbing = 0 - - T.death(0) - T.Drain() - return 1 - - -//Change our DNA to that of somebody we've absorbed. -/mob/proc/changeling_transform() - set category = "Changeling" - set name = "Transform (5)" - - var/datum/changeling/changeling = changeling_power(5,1,0) - if(!changeling) return - - var/list/names = list() - 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/absorbed_dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - changeling.chem_charges -= 5 - changeling.geneticdamage = 30 - - var/S_name = chosen_dna.speciesName - var/datum/species/S_dat = all_species[S_name] - var/changeTime = 2 SECONDS - if(mob_size != S_dat.mob_size) - src.visible_message("[src]'s body begins to twist, their mass changing rapidly!") - changeTime = 8 SECONDS - else - src.visible_message("[src]'s body begins to twist, changing rapidly!") - - if(!do_after(src, changeTime)) - to_chat(src, "You fail to change shape.") - return - handle_changeling_transform(chosen_dna) - - 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!") - - src.dna = chosen_dna.dna - src.real_name = chosen_dna.name - src.flavor_text = "" - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - var/newSpecies = chosen_dna.speciesName - H.set_species(newSpecies,1) - H.b_type = chosen_dna.dna.b_type - H.sync_organ_dna() - - domutcheck(src, null) - src.UpdateAppearance() - - -//Transform into a monkey. -/mob/proc/changeling_lesser_form() - set category = "Changeling" - set name = "Lesser Form (1)" - - var/datum/changeling/changeling = changeling_power(1,0,0) - if(!changeling) return - - if(src.has_brain_worms()) - to_chat(src, "We cannot perform this ability at the present time!") - return - - var/mob/living/carbon/human/H = src - - if(!istype(H) || !H.species.primitive_form) - to_chat(src, "We cannot perform this ability in this form!") - return - - changeling.chem_charges-- - H.visible_message("[H] transforms!") - changeling.geneticdamage = 30 - to_chat(H, "Our genes cry out!") - H = H.monkeyize() - feedback_add_details("changeling_powers","LF") - return 1 - -//Transform into a human -/mob/proc/changeling_lesser_transform() - set category = "Changeling" - set name = "Transform (1)" - - var/datum/changeling/changeling = changeling_power(1,1,0) - if(!changeling) return - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_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) - if(!chosen_dna) - return - - var/mob/living/carbon/human/C = src - - changeling.chem_charges-- - C.remove_changeling_powers() - C.visible_message("[C] transforms!") - C.dna = chosen_dna.Clone() - - var/list/implants = list() - for (var/obj/item/weapon/implant/I in C) //Still preserving implants - implants += I - - C.transforming = 1 - C.canmove = 0 - C.icon = null - C.overlays.Cut() - C.set_invisibility(101) - var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("monkey2h", animation) - sleep(48) - qdel(animation) - - for(var/obj/item/W in src) - C.drop_from_inventory(W) - - var/mob/living/carbon/human/O = new /mob/living/carbon/human( src ) - if (C.dna.GetUIState(DNA_UI_GENDER)) - O.gender = FEMALE - else - O.gender = MALE - O.dna = C.dna.Clone() - C.dna = null - O.real_name = chosen_dna.real_name - - for(var/obj/T in C) - qdel(T) - - O.loc = C.loc - - O.UpdateAppearance() - domutcheck(O, null) - O.setToxLoss(C.getToxLoss()) - O.adjustBruteLoss(C.getBruteLoss()) - O.setOxyLoss(C.getOxyLoss()) - O.adjustFireLoss(C.getFireLoss()) - O.set_stat(C.stat) - for (var/obj/item/weapon/implant/I in implants) - I.forceMove(O) - I.implanted = O - - C.mind.transfer_to(O) - O.make_changeling() - O.changeling_update_languages(changeling.absorbed_languages) - - feedback_add_details("changeling_powers","LFT") - qdel(C) - return 1 - - -//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. -/mob/proc/changeling_fakedeath() - set category = "Changeling" - set name = "Regenerative Stasis (20)" - - var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) - if(!changeling) return - - var/mob/living/carbon/C = src - if(!C.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death - return - to_chat(C, "We will attempt to regenerate our form.") - C.status_flags |= FAKEDEATH //play dead - C.update_canmove() - C.remove_changeling_powers() - - C.emote("gasp") - - spawn(rand(800,2000)) - if(changeling_power(20,1,100,DEAD)) - // charge the changeling chemical cost for stasis - changeling.chem_charges -= 20 - - to_chat(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 - to_chat(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() - set category = "Changeling" - set name = "Ranged Sting (10)" - set desc="Your next sting ability can be used against targets 2 squares away." - - var/datum/changeling/changeling = changeling_power(10,0,100) - if(!changeling) return 0 - changeling.chem_charges -= 10 - to_chat(src, "Your throat adjusts to launch the sting.") - changeling.sting_range = 2 - src.verbs -= /mob/proc/changeling_boost_range - spawn(5) src.verbs += /mob/proc/changeling_boost_range - feedback_add_details("changeling_powers","RS") - return 1 - - -//Recover from stuns. -/mob/proc/changeling_unstun() - set category = "Changeling" - set name = "Epinephrine Sacs (45)" - set desc = "Removes all stuns" - - var/datum/changeling/changeling = changeling_power(45,0,100,UNCONSCIOUS) - if(!changeling) return 0 - changeling.chem_charges -= 45 - - var/mob/living/carbon/human/C = src - C.set_stat(CONSCIOUS) - C.SetParalysis(0) - C.SetStunned(0) - C.SetWeakened(0) - C.lying = 0 - C.update_canmove() - - src.verbs -= /mob/proc/changeling_unstun - spawn(5) src.verbs += /mob/proc/changeling_unstun - feedback_add_details("changeling_powers","UNS") - return 1 - - -//Speeds up chemical regeneration -/mob/proc/changeling_fastchemical() - src.mind.changeling.chem_recharge_rate *= 2 - return 1 - -//Increases macimum chemical storage -/mob/proc/changeling_engorgedglands() - src.mind.changeling.chem_storage += 25 - return 1 - - -//Prevents AIs tracking you but makes you easily detectable to the human-eye. -/mob/proc/changeling_digitalcamo() - set category = "Changeling" - set name = "Toggle Digital Camoflague" - set desc = "The AI can no longer track us, but we will look different if examined. Has a constant cost while active." - - var/datum/changeling/changeling = changeling_power() - if(!changeling) return 0 - - var/mob/living/carbon/human/C = src - if(C.digitalcamo) to_chat(C, "We return to normal.") - else to_chat(C, "We distort our form to prevent AI-tracking.") - C.digitalcamo = !C.digitalcamo - - spawn(0) - while(C && C.digitalcamo && C.mind && C.mind.changeling) - C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0) - sleep(40) - - src.verbs -= /mob/proc/changeling_digitalcamo - spawn(5) src.verbs += /mob/proc/changeling_digitalcamo - feedback_add_details("changeling_powers","CAM") - return 1 - - -//Starts healing you every second for 10 seconds. Can be used whilst unconscious. -/mob/proc/changeling_rapidregen() - set category = "Changeling" - set name = "Rapid Regeneration (30)" - set desc = "Begins rapidly regenerating. Does not effect stuns or chemicals." - - var/datum/changeling/changeling = changeling_power(30,0,100,UNCONSCIOUS) - if(!changeling) return 0 - src.mind.changeling.chem_charges -= 30 - - var/mob/living/carbon/human/C = src - spawn(0) - for(var/i = 0, i<10,i++) - if(C) - C.adjustBruteLoss(-10) - C.adjustToxLoss(-10) - C.adjustOxyLoss(-10) - C.adjustFireLoss(-10) - sleep(10) - - src.verbs -= /mob/proc/changeling_rapidregen - spawn(5) src.verbs += /mob/proc/changeling_rapidregen - feedback_add_details("changeling_powers","RR") - return 1 - -// HIVE MIND UPLOAD/DOWNLOAD DNA - -var/list/datum/absorbed_dna/hivemind_bank = list() - -/mob/proc/changeling_hiveupload() - set category = "Changeling" - set name = "Hive Channel (10)" - set desc = "Allows you to channel DNA in the airwaves to allow other changelings to absorb it." - - var/datum/changeling/changeling = changeling_power(10,1) - if(!changeling) return - - var/list/names = list() - 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) - to_chat(src, "The airwaves already have all of our DNA.") - return - - var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names - if(!S) return - - var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - changeling.chem_charges -= 10 - hivemind_bank += chosen_dna - to_chat(src, "We channel the DNA of [S] to the air.") - feedback_add_details("changeling_powers","HU") - return 1 - -/mob/proc/changeling_hivedownload() - set category = "Changeling" - set name = "Hive Absorb (20)" - set desc = "Allows you to absorb DNA that is being channeled in the airwaves." - - var/datum/changeling/changeling = changeling_power(20,1) - if(!changeling) return - - var/list/names = list() - for(var/datum/absorbed_dna/DNA in hivemind_bank) - if(!(changeling.GetDNA(DNA.name))) - names[DNA.name] = DNA - - if(names.len <= 0) - to_chat(src, "There's no new DNA to absorb from the air.") - return - - var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names - if(!S) return - var/datum/dna/chosen_dna = names[S] - if(!chosen_dna) - return - - changeling.chem_charges -= 20 - absorbDNA(chosen_dna) - to_chat(src, "We absorb the DNA of [S] from the air.") - feedback_add_details("changeling_powers","HD") - return 1 - -// Fake Voice - -/mob/proc/changeling_mimicvoice() - set category = "Changeling" - set name = "Mimic Voice" - set desc = "Shape our vocal glands to form a voice of someone we choose. We cannot regenerate chemicals when mimicing." - - - var/datum/changeling/changeling = changeling_power() - if(!changeling) return - - if(changeling.mimicing) - changeling.mimicing = "" - to_chat(src, "We return our vocal glands to their original location.") - return - - var/mimic_voice = sanitize(input(usr, "Enter a name to mimic.", "Mimic Voice", null), MAX_NAME_LEN) - if(!mimic_voice) - return - - changeling.mimicing = mimic_voice - - to_chat(src, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") - to_chat(src, "Use this power again to return to our original voice and reproduce chemicals again.") - feedback_add_details("changeling_powers","MV") - - spawn(0) - while(src && src.mind && src.mind.changeling && src.mind.changeling.mimicing) - src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0) - sleep(40) - if(src && src.mind && src.mind.changeling) - src.mind.changeling.mimicing = "" - ////////// - //STINGS// //They get a pretty header because there's just so fucking many of them ;_; - ////////// - -/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) - if(M.loc == src.loc) - return 1 //target and source are in the same thing - if(!isturf(src.loc) || !isturf(M.loc)) - to_chat(src, "We cannot reach \the [M] with a sting!") - return 0 //One is inside, the other is outside something. - // Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising - if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail - to_chat(src, "We cannot find a path to sting \the [M] by!") - return 0 - 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, var/loud) - var/datum/changeling/changeling = changeling_power(required_chems) - if(!changeling) return - - var/list/victims = list() - for(var/mob/living/carbon/human/C in oview(changeling.sting_range)) - victims += C - var/mob/living/carbon/human/T = input(src, "Who will we sting?") as null|anything in victims - - if(!T) return - if(!(T in view(changeling.sting_range))) return - if(!sting_can_reach(T, changeling.sting_range)) return - if(!changeling_power(required_chems)) return - if(T.isSynthetic()) - to_chat(src, "[T] is not compatible with our biology.") - return - - changeling.chem_charges -= required_chems - changeling.sting_range = 1 - src.verbs -= verb_path - spawn(10) src.verbs += verb_path - if(!loud) - to_chat(src, "We stealthily sting [T].") - else - visible_message("[src] fires an organic shard into [T]'s chest, puncturing the stinger into their skin!") - if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting - to_chat(T, "You feel a tiny prick.") - return - - -/mob/proc/changeling_lsdsting() - set category = "Changeling" - set name = "Hallucination Sting (15)" - set desc = "Causes terror in the target." - - var/mob/living/carbon/human/T = changeling_sting(15,/mob/proc/changeling_lsdsting) - if(!T) return 0 - spawn(rand(300,600)) - if(T) T.hallucination(400, 80) - feedback_add_details("changeling_powers","HS") - return 1 - -/mob/proc/changeling_silence_sting() - set category = "Changeling" - set name = "Silence sting (10)" - set desc="Sting target" - - var/mob/living/carbon/human/T = changeling_sting(10,/mob/proc/changeling_silence_sting) - if(!T) return 0 - T.silent += 30 - feedback_add_details("changeling_powers","SS") - return 1 - -/mob/proc/changeling_blind_sting() - set category = "Changeling" - set name = "Blind sting (20)" - set desc="Sting target" - - var/mob/living/carbon/human/T = changeling_sting(20,/mob/proc/changeling_blind_sting) - if(!T) return 0 - to_chat(T, "Your eyes burn horrificly!") - T.disabilities |= NEARSIGHTED - spawn(300) T.disabilities &= ~NEARSIGHTED - T.eye_blind = 10 - T.eye_blurry = 20 - feedback_add_details("changeling_powers","BS") - return 1 - -/mob/proc/changeling_deaf_sting() - set category = "Changeling" - set name = "Deaf sting (5)" - set desc="Sting target:" - - var/mob/living/carbon/human/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) - if(!T) return 0 - to_chat(T, "Your ears pop and begin ringing loudly!") - T.sdisabilities |= DEAF - spawn(300) T.sdisabilities &= ~DEAF - feedback_add_details("changeling_powers","DS") - return 1 - -/mob/proc/changeling_DEATHsting() - set category = "Changeling" - set name = "Death Sting (40)" - set desc = "Causes spasms onto death." - var/loud = 1 - - var/mob/living/carbon/human/T = changeling_sting(40,/mob/proc/changeling_DEATHsting,loud) - if(!T) return 0 - to_chat(T, "You feel a small prick and your chest becomes tight.") - T.make_jittery(400) - if(T.reagents) T.reagents.add_reagent(/datum/reagent/lexorin, 40) - feedback_add_details("changeling_powers","DTHS") - return 1 - -/mob/proc/changeling_extract_dna_sting() - set category = "Changeling" - set name = "Extract DNA Sting (40)" - set desc="Stealthily sting a target to extract their DNA." - - var/datum/changeling/changeling = null - if(src.mind && src.mind.changeling) - changeling = src.mind.changeling - if(!changeling) - return 0 - - var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) - if(!T) return 0 - if((HUSK in T.mutations) || (T.species.flags & NO_SCAN)) - to_chat(src, "We cannot extract DNA from this creature!") - return 0 - - 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 +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/datum/absorbed_dna/absorbed_dna = list() + var/list/absorbed_languages = list() + var/absorbedcount = 0 + var/chem_charges = 20 + var/chem_recharge_rate = 0.5 + var/chem_storage = 50 + var/sting_range = 1 + var/changelingID = "Changeling" + var/geneticdamage = 0 + var/isabsorbing = 0 + var/geneticpoints = 25 + var/purchasedpowers = list() + var/mimicing = "" + var/cloaked = 0 + var/armor_deployed = 0 //This is only used for changeling_generic_equip_all_slots() at the moment. + var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name. + var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too. + var/last_shriek = null // world.time when the ling last used a shriek. + var/next_escape = 0 // world.time when the ling can next use Escape Restraints + + +/datum/changeling/New() + ..() + if(possible_changeling_IDs.len) + changelingID = pick(possible_changeling_IDs) + possible_changeling_IDs -= changelingID + changelingID = "[changelingID]" + else + changelingID = "[rand(1,999)]" + +/datum/changeling/proc/regenerate() + chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage) + geneticdamage = max(0, geneticdamage-1) + +/datum/changeling/proc/GetDNA(var/dna_owner) + 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() + + if(!mind) return + if(!mind.changeling) mind.changeling = new /datum/changeling(gender) + + verbs += /datum/changeling/proc/EvolutionMenu + add_language("Changeling") + + var/lesser_form = !ishuman(src) + + if(!powerinstances.len) + for(var/P in powers) + powerinstances += new P() + + // Code to auto-purchase free powers. + for(var/datum/power/changeling/P in powerinstances) + if(!P.genomecost) // Is it free? + if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already? + mind.changeling.purchasePower(mind, P.name, 0)// Purchase it. Don't remake our verbs, we're doing it after this. + + for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) + if(P.isVerb) + if(lesser_form && !P.allowduringlesserform) continue + if(!(P in src.verbs)) + src.verbs += P.verbpath + + for(var/language in languages) + mind.changeling.absorbed_languages |= language + + var/mob/living/carbon/human/H = src + if(istype(H)) + var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages) + absorbDNA(newDNA) + + return 1 + +//removes our changeling verbs +/mob/proc/remove_changeling_powers() + if(!mind || !mind.changeling) return + for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) + if(P.isVerb) + 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) + + if(!src.mind) return + if(!iscarbon(src)) return + + var/datum/changeling/changeling = src.mind.changeling + if(!changeling) + world.log << "[src] has the changeling_transform() verb but is not a changeling." + return + + if(src.stat > max_stat) + to_chat(src, "We are incapacitated.") + return + + if(changeling.absorbed_dna.len < required_dna) + to_chat(src, "We require at least [required_dna] samples of compatible DNA.") + return + + if(changeling.chem_charges < required_chems) + to_chat(src, "We require at least [required_chems] units of chemicals to do that!") + return + + if(changeling.geneticdamage > max_genetic_damage) + to_chat(src, "Our genomes are still reassembling. We need time to recover first.") + return + + return changeling + + +//Used to dump the languages from the changeling datum into the actual mob. +/mob/proc/changeling_update_languages(var/updated_languages) + + languages = list() + for(var/language in updated_languages) + languages += language + + //This isn't strictly necessary but just to be safe... + add_language("Changeling") + + return + +//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() + set category = "Changeling" + set name = "Absorb DNA" + + var/datum/changeling/changeling = changeling_power(0,0,100) + if(!changeling) return + + var/obj/item/grab/G = src.get_active_hand() + if(!istype(G)) + to_chat(src, "We must be grabbing a creature in our active hand to absorb them.") + return + + var/mob/living/carbon/human/T = G.affecting + if(!istype(T)) + to_chat(src, "[T] is not compatible with our biology.") + return + + if(T.species.flags & NO_SCAN) + to_chat(src, "We cannot extract DNA from this creature!") + return + + if(HUSK in T.mutations) + to_chat(src, "This creature's DNA is ruined beyond useability!") + return + + if(!G.can_absorb()) + to_chat(src, "We must have a tighter grip to absorb this creature.") + return + + if(changeling.isabsorbing) + to_chat(src, "We are already absorbing!") + return + + var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting) + if(!affecting) + to_chat(src, "They are missing that body part!") + + changeling.isabsorbing = 1 + for(var/stage = 1, stage<=3, stage++) + switch(stage) + if(1) + to_chat(src, "This creature is compatible. We must hold still...") + if(2) + to_chat(src, "We extend a proboscis.") + src.visible_message("[src] extends a proboscis!") + if(3) + to_chat(src, "We stab [T] with the proboscis.") + src.visible_message("[src] stabs [T] with the proboscis!") + to_chat(T, "You feel a sharp stabbing pain!") + affecting.take_damage(39, 0, DAM_SHARP, "large organic needle") + + feedback_add_details("changeling_powers","A[stage]") + if(!do_mob(src, T, 150)) + to_chat(src, "Our absorption of [T] has been interrupted!") + changeling.isabsorbing = 0 + return + + to_chat(src, "We have absorbed [T]!") + src.visible_message("[src] sucks the fluids from [T]!") + to_chat(T, "You have been absorbed by the changeling!") + changeling.chem_charges += 10 + changeling.geneticpoints += 2 + + //Steal all of their languages! + for(var/language in T.languages) + if(!(language in changeling.absorbed_languages)) + changeling.absorbed_languages += language + + changeling_update_languages(changeling.absorbed_languages) + + var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages) + absorbDNA(newDNA) + if(mind && T.mind) + mind.store_memory("[T.real_name]'s memories:") + mind.store_memory(T.mind.memory) + mind.store_memory("
") + + if(T.mind && T.mind.changeling) + if(T.mind.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 + absorbDNA(dna_data) + changeling.absorbedcount++ + T.mind.changeling.absorbed_dna.len = 1 + + if(T.mind.changeling.purchasedpowers) + for(var/datum/power/changeling/Tp in T.mind.changeling.purchasedpowers) + if(Tp in changeling.purchasedpowers) + continue + else + changeling.purchasedpowers += Tp + + if(!Tp.isVerb) + call(Tp.verbpath)() + else + src.make_changeling() + + changeling.chem_charges += T.mind.changeling.chem_charges + changeling.geneticpoints += T.mind.changeling.geneticpoints + T.mind.changeling.chem_charges = 0 + T.mind.changeling.geneticpoints = 0 + T.mind.changeling.absorbedcount = 0 + + changeling.absorbedcount++ + changeling.isabsorbing = 0 + + T.death(0) + T.Drain() + return 1 + + +//Change our DNA to that of somebody we've absorbed. +/mob/proc/changeling_transform() + set category = "Changeling" + set name = "Transform (5)" + + var/datum/changeling/changeling = changeling_power(5,1,0) + if(!changeling) return + + var/list/names = list() + 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/absorbed_dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + changeling.chem_charges -= 5 + changeling.geneticdamage = 30 + + var/S_name = chosen_dna.speciesName + var/datum/species/S_dat = all_species[S_name] + var/changeTime = 2 SECONDS + if(mob_size != S_dat.mob_size) + src.visible_message("[src]'s body begins to twist, their mass changing rapidly!") + changeTime = 8 SECONDS + else + src.visible_message("[src]'s body begins to twist, changing rapidly!") + + if(!do_after(src, changeTime)) + to_chat(src, "You fail to change shape.") + return + handle_changeling_transform(chosen_dna) + + 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!") + + src.dna = chosen_dna.dna + src.real_name = chosen_dna.name + src.flavor_text = "" + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + var/newSpecies = chosen_dna.speciesName + H.set_species(newSpecies,1) + H.b_type = chosen_dna.dna.b_type + H.sync_organ_dna() + + domutcheck(src, null) + src.UpdateAppearance() + + +//Transform into a monkey. +/mob/proc/changeling_lesser_form() + set category = "Changeling" + set name = "Lesser Form (1)" + + var/datum/changeling/changeling = changeling_power(1,0,0) + if(!changeling) return + + if(src.has_brain_worms()) + to_chat(src, "We cannot perform this ability at the present time!") + return + + var/mob/living/carbon/human/H = src + + if(!istype(H) || !H.species.primitive_form) + to_chat(src, "We cannot perform this ability in this form!") + return + + changeling.chem_charges-- + H.visible_message("[H] transforms!") + changeling.geneticdamage = 30 + to_chat(H, "Our genes cry out!") + H = H.monkeyize() + feedback_add_details("changeling_powers","LF") + return 1 + +//Transform into a human +/mob/proc/changeling_lesser_transform() + set category = "Changeling" + set name = "Transform (1)" + + var/datum/changeling/changeling = changeling_power(1,1,0) + if(!changeling) return + + var/list/names = list() + for(var/datum/dna/DNA in changeling.absorbed_dna) + names += "[DNA.real_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) + if(!chosen_dna) + return + + var/mob/living/carbon/human/C = src + + changeling.chem_charges-- + C.remove_changeling_powers() + C.visible_message("[C] transforms!") + C.dna = chosen_dna.Clone() + + var/list/implants = list() + for (var/obj/item/weapon/implant/I in C) //Still preserving implants + implants += I + + C.transforming = 1 + C.canmove = 0 + C.icon = null + C.overlays.Cut() + C.set_invisibility(101) + var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("monkey2h", animation) + sleep(48) + qdel(animation) + + for(var/obj/item/W in src) + C.drop_from_inventory(W) + + var/mob/living/carbon/human/O = new /mob/living/carbon/human( src ) + if (C.dna.GetUIState(DNA_UI_GENDER)) + O.gender = FEMALE + else + O.gender = MALE + O.dna = C.dna.Clone() + C.dna = null + O.real_name = chosen_dna.real_name + + for(var/obj/T in C) + qdel(T) + + O.loc = C.loc + + O.UpdateAppearance() + domutcheck(O, null) + O.setToxLoss(C.getToxLoss()) + O.adjustBruteLoss(C.getBruteLoss()) + O.setOxyLoss(C.getOxyLoss()) + O.adjustFireLoss(C.getFireLoss()) + O.set_stat(C.stat) + for (var/obj/item/weapon/implant/I in implants) + I.forceMove(O) + I.implanted = O + + C.mind.transfer_to(O) + O.make_changeling() + O.changeling_update_languages(changeling.absorbed_languages) + + feedback_add_details("changeling_powers","LFT") + qdel(C) + return 1 + + +//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. +/mob/proc/changeling_fakedeath() + set category = "Changeling" + set name = "Regenerative Stasis (20)" + + var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) + if(!changeling) return + + var/mob/living/carbon/C = src + if(!C.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death + return + to_chat(C, "We will attempt to regenerate our form.") + C.status_flags |= FAKEDEATH //play dead + C.update_canmove() + C.remove_changeling_powers() + + C.emote("gasp") + + spawn(rand(800,2000)) + if(changeling_power(20,1,100,DEAD)) + // charge the changeling chemical cost for stasis + changeling.chem_charges -= 20 + + to_chat(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 + to_chat(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() + set category = "Changeling" + set name = "Ranged Sting (10)" + set desc="Your next sting ability can be used against targets 2 squares away." + + var/datum/changeling/changeling = changeling_power(10,0,100) + if(!changeling) return 0 + changeling.chem_charges -= 10 + to_chat(src, "Your throat adjusts to launch the sting.") + changeling.sting_range = 2 + src.verbs -= /mob/proc/changeling_boost_range + spawn(5) src.verbs += /mob/proc/changeling_boost_range + feedback_add_details("changeling_powers","RS") + return 1 + + +//Recover from stuns. +/mob/proc/changeling_unstun() + set category = "Changeling" + set name = "Epinephrine Sacs (45)" + set desc = "Removes all stuns" + + var/datum/changeling/changeling = changeling_power(45,0,100,UNCONSCIOUS) + if(!changeling) return 0 + changeling.chem_charges -= 45 + + var/mob/living/carbon/human/C = src + C.set_stat(CONSCIOUS) + C.SetParalysis(0) + C.SetStunned(0) + C.SetWeakened(0) + C.lying = 0 + C.update_canmove() + + src.verbs -= /mob/proc/changeling_unstun + spawn(5) src.verbs += /mob/proc/changeling_unstun + feedback_add_details("changeling_powers","UNS") + return 1 + + +//Speeds up chemical regeneration +/mob/proc/changeling_fastchemical() + src.mind.changeling.chem_recharge_rate *= 2 + return 1 + +//Increases macimum chemical storage +/mob/proc/changeling_engorgedglands() + src.mind.changeling.chem_storage += 25 + return 1 + + +//Prevents AIs tracking you but makes you easily detectable to the human-eye. +/mob/proc/changeling_digitalcamo() + set category = "Changeling" + set name = "Toggle Digital Camoflague" + set desc = "The AI can no longer track us, but we will look different if examined. Has a constant cost while active." + + var/datum/changeling/changeling = changeling_power() + if(!changeling) return 0 + + var/mob/living/carbon/human/C = src + if(C.digitalcamo) to_chat(C, "We return to normal.") + else to_chat(C, "We distort our form to prevent AI-tracking.") + C.digitalcamo = !C.digitalcamo + + spawn(0) + while(C && C.digitalcamo && C.mind && C.mind.changeling) + C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0) + sleep(40) + + src.verbs -= /mob/proc/changeling_digitalcamo + spawn(5) src.verbs += /mob/proc/changeling_digitalcamo + feedback_add_details("changeling_powers","CAM") + return 1 + + +//Starts healing you every second for 10 seconds. Can be used whilst unconscious. +/mob/proc/changeling_rapidregen() + set category = "Changeling" + set name = "Rapid Regeneration (30)" + set desc = "Begins rapidly regenerating. Does not effect stuns or chemicals." + + var/datum/changeling/changeling = changeling_power(30,0,100,UNCONSCIOUS) + if(!changeling) return 0 + src.mind.changeling.chem_charges -= 30 + + var/mob/living/carbon/human/C = src + spawn(0) + for(var/i = 0, i<10,i++) + if(C) + C.adjustBruteLoss(-10) + C.adjustToxLoss(-10) + C.adjustOxyLoss(-10) + C.adjustFireLoss(-10) + sleep(10) + + src.verbs -= /mob/proc/changeling_rapidregen + spawn(5) src.verbs += /mob/proc/changeling_rapidregen + feedback_add_details("changeling_powers","RR") + return 1 + +// HIVE MIND UPLOAD/DOWNLOAD DNA + +var/list/datum/absorbed_dna/hivemind_bank = list() + +/mob/proc/changeling_hiveupload() + set category = "Changeling" + set name = "Hive Channel (10)" + set desc = "Allows you to channel DNA in the airwaves to allow other changelings to absorb it." + + var/datum/changeling/changeling = changeling_power(10,1) + if(!changeling) return + + var/list/names = list() + 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) + to_chat(src, "The airwaves already have all of our DNA.") + return + + var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names + if(!S) return + + var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + changeling.chem_charges -= 10 + hivemind_bank += chosen_dna + to_chat(src, "We channel the DNA of [S] to the air.") + feedback_add_details("changeling_powers","HU") + return 1 + +/mob/proc/changeling_hivedownload() + set category = "Changeling" + set name = "Hive Absorb (20)" + set desc = "Allows you to absorb DNA that is being channeled in the airwaves." + + var/datum/changeling/changeling = changeling_power(20,1) + if(!changeling) return + + var/list/names = list() + for(var/datum/absorbed_dna/DNA in hivemind_bank) + if(!(changeling.GetDNA(DNA.name))) + names[DNA.name] = DNA + + if(names.len <= 0) + to_chat(src, "There's no new DNA to absorb from the air.") + return + + var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names + if(!S) return + var/datum/dna/chosen_dna = names[S] + if(!chosen_dna) + return + + changeling.chem_charges -= 20 + absorbDNA(chosen_dna) + to_chat(src, "We absorb the DNA of [S] from the air.") + feedback_add_details("changeling_powers","HD") + return 1 + +// Fake Voice + +/mob/proc/changeling_mimicvoice() + set category = "Changeling" + set name = "Mimic Voice" + set desc = "Shape our vocal glands to form a voice of someone we choose. We cannot regenerate chemicals when mimicing." + + + var/datum/changeling/changeling = changeling_power() + if(!changeling) return + + if(changeling.mimicing) + changeling.mimicing = "" + to_chat(src, "We return our vocal glands to their original location.") + return + + var/mimic_voice = sanitize(input(usr, "Enter a name to mimic.", "Mimic Voice", null), MAX_NAME_LEN) + if(!mimic_voice) + return + + changeling.mimicing = mimic_voice + + to_chat(src, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") + to_chat(src, "Use this power again to return to our original voice and reproduce chemicals again.") + feedback_add_details("changeling_powers","MV") + + spawn(0) + while(src && src.mind && src.mind.changeling && src.mind.changeling.mimicing) + src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0) + sleep(40) + if(src && src.mind && src.mind.changeling) + src.mind.changeling.mimicing = "" + ////////// + //STINGS// //They get a pretty header because there's just so fucking many of them ;_; + ////////// + +/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) + if(M.loc == src.loc) + return 1 //target and source are in the same thing + if(!isturf(src.loc) || !isturf(M.loc)) + to_chat(src, "We cannot reach \the [M] with a sting!") + return 0 //One is inside, the other is outside something. + // Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising + if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail + to_chat(src, "We cannot find a path to sting \the [M] by!") + return 0 + 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, var/loud) + var/datum/changeling/changeling = changeling_power(required_chems) + if(!changeling) return + + var/list/victims = list() + for(var/mob/living/carbon/human/C in oview(changeling.sting_range)) + victims += C + var/mob/living/carbon/human/T = input(src, "Who will we sting?") as null|anything in victims + + if(!T) return + if(!(T in view(changeling.sting_range))) return + if(!sting_can_reach(T, changeling.sting_range)) return + if(!changeling_power(required_chems)) return + if(T.isSynthetic()) + to_chat(src, "[T] is not compatible with our biology.") + return + + changeling.chem_charges -= required_chems + changeling.sting_range = 1 + src.verbs -= verb_path + spawn(10) src.verbs += verb_path + if(!loud) + to_chat(src, "We stealthily sting [T].") + else + visible_message("[src] fires an organic shard into [T]'s chest, puncturing the stinger into their skin!") + if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting + to_chat(T, "You feel a tiny prick.") + return + + +/mob/proc/changeling_lsdsting() + set category = "Changeling" + set name = "Hallucination Sting (15)" + set desc = "Causes terror in the target." + + var/mob/living/carbon/human/T = changeling_sting(15,/mob/proc/changeling_lsdsting) + if(!T) return 0 + spawn(rand(300,600)) + if(T) T.hallucination(400, 80) + feedback_add_details("changeling_powers","HS") + return 1 + +/mob/proc/changeling_silence_sting() + set category = "Changeling" + set name = "Silence sting (10)" + set desc="Sting target" + + var/mob/living/carbon/human/T = changeling_sting(10,/mob/proc/changeling_silence_sting) + if(!T) return 0 + T.silent += 30 + feedback_add_details("changeling_powers","SS") + return 1 + +/mob/proc/changeling_blind_sting() + set category = "Changeling" + set name = "Blind sting (20)" + set desc="Sting target" + + var/mob/living/carbon/human/T = changeling_sting(20,/mob/proc/changeling_blind_sting) + if(!T) return 0 + to_chat(T, "Your eyes burn horrificly!") + T.disabilities |= NEARSIGHTED + spawn(300) T.disabilities &= ~NEARSIGHTED + T.eye_blind = 10 + T.eye_blurry = 20 + feedback_add_details("changeling_powers","BS") + return 1 + +/mob/proc/changeling_deaf_sting() + set category = "Changeling" + set name = "Deaf sting (5)" + set desc="Sting target:" + + var/mob/living/carbon/human/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) + if(!T) return 0 + to_chat(T, "Your ears pop and begin ringing loudly!") + T.sdisabilities |= DEAF + spawn(300) T.sdisabilities &= ~DEAF + feedback_add_details("changeling_powers","DS") + return 1 + +/mob/proc/changeling_DEATHsting() + set category = "Changeling" + set name = "Death Sting (40)" + set desc = "Causes spasms onto death." + var/loud = 1 + + var/mob/living/carbon/human/T = changeling_sting(40,/mob/proc/changeling_DEATHsting,loud) + if(!T) return 0 + to_chat(T, "You feel a small prick and your chest becomes tight.") + T.make_jittery(400) + if(T.reagents) T.reagents.add_reagent(/datum/reagent/lexorin, 40) + feedback_add_details("changeling_powers","DTHS") + return 1 + +/mob/proc/changeling_extract_dna_sting() + set category = "Changeling" + set name = "Extract DNA Sting (40)" + set desc="Stealthily sting a target to extract their DNA." + + var/datum/changeling/changeling = null + if(src.mind && src.mind.changeling) + changeling = src.mind.changeling + if(!changeling) + return 0 + + var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) + if(!T) return 0 + if((HUSK in T.mutations) || (T.species.flags & NO_SCAN)) + to_chat(src, "We cannot extract DNA from this creature!") + return 0 + + 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 diff --git a/code/game/gamemodes/changeling/generic_equip_procs.dm b/code/game/gamemodes/changeling/generic_equip_procs.dm new file mode 100644 index 0000000..d4b4b2e --- /dev/null +++ b/code/game/gamemodes/changeling/generic_equip_procs.dm @@ -0,0 +1,280 @@ +//This is a generic proc that should be called by other ling armor procs to equip them. +/mob/proc/changeling_generic_armor(var/armor_type, var/helmet_type, var/boot_type, var/chem_cost) + + if(!ishuman(src)) + return 0 + + var/mob/living/carbon/human/M = src + + if(istype(M.wear_suit, armor_type) || istype(M.head, helmet_type) || istype(M.shoes, boot_type)) + chem_cost = 0 + + var/datum/changeling/changeling = changeling_power(chem_cost, 1, 100, CONSCIOUS) + + if(!changeling) + return + + //First, check if we're already wearing the armor, and if so, take it off. + if(istype(M.wear_suit, armor_type) || istype(M.head, helmet_type) || istype(M.shoes, boot_type)) + M.visible_message("[M] casts off their [M.wear_suit.name]!", + "We cast off our [M.wear_suit.name]", + "You hear the organic matter ripping and tearing!") + if(istype(M.wear_suit, armor_type)) + qdel(M.wear_suit) + if(istype(M.head, helmet_type)) + qdel(M.head) + if(istype(M.shoes, boot_type)) + qdel(M.shoes) + M.update_inv_wear_suit() + M.update_inv_head() + M.update_hair() + M.update_inv_shoes() + return 1 + + if(M.head || M.wear_suit) //Make sure our slots aren't full + src << "We require nothing to be on our head, and we cannot wear any external suits, or shoes." + return 0 + + var/obj/item/clothing/suit/A = new armor_type(src) + src.equip_to_slot_or_del(A, slot_wear_suit) + + var/obj/item/clothing/suit/H = new helmet_type(src) + src.equip_to_slot_or_del(H, slot_head) + + var/obj/item/clothing/shoes/B = new boot_type(src) + src.equip_to_slot_or_del(B, slot_shoes) + + src.mind.changeling.chem_charges -= chem_cost + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + M.update_inv_wear_suit() + M.update_inv_head() + M.update_hair() + M.update_inv_shoes() + return 1 + +/mob/proc/changeling_generic_equip_all_slots(var/list/stuff_to_equip, var/cost) + var/datum/changeling/changeling = changeling_power(cost,1,100,CONSCIOUS) + if(!changeling) + return + + if(!ishuman(src)) + return 0 + + var/mob/living/carbon/human/M = src + + var/success = 0 + + //First, check if we're already wearing the armor, and if so, take it off. + + if(M.mind.changeling.armor_deployed) + if(M.head && stuff_to_equip["head"]) + if(istype(M.head, stuff_to_equip["head"])) + qdel(M.head) + success = 1 + + if(M.wear_id && stuff_to_equip["wear_id"]) + if(istype(M.wear_id, stuff_to_equip["wear_id"])) + qdel(M.wear_id) + success = 1 + + if(M.wear_suit && stuff_to_equip["wear_suit"]) + if(istype(M.wear_suit, stuff_to_equip["wear_suit"])) + qdel(M.wear_suit) + success = 1 + + if(M.gloves && stuff_to_equip["gloves"]) + if(istype(M.gloves, stuff_to_equip["gloves"])) + qdel(M.gloves) + success = 1 + if(M.shoes && stuff_to_equip["shoes"]) + if(istype(M.shoes, stuff_to_equip["shoes"])) + qdel(M.shoes) + success = 1 + + if(M.belt && stuff_to_equip["belt"]) + if(istype(M.belt, stuff_to_equip["belt"])) + qdel(M.belt) + success = 1 + + if(M.glasses && stuff_to_equip["glasses"]) + if(istype(M.glasses, stuff_to_equip["glasses"])) + qdel(M.glasses) + success = 1 + + if(M.wear_mask && stuff_to_equip["wear_mask"]) + if(istype(M.wear_mask, stuff_to_equip["wear_mask"])) + qdel(M.wear_mask) + success = 1 + + if(M.back && stuff_to_equip["back"]) + if(istype(M.back, stuff_to_equip["back"])) + for(var/atom/movable/AM in M.back.contents) //Dump whatever's in the bag before deleting. + AM.forceMove(src.loc) + qdel(M.back) + success = 1 + + if(M.w_uniform && stuff_to_equip["w_uniform"]) + if(istype(M.w_uniform, stuff_to_equip["w_uniform"])) + qdel(M.w_uniform) + success = 1 + + if(success) + playsound(src, 'sound/effects/splat.ogg', 30, 1) + visible_message("[src] pulls on their clothes, peeling it off along with parts of their skin attached!", + "We remove and deform our equipment.") + M.update_icons() + M.mind.changeling.armor_deployed = 0 + return success + + else + + M << "We begin growing our new equipment..." + + var/list/grown_items_list = list() + + var/t = stuff_to_equip["head"] + if(!M.head && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_head) + grown_items_list.Add("a helmet") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["w_uniform"] + if(!M.w_uniform && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_w_uniform) + grown_items_list.Add("a uniform") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["gloves"] + if(!M.gloves && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_gloves) + grown_items_list.Add("some gloves") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["shoes"] + if(!M.shoes && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_shoes) + grown_items_list.Add("shoes") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["belt"] + if(!M.belt && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_belt) + grown_items_list.Add("a belt") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["glasses"] + if(!M.glasses && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_glasses) + grown_items_list.Add("some glasses") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["wear_mask"] + if(!M.wear_mask && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_wear_mask) + grown_items_list.Add("a mask") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["back"] + if(!M.back && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_back) + grown_items_list.Add("a backpack") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["wear_suit"] + if(!M.wear_suit && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_wear_suit) + grown_items_list.Add("an exosuit") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + t = stuff_to_equip["wear_id"] + if(!M.wear_id && t) + var/I = new t + M.equip_to_slot_or_del(I, slot_wear_id) + grown_items_list.Add("an ID card") + playsound(src, 'sound/effects/splat.ogg', 30, 1) + M.update_icons() + success = 1 + sleep(1 SECOND) + + var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) + + M << "We have grown [feedback]." + /* + for(var/I in stuff_to_equip) + world << I + world << stuff_to_equip + world << "Proc ended." + */ + M.update_icons() + if(success) + M.mind.changeling.armor_deployed = 1 + M.mind.changeling.chem_charges -= 10 + return success + +//This is a generic proc that should be called by other ling weapon procs to equip them. +/mob/proc/changeling_generic_weapon(var/weapon_type, var/make_sound = 1, var/cost = 20) + var/datum/changeling/changeling = changeling_power(cost,1,100,CONSCIOUS) + if(!changeling) + return + + if(!ishuman(src)) + return 0 + +/* var/mob/living/M = holder.wearer + + if(M.l_hand && M.r_hand) + to_chat(M, "Your hands are full.") + return 0 +*/ + ..() + + var/mob/living/M = src + + if(M.l_hand && M.r_hand) + to_chat(M, "Your hands are full.") + return + + + var/obj/item/weapon/W = new weapon_type(src) + src.put_in_hands(W) + + src.mind.changeling.chem_charges -= cost + if(make_sound) + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/modularchangling.dm b/code/game/gamemodes/changeling/modularchangling.dm index 73a6ceb..9c04f60 100644 --- a/code/game/gamemodes/changeling/modularchangling.dm +++ b/code/game/gamemodes/changeling/modularchangling.dm @@ -1,484 +1,842 @@ -// READ: Don't use the apostrophe in name or desc. Causes script errors. - -var/list/powers = typesof(/datum/power/changeling) - /datum/power/changeling //needed for the badmin verb for now -var/list/datum/power/changeling/powerinstances = list() - -/datum/power //Could be used by other antags too - var/name = "Power" - var/desc = "Placeholder" - var/helptext = "" - var/isVerb = 1 // Is it an active power, or passive? - var/verbpath // Path to a verb that contains the effects. - -/datum/power/changeling - var/allowduringlesserform = 0 - var/genomecost = 500000 // Cost for the changling to evolve this power. - -/datum/power/changeling/absorb_dna - name = "Absorb DNA" - desc = "Permits us to syphon the DNA from a human. They become one with us, and we become stronger." - genomecost = 0 - verbpath = /mob/proc/changeling_absorb_dna - -/datum/power/changeling/transform - name = "Transform" - desc = "We take on the apperance and voice of one we have absorbed." - genomecost = 0 - verbpath = /mob/proc/changeling_transform - -/datum/power/changeling/fakedeath - name = "Regenerative Stasis" - desc = "We become weakened to a death-like state, where we will rise again from death." - helptext = "Can be used before or after death. Duration varies greatly." - genomecost = 0 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_fakedeath - -// Hivemind - -/datum/power/changeling/hive_upload - name = "Hive Channel" - desc = "We can channel a DNA into the airwaves, allowing our fellow changelings to absorb it and transform into it as if they acquired the DNA themselves." - helptext = "Allows other changelings to absorb the DNA you channel from the airwaves. Will not help them towards their absorb objectives." - genomecost = 0 - verbpath = /mob/proc/changeling_hiveupload - -/datum/power/changeling/hive_download - name = "Hive Absorb" - desc = "We can absorb a single DNA from the airwaves, allowing us to use more disguises with help from our fellow changelings." - helptext = "Allows you to absorb a single DNA and use it. Does not count towards your absorb objective." - genomecost = 0 - verbpath = /mob/proc/changeling_hivedownload - -/datum/power/changeling/lesser_form - name = "Lesser Form" - desc = "We debase ourselves and become lesser. We become a monkey." - genomecost = 4 - verbpath = /mob/proc/changeling_lesser_form - -/datum/power/changeling/deaf_sting - name = "Deaf Sting" - desc = "We silently 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." - genomecost = 2 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_blind_sting - -/datum/power/changeling/silence_sting - name = "Silence Sting" - desc = "We silently sting a human, completely silencing them for a short time." - helptext = "Does not provide a warning to a victim that they have been stung, until they try to speak and cannot." - genomecost = 3 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_silence_sting - -/datum/power/changeling/mimicvoice - name = "Mimic Voice" - desc = "We shape our vocal glands to sound like a desired voice." - helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this" - genomecost = 1 - verbpath = /mob/proc/changeling_mimicvoice - -/datum/power/changeling/extractdna - name = "Extract DNA" - desc = "We stealthily sting a target and extract the DNA from them." - helptext = "Will give you the DNA of your target, allowing you to transform into them. Does not count towards absorb objectives." - genomecost = 2 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_extract_dna_sting - -/datum/power/changeling/LSDSting - name = "Hallucination Sting" - desc = "We evolve the ability to sting a target with a powerful hallunicationary chemical." - helptext = "The target does not notice they have been stung. The effect occurs after 30 to 60 seconds." - genomecost = 3 - verbpath = /mob/proc/changeling_lsdsting - -/datum/power/changeling/DeathSting - name = "Death Sting" - desc = "We sting a human, filling them with potent chemicals. Their rapid death is all but assured, but our crime will be obvious." - helptext = "It will be clear to any surrounding witnesses if you use this power." - genomecost = 10 - verbpath = /mob/proc/changeling_DEATHsting - - -/datum/power/changeling/boost_range - name = "Boost Range" - desc = "We evolve the ability to shoot our stingers at humans, with some preperation." - genomecost = 2 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_boost_range - -/datum/power/changeling/Epinephrine - name = "Epinephrine sacs" - desc = "We evolve additional sacs of adrenaline throughout our body." - helptext = "Gives the ability to instantly recover from stuns. High chemical cost." - genomecost = 3 - verbpath = /mob/proc/changeling_unstun - -/datum/power/changeling/ChemicalSynth - name = "Rapid Chemical-Synthesis" - desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." - helptext = "Doubles the rate at which we naturally recharge chemicals." - genomecost = 4 - isVerb = 0 - verbpath = /mob/proc/changeling_fastchemical -/* -/datum/power/changeling/AdvChemicalSynth - name = "Advanced Chemical-Synthesis" - desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." - helptext = "Doubles the rate at which we naturally recharge chemicals." - genomecost = 8 - isVerb = 0 - verbpath = /mob/proc/changeling_fastchemical -*/ -/datum/power/changeling/EngorgedGlands - name = "Engorged Chemical Glands" - desc = "Our chemical glands swell, permitting us to store more chemicals inside of them." - helptext = "Allows us to store an extra 25 units of chemicals." - genomecost = 4 - isVerb = 0 - verbpath = /mob/proc/changeling_engorgedglands - -/datum/power/changeling/DigitalCamoflague - name = "Digital Camoflauge" - desc = "We evolve the ability to distort our form and proprtions, defeating common altgorthms used to detect lifeforms on cameras." - helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us.. uncanny. We must constantly expend chemicals to maintain our form like this." - genomecost = 1 - allowduringlesserform = 1 - verbpath = /mob/proc/changeling_digitalcamo - -/datum/power/changeling/rapidregeneration - name = "Rapid Regeneration" - desc = "We evolve the ability to rapidly regenerate, negating the need for stasis." - helptext = "Heals a moderate amount of damage every tick." - genomecost = 7 - verbpath = /mob/proc/changeling_rapidregen - - - -// Modularchangling, totally stolen from the new player panel. YAYY -/datum/changeling/proc/EvolutionMenu()//The new one - set category = "Changeling" - set desc = "Level up!" - - if(!usr || !usr.mind || !usr.mind.changeling) return - src = usr.mind.changeling - - if(!powerinstances.len) - for(var/P in powers) - powerinstances += new P() - - var/dat = "Changling Evolution Menu" - - //javascript, the part that does most of the work~ - dat += {" - - - - - - - "} - - //body tag start + onload and onkeypress (onkeyup) javascript event calls - dat += "" - - //title + search bar - dat += {" - - - - - - - - -
- Changling Evolution Menu
- Hover over a power to see more information
- Current evolution points left to evolve with: [geneticpoints]
- Absorb genomes to acquire more evolution points -

-

- Search: -
- - "} - - //player table header - dat += {" - - "} - - var/i = 1 - for(var/datum/power/changeling/P in powerinstances) - var/ownsthis = 0 - - if(P in purchasedpowers) - ownsthis = 1 - - - var/color = "#e6e6e6" - if(i%2 == 0) - color = "#f2f2f2" - - - dat += {" - - - - - - "} - - i++ - - - //player table ending - dat += {" -
- - - Evolve [P] - Cost: [ownsthis ? "Purchased" : P.genomecost] - -
-
-
- - - - "} - - usr << browse(dat, "window=powers;size=900x480") - - -/datum/changeling/Topic(href, href_list) - ..() - if(!ismob(usr)) - return - - if(href_list["P"]) - var/datum/mind/M = usr.mind - if(!istype(M)) - return - purchasePower(M, href_list["P"]) - call(/datum/changeling/proc/EvolutionMenu)() - - - -/datum/changeling/proc/purchasePower(var/datum/mind/M, var/Pname, var/remake_verbs = 1) - if(!M || !M.changeling) - return - - var/datum/power/changeling/Thepower = Pname - - - for (var/datum/power/changeling/P in powerinstances) -// log_debug("[P] - [Pname] = [P.name == Pname ? "True" : "False"]") - - if(P.name == Pname) - Thepower = P - break - - - if(Thepower == null) - to_chat(M.current, "This is awkward. Changeling power purchase failed, please report this bug to a coder!") - return - - if(Thepower in purchasedpowers) - to_chat(M.current, "We have already evolved this ability!") - return - - - if(geneticpoints < Thepower.genomecost) - to_chat(M.current, "We cannot evolve this... yet. We must acquire more DNA.") - return - - geneticpoints -= Thepower.genomecost - - purchasedpowers += Thepower - - if(!Thepower.isVerb && Thepower.verbpath) - call(M.current, Thepower.verbpath)() - else if(remake_verbs) - M.current.make_changeling() - +// READ: Don't use the apostrophe in name or desc. Causes script errors. + +var/list/powers = typesof(/datum/power/changeling) - /datum/power/changeling //needed for the badmin verb for now +var/list/datum/power/changeling/powerinstances = list() + +/datum/power //Could be used by other antags too + var/name = "Power" + var/desc = "Placeholder" + var/helptext = "" + var/enhancedtext = "" + var/isVerb = 1 // Is it an active power, or passive? + var/verbpath // Path to a verb that contains the effects. + +/datum/power/changeling + var/allowduringlesserform = 0 + var/genomecost = 500000 // Cost for the changling to evolve this power. + +/datum/power/changeling/absorb_dna + name = "Absorb DNA" + desc = "Permits us to syphon the DNA from a human. They become one with us, and we become stronger." + genomecost = 0 + verbpath = /mob/proc/changeling_absorb_dna + +/datum/power/changeling/transform + name = "Transform" + desc = "We take on the apperance and voice of one we have absorbed." + genomecost = 0 + verbpath = /mob/proc/changeling_transform + +/datum/power/changeling/fakedeath + name = "Regenerative Stasis" + desc = "We become weakened to a death-like state, where we will rise again from death." + helptext = "Can be used before or after death. Duration varies greatly." + genomecost = 0 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_fakedeath + +// Hivemind + +/datum/power/changeling/hive_upload + name = "Hive Channel" + desc = "We can channel a DNA into the airwaves, allowing our fellow changelings to absorb it and transform into it as if they acquired the DNA themselves." + helptext = "Allows other changelings to absorb the DNA you channel from the airwaves. Will not help them towards their absorb objectives." + genomecost = 0 + verbpath = /mob/proc/changeling_hiveupload + +/datum/power/changeling/hive_download + name = "Hive Absorb" + desc = "We can absorb a single DNA from the airwaves, allowing us to use more disguises with help from our fellow changelings." + helptext = "Allows you to absorb a single DNA and use it. Does not count towards your absorb objective." + genomecost = 0 + verbpath = /mob/proc/changeling_hivedownload + +/datum/power/changeling/lesser_form + name = "Lesser Form" + desc = "We debase ourselves and become lesser. We become a monkey." + genomecost = 4 + verbpath = /mob/proc/changeling_lesser_form + +/datum/power/changeling/deaf_sting + name = "Deaf Sting" + desc = "We silently 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." + genomecost = 2 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_blind_sting + +/datum/power/changeling/silence_sting + name = "Silence Sting" + desc = "We silently sting a human, completely silencing them for a short time." + helptext = "Does not provide a warning to a victim that they have been stung, until they try to speak and cannot." + genomecost = 3 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_silence_sting + +/datum/power/changeling/mimicvoice + name = "Mimic Voice" + desc = "We shape our vocal glands to sound like a desired voice." + helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this" + genomecost = 1 + verbpath = /mob/proc/changeling_mimicvoice + +/datum/power/changeling/extractdna + name = "Extract DNA" + desc = "We stealthily sting a target and extract the DNA from them." + helptext = "Will give you the DNA of your target, allowing you to transform into them. Does not count towards absorb objectives." + genomecost = 2 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_extract_dna_sting + +/datum/power/changeling/LSDSting + name = "Hallucination Sting" + desc = "We evolve the ability to sting a target with a powerful hallunicationary chemical." + helptext = "The target does not notice they have been stung. The effect occurs after 30 to 60 seconds." + genomecost = 3 + verbpath = /mob/proc/changeling_lsdsting + +/datum/power/changeling/DeathSting + name = "Death Sting" + desc = "We sting a human, filling them with potent chemicals. Their rapid death is all but assured, but our crime will be obvious." + helptext = "It will be clear to any surrounding witnesses if you use this power." + genomecost = 10 + verbpath = /mob/proc/changeling_DEATHsting + + +/datum/power/changeling/boost_range + name = "Boost Range" + desc = "We evolve the ability to shoot our stingers at humans, with some preperation." + genomecost = 2 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_boost_range + +/datum/power/changeling/Epinephrine + name = "Epinephrine sacs" + desc = "We evolve additional sacs of adrenaline throughout our body." + helptext = "Gives the ability to instantly recover from stuns. High chemical cost." + genomecost = 3 + verbpath = /mob/proc/changeling_unstun + +/datum/power/changeling/ChemicalSynth + name = "Rapid Chemical-Synthesis" + desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." + helptext = "Doubles the rate at which we naturally recharge chemicals." + genomecost = 4 + isVerb = 0 + verbpath = /mob/proc/changeling_fastchemical +/* +/datum/power/changeling/AdvChemicalSynth + name = "Advanced Chemical-Synthesis" + desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." + helptext = "Doubles the rate at which we naturally recharge chemicals." + genomecost = 8 + isVerb = 0 + verbpath = /mob/proc/changeling_fastchemical +*/ +/datum/power/changeling/EngorgedGlands + name = "Engorged Chemical Glands" + desc = "Our chemical glands swell, permitting us to store more chemicals inside of them." + helptext = "Allows us to store an extra 25 units of chemicals." + genomecost = 4 + isVerb = 0 + verbpath = /mob/proc/changeling_engorgedglands + +/datum/power/changeling/DigitalCamoflague + name = "Digital Camoflauge" + desc = "We evolve the ability to distort our form and proprtions, defeating common altgorthms used to detect lifeforms on cameras." + helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us.. uncanny. We must constantly expend chemicals to maintain our form like this." + genomecost = 1 + allowduringlesserform = 1 + verbpath = /mob/proc/changeling_digitalcamo + +/datum/power/changeling/rapidregeneration + name = "Rapid Regeneration" + desc = "We evolve the ability to rapidly regenerate, negating the need for stasis." + helptext = "Heals a moderate amount of damage every tick." + genomecost = 7 + verbpath = /mob/proc/changeling_rapidregen + + + +////////////////////////////////////////////////////// +//DeadPhil Polaris Ability/////////////// +/////////////////////// +////////////////////////////////////////////////////// + + + + +/datum/power/changeling/recursive_enhancement + name = "Recursive Enhancement" + desc = "We cause our abilities to have increased or additional effects." + helptext = "To check the effects for each ability, check the blue text underneath the ability in the evolution menu." +// ability_icon_state = "ling_recursive_enhancement" + genomecost = 3 + verbpath = /mob/proc/changeling_recursive_enhancement + +//Increases macimum chemical storage +/mob/proc/changeling_recursive_enhancement() + set category = "Changeling" + set name = "Recursive Enhancement" + set desc = "Empowers our abilities." + var/datum/changeling/changeling = changeling_power(0,0,100,UNCONSCIOUS) + if(!changeling) + return 0 + if(src.mind.changeling.recursive_enhancement) + to_chat(src, "We will no longer empower our abilities.") + src.mind.changeling.recursive_enhancement = 0 + return 0 + to_chat(src, "We empower ourselves. Our abilities will now be extra potent.") + src.mind.changeling.recursive_enhancement = 1 + feedback_add_details("changeling_powers","RE") + return 1 + +/datum/power/changeling/arm_blade + name = "Arm Blade" + desc = "We reform one of our arms into a deadly blade." + helptext = "We may retract our armblade by dropping it. It can deflect projectiles." + enhancedtext = "The blade will have armor peneratration." +// ability_icon_state = "ling_armblade" + genomecost = 8 + verbpath = /mob/proc/changeling_arm_blade + +//Grows a scary, and powerful arm blade. +/mob/proc/changeling_arm_blade() + set category = "Changeling" + set name = "Arm Blade (20)" + + if(src.mind.changeling.recursive_enhancement) + if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/arm_blade/greater)) + to_chat(src, "We prepare an extra sharp blade.") + + return 1 + + else + if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/arm_blade)) + return 1 + return 0 + +//Claws +/datum/power/changeling/claw + name = "Claw" + desc = "We reform one of our arms into a deadly claw." + helptext = "We may retract our claw by dropping it." + enhancedtext = "The claw will have armor peneratration." +// ability_icon_state = "ling_claw" + genomecost = 6 + verbpath = /mob/proc/changeling_claw + +//Grows a scary, and powerful arm blade. +/mob/proc/changeling_claw() + set category = "Changeling" + set name = "Claw (15)" + + if(src.mind.changeling.recursive_enhancement) + if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/claw/greater, 1, 15)) + to_chat(src, "We prepare an extra sharp claw.") + return 1 + + else + if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/claw, 1, 15)) + return 1 + return 0 + +/obj/item/weapon/melee/changeling + name = "arm weapon" + desc = "A grotesque weapon made out of bone and flesh that cleaves through people as a hot knife through butter." + icon = 'icons/obj/weapons.dmi' + icon_state = "arm_blade" + w_class = ITEM_SIZE_HUGE + force = 5 + anchored = 1 + throwforce = 0 //Just to be on the safe side + throw_range = 0 + throw_speed = 0 + var/mob/living/creator //This is just like ninja swords, needed to make sure dumb shit that removes the sword doesn't make it stay around. + var/weapType = "weapon" + var/weapLocation = "arm" + +/obj/item/weapon/melee/changeling/New(location) + ..() + if(ismob(loc)) + visible_message("A grotesque weapon forms around [loc.name]\'s arm!", + "Our arm twists and mutates, transforming it into a deadly weapon.", + "You hear organic matter ripping and tearing!") + src.creator = loc + +/obj/item/weapon/melee/changeling/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/weapon/melee/changeling/dropped(mob/user) + visible_message("With a sickening crunch, [creator] reforms their arm!", + "We assimilate the weapon back into our body.", + "You hear organic matter ripping and tearing!") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + spawn(1) + if(src) + qdel(src) + +/obj/item/weapon/melee/changeling/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/* /obj/item/weapon/melee/changeling/suicide_act(mob/user) + viewers(user) << "[user] is impaling \himself the [src.name]! It looks like \he's trying to commit suicide." + return +*/ + +/obj/item/weapon/melee/changeling/Process() //Stolen from ninja swords. + 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/melee/changeling/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_state = "arm_blade" + force = 40 + armor_penetration = 15 + sharp = 1 + edge = 1 + anchored = 1 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/melee/changeling/arm_blade/greater + name = "arm greatblade" + desc = "A grotesque blade made out of bone and flesh that cleaves through people and armor as a hot knife through butter." + armor_penetration = 30 + +/obj/item/weapon/melee/changeling/claw + name = "hand claw" + desc = "A grotesque claw made out of bone and flesh that cleaves through people as a hot knife through butter." + icon_state = "ling_claw" + force = 15 + sharp = 1 + edge = 1 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/melee/changeling/claw/greater + name = "hand greatclaw" + force = 20 + armor_penetration = 20 + anchored = 1 + + +/datum/power/changeling/electric_lockpick + name = "Electric Lockpick" + desc = "We discreetly evolve a finger to be able to send a small electric charge. \ + We can open most electrical locks, but it will be obvious when we do so." + helptext = "Use the ability, then touch something that utilizes an electrical locking system, to open it. Each use costs 10 chemicals." +// ability_icon_state = "ling_electric_lockpick" + genomecost = 10 + verbpath = /mob/proc/changeling_electric_lockpick + +//Emag-lite +/mob/proc/changeling_electric_lockpick() + set category = "Changeling" + set name = "Electric Lockpick (5 + 10/use)" + set desc = "Bruteforces open most electrical locking systems, at 10 chemicals per use." + + var/datum/changeling/changeling = changeling_power(5,0,100,CONSCIOUS) + + var/obj/held_item = get_active_hand() + + if(!changeling) + return 0 + + if(held_item == null) + if(changeling_generic_weapon(/obj/item/weapon/finger_lockpick,0,5)) //Chemical cost is handled in the equip proc. + return 1 + return 0 + +/obj/item/weapon/finger_lockpick + name = "finger lockpick" + desc = "This finger appears to be an organic datajack." + icon = 'icons/obj/weapons.dmi' + icon_state = "electric_hand" + +/obj/item/weapon/finger_lockpick/New() + if(ismob(loc)) + loc << "We shape our finger to fit inside electronics, and are ready to force them open." + +/obj/item/weapon/finger_lockpick/dropped(mob/user) + to_chat(user, "We discreetly shape our finger back to a less suspicious form.") + spawn(1) + if(src) + qdel(src) + +/obj/item/weapon/finger_lockpick/afterattack(var/atom/target, var/mob/living/user, proximity) + if(!target) + return + if(!proximity) + return + if(!user.mind.changeling) + return + + var/datum/changeling/ling_datum = user.mind.changeling + + if(ling_datum.chem_charges < 10) + to_chat(user, "We require more chemicals to do that.") + return + + //Airlocks require an ugly block of code, but we don't want to just call emag_act(), since we don't want to break airlocks forever. + if(istype(target,/obj/machinery/door)) + var/obj/machinery/door/door = target + to_chat(user, "We send an electrical pulse up our finger, and into \the [target], attempting to open it.") + + if(door.density && door.operable()) + door.do_animate("spark") + sleep(6) + //More typechecks, because windoors can't be locked. Fun. + if(istype(target,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/airlock = target + + if(airlock.locked) //Check if we're bolted. + airlock.unlock() + to_chat(user, "We've unlocked \the [airlock]. Another pulse is requried to open it.") + else //We're not bolted, so open the door already. + airlock.open() + to_chat(user, "We've opened \the [airlock].") + else + door.open() //If we're a windoor, open the windoor. + to_chat(user, "We've opened \the [door].") + else //Probably broken or no power. + to_chat(user, "The door does not respond to the pulse.") + door.add_fingerprint(user) + log_and_message_admins("finger-lockpicked \an [door].") + ling_datum.chem_charges -= 10 + return 1 + + else if(istype(target,/obj/)) //This should catch everything else we might miss, without a million typechecks. + var/obj/O = target + to_chat(user, "We send an electrical pulse up our finger, and into \the [O].") + O.add_fingerprint(user) + O.emag_act(1,user,src) + log_and_message_admins("finger-lockpicked \an [O].") + ling_datum.chem_charges -= 10 + + return 1 + return 0 + +//////////////////////////////////////////// +//////////////////Invisible deadphil polaris//////////////// +//////////////////////////////////////////// + +/datum/power/changeling/visible_camouflage + name = "Camouflage" + desc = "We rapidly shape the color of our skin and secrete easily reversible dye on our clothes, to blend in with our surroundings. \ + We are undetectable, so long as we move slowly.(Toggle)" + helptext = "Running, and performing most acts will reveal us. Our chemical regeneration is halted while we are hidden." + enhancedtext = "Can run while hidden." +// ability_icon_state = "ling_camoflage" + genomecost = 10 + verbpath = /mob/proc/changeling_visible_camouflage + +//Hide us from anyone who would do us harm. +/mob/proc/changeling_visible_camouflage() + set category = "Changeling" + set name = "Visible Camouflage (10)" + set desc = "Turns yourself almost invisible, as long as you move slowly." + + + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + + if(H.mind.changeling.cloaked) + H.mind.changeling.cloaked = 0 + return 1 + + //We delay the check, so that people can uncloak without needing 10 chemicals to do so. + var/datum/changeling/changeling = changeling_power(10,0,100,CONSCIOUS) + + if(!changeling) + return 0 + changeling.chem_charges -= 10 + var/old_regen_rate = H.mind.changeling.chem_recharge_rate + + to_chat(H, "We vanish from sight, and will remain hidden, so long as we move carefully.") + H.mind.changeling.cloaked = 1 + H.mind.changeling.chem_recharge_rate = 0 + animate(src,alpha = 255, alpha = 10, time = 10) + + var/must_walk = TRUE + if(src.mind.changeling.recursive_enhancement) + must_walk = FALSE + to_chat(src, "We may move at our normal speed while hidden.") + + if(must_walk) + H.set_m_intent("walk") + + var/remain_cloaked = TRUE + while(remain_cloaked) //This loop will keep going until the player uncloaks. + sleep(1 SECOND) // Sleep at the start so that if something invalidates a cloak, it will drop immediately after the check and not in one second. + + if(H.m_intent != "walk" && must_walk) // Moving too fast uncloaks you. + remain_cloaked = 0 + if(!H.mind.changeling.cloaked) + remain_cloaked = 0 + if(H.stat) // Dead or unconscious lings can't stay cloaked. + remain_cloaked = 0 + if(H.incapacitated(INCAPACITATION_DISABLED)) // Stunned lings also can't stay cloaked. + remain_cloaked = 0 + + if(mind.changeling.chem_recharge_rate != 0) //Without this, there is an exploit that can be done, if one buys engorged chem sacks while cloaked. + old_regen_rate += mind.changeling.chem_recharge_rate //Unfortunately, it has to occupy this part of the proc. This fixes it while at the same time + mind.changeling.chem_recharge_rate = 0 //making sure nobody loses out on their bonus regeneration after they're done hiding. + + + + H.invisibility = initial(invisibility) + visible_message("[src] suddenly fades in, seemingly from nowhere!", + "We revert our camouflage, revealing ourselves.") + H.set_m_intent("run") + H.mind.changeling.cloaked = 0 + H.mind.changeling.chem_recharge_rate = old_regen_rate + + animate(src,alpha = 10, alpha = 255, time = 10) + +//////////////////////////////////////////////////////// +////////////////////end invisible/////////////////// +//////////////////////////////////////////////////////// + + + + +// Modularchangling, totally stolen from the new player panel. YAYY +/datum/changeling/proc/EvolutionMenu()//The new one + set category = "Changeling" + set desc = "Level up!" + + if(!usr || !usr.mind || !usr.mind.changeling) return + src = usr.mind.changeling + + if(!powerinstances.len) + for(var/P in powers) + powerinstances += new P() + + var/dat = "Changling Evolution Menu" + + //javascript, the part that does most of the work~ + dat += {" + + + + + + + "} + + //body tag start + onload and onkeypress (onkeyup) javascript event calls + dat += "" + + //title + search bar + dat += {" + + + + + + + + +
+ Changling Evolution Menu
+ Hover over a power to see more information
+ Current evolution points left to evolve with: [geneticpoints]
+ Absorb genomes to acquire more evolution points +

+

+ Search: +
+ + "} + + //player table header + dat += {" + + "} + + var/i = 1 + for(var/datum/power/changeling/P in powerinstances) + var/ownsthis = 0 + + if(P in purchasedpowers) + ownsthis = 1 + + + var/color = "#e6e6e6" + if(i%2 == 0) + color = "#f2f2f2" + + + dat += {" + + + + + + "} + + i++ + + + //player table ending + dat += {" +
+ + + Evolve [P] - Cost: [ownsthis ? "Purchased" : P.genomecost] + +
+
+
+ + + + "} + + usr << browse(dat, "window=powers;size=900x480") + + +/datum/changeling/Topic(href, href_list) + ..() + if(!ismob(usr)) + return + + if(href_list["P"]) + var/datum/mind/M = usr.mind + if(!istype(M)) + return + purchasePower(M, href_list["P"]) + call(/datum/changeling/proc/EvolutionMenu)() + + + +/datum/changeling/proc/purchasePower(var/datum/mind/M, var/Pname, var/remake_verbs = 1) + if(!M || !M.changeling) + return + + var/datum/power/changeling/Thepower = Pname + + + for (var/datum/power/changeling/P in powerinstances) +// log_debug("[P] - [Pname] = [P.name == Pname ? "True" : "False"]") + + if(P.name == Pname) + Thepower = P + break + + + if(Thepower == null) + to_chat(M.current, "This is awkward. Changeling power purchase failed, please report this bug to a coder!") + return + + if(Thepower in purchasedpowers) + to_chat(M.current, "We have already evolved this ability!") + return + + + if(geneticpoints < Thepower.genomecost) + to_chat(M.current, "We cannot evolve this... yet. We must acquire more DNA.") + return + + geneticpoints -= Thepower.genomecost + + purchasedpowers += Thepower + + if(!Thepower.isVerb && Thepower.verbpath) + call(M.current, Thepower.verbpath)() + else if(remake_verbs) + M.current.make_changeling() + diff --git a/icons/mob/items/lefthand.dmi b/icons/mob/items/lefthand.dmi index 8479b89..4a92577 100644 Binary files a/icons/mob/items/lefthand.dmi and b/icons/mob/items/lefthand.dmi differ diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi index 931a4f5..49a78fc 100644 Binary files a/icons/mob/items/righthand.dmi and b/icons/mob/items/righthand.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 3b05964..1e956c9 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ