[MIRROR] Changing changeling (Refactor) (#11142)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-07-04 19:54:55 -07:00
committed by GitHub
parent 9feb91ec4c
commit a0c273ce1f
83 changed files with 1385 additions and 1382 deletions

View File

@@ -0,0 +1,31 @@
///Component that holds the antag trait. This is the base version.
/datum/component/antag
var/mob/living/owner
dupe_mode = COMPONENT_DUPE_UNIQUE //Only one type.
/datum/component/antag/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
///Should never be destroyed as these are applied to the mind.
/datum/component/antag/Destroy(force = FALSE)
if(!force)
return QDEL_HINT_LETMELIVE
owner = null
. = ..()
///Antag datum that is held on /datum/mind. Holds all the antag data.
/datum/antag_holder
var/datum/component/antag/changeling/changeling
var/is_antag = FALSE
/datum/antag_holder/proc/apply_antags(mob/M)
if(!M)
return
if(changeling)
M.make_changeling()
is_antag = TRUE
/datum/antag_holder/proc/is_antag()
return is_antag

View File

@@ -0,0 +1,474 @@
///Changeling component.
///Stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
GLOBAL_LIST_INIT(possible_changeling_IDs,list("Alpha","Beta","Chi","Delta","Epsilon","Eta","Gamma","Iota","Kappa","Lambda","Mu","Nu","Omega","Omicron","Phi","Pi","Psi","Rho","Sigma","Tau","Theta","Upsilon","Xi","Zeta")) //ALPHABETICAL ORDER.
//Needs cleanup
var/list/powers = subtypesof(/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.
var/make_hud_button = TRUE // Is this ability significant enough to dedicate screen space for a HUD button?
var/ability_icon_state = null // icon_state for icons for the ability HUD. Must be in screen_spells.dmi.
/datum/power/changeling
var/allowduringlesserform = FALSE
var/genomecost = 500000 // Cost for the changeling to evolve this power.
/datum/component/antag/changeling
var/list/datum/absorbed_dna/absorbed_dna = list()
var/list/absorbed_languages = list() // Necessary because of set_species stuff
var/absorbedcount = 0
var/lingabsorbedcount = 1 //Starts at one, because that's us
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 = FALSE
var/geneticpoints = 7
var/max_geneticpoints = 7
var/readapts = 1
var/max_readapts = 2
var/list/purchased_powers = list()
var/mimicing = ""
var/cloaked = FALSE
var/is_reviving = FALSE
var/armor_deployed = FALSE //This is only used for changeling_generic_equip_all_slots() at the moment.
var/recursive_enhancement = FALSE //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/thermal_sight = FALSE // Is our Vision Augmented? With thermals?
var/datum/changeling_panel/power_panel //Our changeling eveolution panel. Generated the first time we try to open the panel.
dupe_mode = COMPONENT_DUPE_UNIQUE //Only the first changeling application survives!
var/cooldown_time = 1 SECOND // Sting anti-spam.
var/last_used_sting_time = 0 // world.time when we used last used a power.
var/list/changeling_cooldowns = list(
CRYO_STING = 0,
ESCAPE_RESTRAINTS = 0,
FAKE_DEATH = 0,
FLESHMEND = 0,
CHANGELING_SCREECH = 0
)
///Checks if a mind or a mob is a changeling.
///Checks to see if the thing fed to it is a changeling first, then does some deeper searching.
/proc/is_changeling(mob/M)
var/datum/component/antag/changeling/changeling = (M.GetComponent(/datum/component/antag/changeling))
if(changeling) // Whatever we fed it is a changeling. Return it.
return changeling
//The below is what happens if we fail the above. We do some deeper searching.
if(istype(M, /datum/mind)) //Fed a mind and we failed.
var/datum/mind/our_mind = M
if(our_mind.current)
changeling = (our_mind.current.GetComponent(/datum/component/antag/changeling)) //Check to see if the mob we are currently inhabiting is a changeling.
else //Fed it a mob and we failed
if(M.mind)
changeling = M.mind.antag_holder.changeling //Check our mind's antag holder.
return changeling
///Handles the cooldown for the power. Returns TRUE if the cooldown has passed. FALSE if it's still on cooldown.
///This is just a general anti-spam thing and not really a true cooldown
/datum/component/antag/changeling/proc/handle_cooldown()
if(world.time > last_used_sting_time+cooldown_time)
last_used_sting_time = world.time
return TRUE
return FALSE
/datum/component/antag/changeling/proc/get_cooldown(id)
return changeling_cooldowns[id]
/datum/component/antag/changeling/proc/set_cooldown(id, cooldown_time)
changeling_cooldowns[id] = world.time + cooldown_time
/datum/component/antag/changeling/proc/is_on_cooldown(id)
return (world.time < changeling_cooldowns[id])
/datum/component/antag/changeling/Initialize()
..()
if(owner)
if(GLOB.possible_changeling_IDs.len)
changelingID = pick(GLOB.possible_changeling_IDs)
GLOB.possible_changeling_IDs -= changelingID
changelingID = "[changelingID]"
else
changelingID = "[rand(1,999)]"
add_verb(owner,/mob/proc/EvolutionMenu)
add_verb(owner,/mob/proc/changeling_respec)
owner.add_language("Changeling")
///This is a component that is referenced to by the mind, so it should never be deleted
/datum/component/antag/changeling/Destroy(force = FALSE)
if(!force)
return QDEL_HINT_LETMELIVE
return ..()
//Old code from when it did destroy itself.
/*
if(owner)
remove_verb(owner,/mob/proc/EvolutionMenu)
remove_verb(owner,/mob/proc/changeling_respec)
qdel_null(power_panel)
absorbed_dna.Cut()
absorbed_languages.Cut()
purchased_powers.Cut()
purchased_powers_history.Cut()
. = ..()
*/
//Former /datum/changeling procs
/datum/component/antag/changeling/proc/regenerate()
chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage)
geneticdamage = max(0, geneticdamage-1)
/datum/component/antag/changeling/proc/GetDNA(var/dna_owner)
for(var/datum/absorbed_dna/DNA in absorbed_dna)
if(dna_owner == DNA.name)
return DNA
//Former /mob procs
/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!comp)
return
for(var/language in newDNA.languages)
comp.absorbed_languages |= language
changeling_update_languages(comp.absorbed_languages)
if(!comp.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
comp.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
//The current mob is made a changeling AND the mind is made a changeling.
var/datum/component/antag/changeling/comp = LoadComponent(/datum/component/antag/changeling)
mind.antag_holder.changeling = comp
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 comp.purchased_powers)) // Do we not have it already?
comp.purchasePower(comp.owner, P.name, 0)// Purchase it. Don't remake our verbs, we're doing it after this.
for(var/datum/power/changeling/P in comp.purchased_powers)
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform)
continue
if(!(P in src.verbs))
add_verb(src, P.verbpath)
if(P.make_hud_button)
if(!src.ability_master)
src.ability_master = new /obj/screen/movable/ability_master(src)
src.ability_master.add_ling_ability(
object_given = src,
verb_given = P.verbpath,
name_given = P.name,
ability_icon_given = P.ability_icon_state,
arguments = list()
)
for(var/language in languages)
comp.absorbed_languages |= language
var/mob/living/carbon/human/H = src
if(istype(H))
add_verb(H, /mob/living/carbon/human/proc/innate_shapeshifting)
var/saved_dna = H.dna.Clone() /// Prevent transform from breaking.
var/datum/absorbed_dna/newDNA = new(H.real_name, saved_dna, H.species.name, H.languages, H.identifying_gender, H.flavor_texts, H.modifiers)
absorbDNA(newDNA)
//Code to make it so our BR is marked as a changeling body, so it can't be stolen.
for(var/key in SStranscore.databases)
var/datum/transcore_db/db = SStranscore.databases[key]
if(H.mind.name in db.body_scans)
var/datum/transhuman/body_record/BR = db.body_scans[H.mind.name]
BR.changeling_locked = TRUE
return TRUE
//removes our changeling verbs
/mob/proc/remove_changeling_powers()
if(!mind)
return
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!comp)
return
for(var/datum/power/changeling/P in comp.purchased_powers)
if(P.isVerb)
remove_verb(src, P.verbpath)
var/obj/screen/ability/verb_based/changeling/C = ability_master.get_ability_by_proc_ref(P.verbpath)
if(C)
ability_master.remove_ability(C)
//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/component/antag/changeling/comp = is_changeling(src)
if(!comp)
to_world_log("[src] used a changeling verb but is not a changeling.")
return
if(src.stat > max_stat)
to_chat(src, span_warning("We are incapacitated."))
return
if(comp.absorbed_dna.len < required_dna)
to_chat(src, span_warning("We require at least [required_dna] samples of compatible DNA."))
return
if(comp.chem_charges < required_chems)
to_chat(src, span_warning("We require at least [required_chems] units of chemicals to do that!"))
return
if(comp.geneticdamage > max_genetic_damage)
to_chat(src, span_warning("Our genomes are still reassembling. We need time to recover first."))
return
return comp
//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")
//////////
//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, span_warning("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/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail
to_chat(src, span_warning("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/datum/component/antag/changeling/comp = changeling_power(required_chems)
if(!comp)
return
if(!comp.handle_cooldown())
to_chat(src, span_warning("We are still recovering from our last sting."))
return
var/list/victims = list()
for(var/mob/living/carbon/C in oview(comp.sting_range))
victims += C
var/mob/living/carbon/T = tgui_input_list(src, "Who will we sting?", "Sting!", victims)
if(!T)
return
if(!comp.handle_cooldown())//Check again in case we have multiple windows open at once.
to_chat(src, span_warning("We are still recovering from our last sting."))
return
if(T.isSynthetic())
to_chat(src, span_notice("We are unable to pierce the outer shell of [T]."))
return
if(!(T in view(comp.sting_range))) return
if(!sting_can_reach(T, comp.sting_range)) return
if(!changeling_power(required_chems)) return
comp.chem_charges -= required_chems
comp.sting_range = 1
to_chat(src, span_notice("We stealthily sting [T]."))
var/datum/component/antag/changeling/target_comp = is_changeling(T)
if(!T.mind || !target_comp)
return T //T will be affected by the sting
to_chat(T, span_warning("You feel a tiny prick.")) //Stings on other lings have no effect, but they know you're a ling, too.
return
//Former /turf procs
/turf/proc/AdjacentTurfsRangedSting()
//Yes this is snowflakey, but I couldn't get it to work any other way.. -Luke
var/list/allowed = list(
/obj/structure/table,
/obj/structure/closet,
/obj/structure/frame,
/obj/structure/target_stake,
/obj/structure/cable,
/obj/structure/disposalpipe,
/obj/machinery,
/mob
)
var/L[] = new()
for(var/turf/simulated/t in oview(src,1))
var/add = 1
if(t.density)
add = 0
if(add && LinkBlocked(src,t))
add = 0
if(add && TurfBlockedNonWindow(t))
add = 0
for(var/obj/O in t)
if(O.density)
add = 0
break
if(istype(O, /obj/machinery/door))
//not sure why this doesn't fire on LinkBlocked()
add = 0
break
for(var/type in allowed)
if (istype(O, type))
add = 1
break
if(!add)
break
if(add)
L.Add(t)
return L
/mob/proc/EvolutionMenu()
set name = "-Evolution Menu-"
set category = "Changeling"
set desc = "Adapt yourself carefully."
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!comp)
to_chat(src, "You are not a changeling!")
return
if(!powerinstances.len)
for(var/changeling_power in powers)
powerinstances += new changeling_power()
if(!comp.power_panel)
comp.power_panel = new()
comp.power_panel.comp = comp
comp.power_panel.tgui_interact(src)
///Purchasing a power. Called by the Evolution Panel.
/datum/component/antag/changeling/proc/purchasePower(var/mob/owner, var/Pname, var/remake_verbs = 1)
var/datum/power/changeling/Thepower = Pname
for (var/datum/power/changeling/P in powerinstances)
//to_world("[P] - [Pname] = [P.name == Pname ? "True" : "False"]")
if(P.name == Pname)
Thepower = P
break
if(Thepower == null)
to_chat(owner, "This is awkward. Changeling power purchase failed, please report this bug to a coder!")
return
if(Thepower in purchased_powers)
to_chat(owner, "We have already evolved this ability!")
return
if(geneticpoints < Thepower.genomecost)
to_chat(owner, "We cannot evolve this... yet. We must acquire more DNA.")
return
geneticpoints -= Thepower.genomecost
purchased_powers += Thepower
if(Thepower.genomecost > 0)
purchased_powers_history.Add("[Pname] ([Thepower.genomecost] points)")
if(Thepower.make_hud_button && Thepower.isVerb)
if(owner.ability_master)
owner.ability_master = new /obj/screen/movable/ability_master(owner)
owner.ability_master.add_ling_ability(
object_given = owner,
verb_given = Thepower.verbpath,
name_given = Thepower.name,
ability_icon_given = Thepower.ability_icon_state,
arguments = list()
)
if(!Thepower.isVerb && Thepower.verbpath)
call(owner, Thepower.verbpath)()
else if(remake_verbs)
owner.make_changeling()
//Debug item. Here because during debugging I DO NOT want to have to open the player panel 5000 times.
/obj/item/toy/katana/changeling_debug
name = "Katana of the Changeling"
desc = "A katana imbued with special powers. It is said that those who wield it will become a changeling."
/obj/item/toy/katana/changeling_debug/attack_self(mob/user)
user.make_changeling()
///Changeling Panel
/datum/changeling_panel
var/datum/component/antag/changeling/comp
/datum/changeling_panel/Destroy(force)
comp = null
. = ..()
/datum/changeling_panel/tgui_state(mob/user)
return GLOB.tgui_always_state
/datum/changeling_panel/tgui_status(mob/user)
if(!isliving(user)) //We ghosted or something.
return STATUS_CLOSE
return ..()
/datum/changeling_panel/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src,"ChangelingPanel", "Changeling Evolution Panel", parent_ui)
ui.open()
/datum/changeling_panel/tgui_data(mob/living/carbon/human/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = list()
var/list/power_list = list()
for(var/datum/power/changeling/P in powerinstances)
var/list/all_powers = list(
"power_name" = P.name,
"power_cost" = P.genomecost,
"power_purchased" = (P in comp.purchased_powers),
"power_desc" = P.desc,
)
UNTYPED_LIST_ADD(power_list, all_powers)
data["available_points"] = comp.geneticpoints
data["power_list"] = power_list
return data
/datum/changeling_panel/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("evolve_power")
comp.purchasePower(comp.owner, params["val"]) //The power must be the power's NAME.
return TRUE
return TRUE

View File

@@ -0,0 +1,22 @@
/datum/absorbed_dna
var/name
var/datum/dna/dna
var/speciesName
var/list/languages
var/identifying_gender
var/list/flavour_texts
var/list/genMods
/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour, var/list/newGenMods)
..()
name = newName
qdel_swap(dna, newDNA)
speciesName = newSpecies
languages = newLanguages
identifying_gender = newIdentifying_Gender
flavour_texts = newFlavour ? newFlavour.Copy() : null
genMods = newGenMods ? newGenMods.Copy() : null
/datum/absorbed_dna/Destroy()
. = ..()
qdel(dna)

View File

@@ -0,0 +1,254 @@
//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/component/antag/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(span_warning("[M] casts off their [M.wear_suit.name]!"),
span_warning("We cast off our [M.wear_suit.name]"),
span_warningplain("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
to_chat(src, span_warning("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)
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/component/antag/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(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(span_warning("[src] pulls on their clothes, peeling it off along with parts of their skin attached!"),
span_notice("We remove and deform our equipment."))
changeling.armor_deployed = 0
return success
else
to_chat(M, span_notice("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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
success = 1
sleep(1 SECOND)
var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
to_chat(M, span_notice("We have grown [feedback]."))
if(success)
changeling.armor_deployed = 1
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/component/antag/changeling/changeling = changeling_power(cost,1,100,CONSCIOUS)
if(!changeling)
return
if(!ishuman(src))
return 0
var/mob/living/carbon/human/M = src
if(M.hands_are_full()) //Make sure our hands aren't full.
to_chat(src, span_warning("Our hands are full. Drop something first."))
return 0
var/obj/item/W = new weapon_type(src)
src.put_in_hands(W)
changeling.chem_charges -= cost
if(make_sound)
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
return 1

View File

@@ -0,0 +1,142 @@
//Updated
/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 if they were of our kind."
ability_icon_state = "ling_absorb_dna"
genomecost = 0
verbpath = /mob/living/proc/changeling_absorb_dna
//Absorbs the victim's DNA. Requires a strong grip on the victim.
//Doesn't cost anything as it's the most basic ability.
/mob/living/proc/changeling_absorb_dna()
set category = "Changeling"
set name = "Absorb DNA"
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100) //Our changeling power
if(!changeling) return
var/obj/item/grab/G = src.get_active_hand()
if(!istype(G))
to_chat(src, span_warning("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) || T.isSynthetic())
to_chat(src, span_warning("\The [T] is not compatible with our biology."))
return
if(T.species.flags & (NO_DNA|NO_SLEEVE))
to_chat(src, span_warning("We do not know how to parse this creature's DNA!"))
return
var/datum/component/antag/changeling/target_changeling = is_changeling(T) //If the target is a changeling
if(HUSK in T.mutations) //Lings can always absorb other lings, unless someone beat them to it first.
if(!target_changeling || target_changeling && target_changeling.geneticpoints < 0)
to_chat(src, span_warning("This creature's DNA is ruined beyond useability!"))
return
if(G.state != GRAB_KILL)
to_chat(src, span_warning("We must have a tighter grip to absorb this creature."))
return
if(changeling.isabsorbing)
to_chat(src, span_warning("We are already absorbing!"))
return
changeling.isabsorbing = TRUE
for(var/stage = 1, stage<=3, stage++)
switch(stage)
if(1)
to_chat(src, span_notice("This creature is compatible. We must hold still..."))
if(2)
to_chat(src, span_notice("We extend a proboscis."))
src.visible_message(span_warning("[src] extends a proboscis!"))
if(3)
to_chat(src, span_notice("We stab [T] with the proboscis."))
src.visible_message(span_danger("[src] stabs [T] with the proboscis!"))
to_chat(T, span_danger("You feel a sharp stabbing pain!"))
var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting)
if(affecting.take_damage(39,0,1,0,"large organic needle"))
T.UpdateDamageIcon()
feedback_add_details("changeling_powers","A[stage]")
if(!do_mob(src, T, 150) || G.state != GRAB_KILL)
to_chat(src, span_warning("Our absorption of [T] has been interrupted!"))
changeling.isabsorbing = FALSE
return
to_chat(src, span_notice("We have absorbed [T]!"))
add_attack_logs(src,T,"Absorbed (changeling)")
visible_message(span_danger("[src] sucks the fluids from [T]!"))
to_chat(T, span_danger("You have been absorbed by the changeling!"))
changeling_obtain_dna(T, changeling, target_changeling)
changeling.isabsorbing = FALSE
T.death(FALSE)
T.Drain()
return 1
///Proc that does the actual 'obtaining DNA' part for changelings. Has four arguments: Our victim, our changeling component, the target's changeling component, and if we drain the victim's nutrition or not.
/mob/living/proc/changeling_obtain_dna(mob/living/carbon/human/victim, datum/component/antag/changeling/changeling, datum/component/antag/changeling/target_changeling, drain = TRUE)
if(!victim || !ishuman(victim)) //There MUST be a victim and it MUST be a human and NOT a monkey!
return
if(!target_changeling)
target_changeling = is_changeling(victim) //Let's see if the victim is a changeling or not.
if(!target_changeling && isMonkey(victim)) //No absorbing non-changeling monkeys.
return
//If we weren't fed a changeling component, we get it ourselves. If that fails, we see if the target is a changeling. If so, they get the DNA of the person predding them. Preyling!
if(!changeling)
changeling = is_changeling(src)
if(!changeling && target_changeling) //Prey is a ling but owner is not.
changeling_obtain_dna(src, target_changeling, drain = FALSE) //Flip the tables!~ Don't steal the pred's nutrition, though!
return
else if(!changeling) //Neither pred or prey are owner.
return
var/saved_dna = victim.dna.Clone()
var/datum/absorbed_dna/newDNA = new(victim.real_name, saved_dna, victim.species.name, victim.languages, victim.identifying_gender, victim.flavor_texts, victim.modifiers)
if(changeling.GetDNA(newDNA.name))
qdel(newDNA)
return //No double dipping! You already ate or absorbed them once this shift, glutton!
absorbDNA(newDNA)
if(drain)
adjust_nutrition(victim.nutrition)
changeling.chem_charges += 10
if(changeling.readapts <= 0)
changeling.readapts = 0 //SANITYYYYYY
changeling.readapts++
//Let's give them a genetic point for absorbing someone...Because honestly if you absorb people you SHOULD get stronger.
changeling.max_geneticpoints++
changeling.geneticpoints++
if(changeling.readapts > changeling.max_readapts)
changeling.readapts = changeling.max_readapts
to_chat(src, span_notice("We can now re-adapt, reverting our evolution so that we may start anew, if needed."))
if(victim.mind && target_changeling)
if(target_changeling.absorbed_dna)
for(var/datum/absorbed_dna/dna_data in target_changeling.absorbed_dna) //steal all their loot
if(dna_data in changeling.absorbed_dna)
continue
absorbDNA(dna_data)
changeling.absorbedcount++
target_changeling.absorbed_dna.len = 1
// This is where lings get boosts from eating eachother
if(target_changeling.lingabsorbedcount)
for(var/a = 1 to target_changeling.lingabsorbedcount)
changeling.lingabsorbedcount++
changeling.geneticpoints += 4
changeling.max_geneticpoints += 4
to_chat(src, span_notice("We absorbed another changeling, and we grow stronger. Our genomes increase."))
target_changeling.chem_charges = 0
target_changeling.geneticpoints = -1
target_changeling.max_geneticpoints = -1 //To prevent revival.
target_changeling.absorbedcount = 0
target_changeling.lingabsorbedcount = 0
changeling.absorbedcount++

View File

@@ -0,0 +1,155 @@
//Updated
/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 = 2
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)"
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!comp)
return
if(comp.recursive_enhancement)
if(changeling_generic_weapon(/obj/item/melee/changeling/arm_blade/greater))
to_chat(src, span_notice("We prepare an extra sharp blade."))
return 1
else
if(changeling_generic_weapon(/obj/item/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 = 1
verbpath = /mob/proc/changeling_claw
//Grows a scary, and powerful claw.
/mob/proc/changeling_claw()
set category = "Changeling"
set name = "Claw (15)"
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!comp)
return
if(comp.recursive_enhancement)
if(changeling_generic_weapon(/obj/item/melee/changeling/claw/greater, 1, 15))
to_chat(src, span_notice("We prepare an extra sharp claw."))
return 1
else
if(changeling_generic_weapon(/obj/item/melee/changeling/claw, 1, 15))
return 1
return 0
/obj/item/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 = ITEMSIZE_HUGE
force = 5
anchored = TRUE
throwforce = 0 //Just to be on the safe side
throw_range = 0
throw_speed = 0
embed_chance = 0 //No embedding.
destroy_on_drop = TRUE
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"
defend_chance = 40 // The base chance for the weapon to parry.
projectile_parry_chance = 15 // The base chance for a projectile to be deflected.
/obj/item/melee/changeling/Initialize(mapload)
. = ..()
if(ismob(loc))
visible_message(span_warning("A grotesque weapon forms around [loc.name]\'s arm!"),
span_warning("Our arm twists and mutates, transforming it into a deadly weapon."),
span_warningplain("You hear organic matter ripping and tearing!"))
src.creator = loc
/obj/item/melee/changeling/dropped(mob/user)
..()
visible_message(span_warning("With a sickening crunch, [creator] reforms their arm!"),
span_notice("We assimilate the weapon back into our body."),
span_warningplain("You hear organic matter ripping and tearing!"))
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
/obj/item/melee/changeling/Destroy()
creator = null
. = ..()
/obj/item/melee/changeling/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(default_parry_check(user, attacker, damage_source) && prob(defend_chance))
user.visible_message(span_danger("\The [user] parries [attack_text] with \the [src]!"))
playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
user.visible_message(span_danger("\The [user] deflects [attack_text] with \the [src]!"))
playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
return 0
/obj/item/melee/changeling/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
if(user.incapacitated() || !istype(damage_source, /obj/item/projectile))
return 0
var/bad_arc = reverse_direction(user.dir)
if(!check_shield_arc(user, bad_arc, damage_source, attacker))
return 0
return 1
/obj/item/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 = TRUE
edge = TRUE
pry = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
defend_chance = 60
projectile_parry_chance = 25
/obj/item/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
defend_chance = 70
projectile_parry_chance = 35
/obj/item/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 = TRUE
edge = TRUE
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
defend_chance = 50
projectile_parry_chance = 15
/obj/item/melee/changeling/claw/greater
name = "hand greatclaw"
force = 20
armor_penetration = 20
pry = 1
defend_chance = 60
projectile_parry_chance = 25

View File

@@ -0,0 +1,138 @@
//Updated
/datum/power/changeling/space_suit
name = "Organic Space Suit"
desc = "We grow an organic suit to protect ourselves from space exposure."
helptext = "To remove the suit, use the ability again."
ability_icon_state = "ling_space_suit"
genomecost = 0 //Have a free spacesuit. It's not worth buying. If you want a special version, get the armor.
verbpath = /mob/proc/changeling_spacesuit
/mob/proc/changeling_spacesuit()
set category = "Changeling"
set name = "Organic Space Suit (20)"
if(changeling_generic_armor(/obj/item/clothing/suit/space/changeling,/obj/item/clothing/head/helmet/space/changeling,/obj/item/clothing/shoes/magboots/changeling, 20))
return 1
return 0
/datum/power/changeling/armor
name = "Chitinous Spacearmor"
desc = "We turn our skin into tough chitin to protect us from damage and space exposure."
helptext = "To remove the armor, use the ability again."
ability_icon_state = "ling_armor"
genomecost = 3
verbpath = /mob/proc/changeling_spacearmor
/mob/proc/changeling_spacearmor()
set category = "Changeling"
set name = "Organic Spacearmor (20)"
if(changeling_generic_armor(/obj/item/clothing/suit/space/changeling/armored,/obj/item/clothing/head/helmet/space/changeling/armored,/obj/item/clothing/shoes/magboots/changeling/armored, 20))
return 1
return 0
//Space suit
/obj/item/clothing/suit/space/changeling
name = "flesh mass"
icon_state = "lingspacesuit"
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
flags = 0 //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it,
//it still ends up in your blood. (also balance but muh fluff)
destroy_on_drop = TRUE
allowed = list(POCKET_GENERIC, POCKET_ALL_TANKS)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) //No armor at all.
canremove = FALSE
/obj/item/clothing/suit/space/changeling/Initialize(mapload)
. = ..()
if(ismob(loc))
loc.visible_message(span_warning("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!"),
span_warning("We inflate our flesh, creating a spaceproof suit!"),
span_warningplain("You hear organic matter ripping and tearing!"))
/obj/item/clothing/head/helmet/space/changeling
name = "flesh mass"
icon_state = "lingspacehelmet"
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
flags = BLOCKHAIR //Again, no THICKMATERIAL.
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
body_parts_covered = HEAD|FACE|EYES
canremove = FALSE
destroy_on_drop = TRUE
/obj/item/clothing/shoes/magboots/changeling
desc = "A suction cupped mass of flesh, shaped like a foot."
name = "fleshy grippers"
icon_state = "lingspacesuit"
actions_types = list(/datum/action/item_action/toggle_grippers)
canremove = FALSE
destroy_on_drop = TRUE
/obj/item/clothing/shoes/magboots/changeling/set_slowdown()
slowdown = shoes? max(SHOES_SLOWDOWN, shoes.slowdown): SHOES_SLOWDOWN //So you can't put on magboots to make you walk faster.
if (magpulse)
slowdown += 1 //It's already tied to a slowdown suit, 6 slowdown is huge.
/obj/item/clothing/shoes/magboots/changeling/attack_self(mob/user)
if(magpulse)
item_flags &= ~NOSLIP
magpulse = 0
set_slowdown()
force = 3
to_chat(user, "We release our grip on the floor.")
else
item_flags |= NOSLIP
magpulse = 1
set_slowdown()
force = 5
to_chat(user, "We cling to the terrain below us.")
//Armor
/obj/item/clothing/suit/space/changeling/armored
name = "chitinous mass"
desc = "A tough, hard covering of black chitin."
icon_state = "lingarmor"
body_parts_covered = CHEST|LEGS|FEET|ARMS|HANDS
armor = list(melee = 75, bullet = 60, laser = 60, energy = 60, bomb = 60, bio = 0, rad = 0) //It costs 3 points, so it should be very protective.
siemens_coefficient = 0.3
max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE
slowdown = 1.5
/obj/item/clothing/suit/space/changeling/armored/Initialize(mapload)
. = ..()
if(ismob(loc))
loc.visible_message(span_warning("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!"),
span_warning("We harden our flesh, creating a suit of armor!"),
span_warningplain("You hear organic matter ripping and tearing!"))
/obj/item/clothing/head/helmet/space/changeling/armored
name = "chitinous mass"
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0)
siemens_coefficient = 0.3
max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE
/obj/item/clothing/shoes/magboots/changeling/armored
desc = "A tough, hard mass of chitin, with long talons for digging into terrain."
name = "chitinous talons"
icon_state = "lingarmor"
actions_types = list(/datum/action/item_action/toggle_talons)
/obj/item/clothing/gloves/combat/changeling //Combined insulated/fireproof gloves
name = "chitinous gauntlets"
desc = "Very resilient gauntlets made out of black chitin. It looks very durable, and can probably resist electrical shock in addition to the elements."
icon_state = "ling"
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0) //No idea if glove armor gets checked
siemens_coefficient = 0
/obj/item/clothing/shoes/boots/combat/changeling //Noslips
name = "chitinous boots"
desc = "Footwear made out of a hard, black chitinous material. The bottoms of these appear to have spikes that can protrude or extract itself into and out \
of the floor at will, granting the wearer stability."
icon_state = "lingarmor"
armor = list(melee = 75, bullet = 60, laser = 70,energy = 60, bomb = 60, bio = 0, rad = 0)
siemens_coefficient = 0.3
min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE
max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE

View File

@@ -0,0 +1,32 @@
//Updated
//Augmented Eyesight: Gives you thermal vision. Also, higher DNA cost because of how powerful it is.
/datum/power/changeling/augmented_eyesight
name = "Augmented Eyesight"
desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
helptext = "Grants us thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
ability_icon_state = "ling_augmented_eyesight"
genomecost = 2
verbpath = /mob/proc/changeling_augmented_eyesight
/mob/proc/changeling_augmented_eyesight()
set category = "Changeling"
set name = "Augmented Eyesight (5)"
set desc = "We evolve our eyes to sense the infrared."
var/datum/component/antag/changeling/comp = changeling_power(5,0,100,CONSCIOUS)
if(!comp)
return 0
var/mob/living/carbon/human/C = src
comp.thermal_sight = !comp.thermal_sight
var/active = comp.thermal_sight
if(active)
comp.chem_charges -= 5
to_chat(C, span_notice("We feel a minute twitch in our eyes, and a hidden layer to the world is revealed."))
C.add_modifier(/datum/modifier/changeling/thermal_sight, 0, src)
else
to_chat(C, span_notice("Our vision dulls."))
C.remove_modifiers_of_type(/datum/modifier/changeling/thermal_sight)
return 1

View File

@@ -0,0 +1,180 @@
/datum/power/changeling/bioelectrogenesis
name = "Bioelectrogenesis"
desc = "We reconfigure a large number of cells in our body to generate an electric charge. \
On demand, we can attempt to recharge anything in our active hand, or we can touch someone with an electrified hand, shocking them."
helptext = "We can shock someone by grabbing them and using this ability, or using the ability with an empty hand and touching them. \
Shocking someone costs ten chemicals per use."
enhancedtext = "Shocking biologicals without grabbing only requires five chemicals, and has more disabling power."
ability_icon_state = "ling_bioelectrogenesis"
genomecost = 2
verbpath = /mob/living/carbon/human/proc/changeling_bioelectrogenesis
//Recharge whatever's in our hand, or shock people.
/mob/living/carbon/human/proc/changeling_bioelectrogenesis()
set category = "Changeling"
set name = "Bioelectrogenesis (20 + 10/shock)"
set desc = "Recharges anything in your hand, or shocks people."
var/datum/component/antag/changeling/changeling = changeling_power(20,0,100,CONSCIOUS)
var/obj/held_item = get_active_hand()
if(!changeling)
return FALSE
if(held_item == null)
if(changeling.recursive_enhancement)
if(changeling_generic_weapon(/obj/item/electric_hand/efficent,0))
to_chat(src, span_notice("We will shock others more efficently."))
return TRUE
else
if(changeling_generic_weapon(/obj/item/electric_hand,0)) //Chemical cost is handled in the equip proc.
return TRUE
return FALSE
else
// Handle glove conductivity.
var/obj/item/clothing/gloves/gloves = src.gloves
var/siemens = 1
if(gloves)
siemens = gloves.siemens_coefficient //Funnily enough, this means things like Knights Gloves will make you stun 2x harder and charge 2x more!
//If we're grabbing someone, electrocute them.
if(istype(held_item,/obj/item/grab))
var/obj/item/grab/G = held_item
if(G.affecting)
G.affecting.electrocute_act(10 * siemens, src, 1.0, BP_TORSO, 0)
var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower.
G.affecting.stun_effect_act(0, agony, BP_TORSO, src)
add_attack_logs(src,G.affecting,"Changeling shocked")
if(siemens)
visible_message(span_warning("Arcs of electricity strike [G.affecting]!"),
span_warning("Our hand channels raw electricity into [G.affecting]."),
span_warningplain("You hear sparks!"))
else
to_chat(src, span_warning("Our gloves block us from shocking \the [G.affecting]."))
changeling.chem_charges -= 10
return TRUE
//Otherwise, charge up whatever's in their hand.
else
//This checks both the active hand, and the contents of the active hand's held item.
var/success = FALSE
var/list/L = new() //We make a new list to avoid copypasta.
//Check our hand.
if(istype(held_item,/obj/item/cell))
L.Add(held_item)
//Now check our hand's item's contents, so we can recharge guns and other stuff.
for(var/obj/item/cell/cell in held_item.contents)
L.Add(cell)
//Now for the actual recharging.
for(var/obj/item/cell/cell in L)
visible_message(span_warning("Some sparks fall out from \the [src.name]\'s [held_item]!"),
span_warning("Our hand channels raw electricity into \the [held_item]. We must remain by the [held_item] to recharge it."),
span_warningplain("You hear sparks!"))
cell.gradual_charge(10, siemens, TRUE, src)
success = TRUE
if(success == FALSE) //If we couldn't do anything with the ability, don't deduct the chemicals.
to_chat(src, span_warning("We are unable to affect \the [held_item]."))
else
changeling.chem_charges -= 10
return success
/obj/item/electric_hand
name = "electrified hand"
desc = "You could probably shock someone badly if you touched them, or recharge something."
icon = 'icons/obj/weapons.dmi'
icon_state = "electric_hand"
show_examine = FALSE
destroy_on_drop = TRUE
var/shock_cost = 10
var/agony_amount = 60
var/electrocute_amount = 10
/obj/item/electric_hand/efficent
shock_cost = 5
agony_amount = 80
electrocute_amount = 20
/obj/item/electric_hand/Initialize(mapload)
. = ..()
if(ismob(loc))
visible_message(span_warning("Electrical arcs form around [loc.name]\'s hand!"),
span_warning("We store a charge of electricity in our hand."),
span_warningplain("You hear crackling electricity!"))
var/T = get_turf(src)
new /obj/effect/effect/sparks(T)
/obj/item/electric_hand/afterattack(var/atom/target, var/mob/living/carbon/human/user, proximity)
if(!target)
return
if(!proximity)
return
// Handle glove conductivity.
var/obj/item/clothing/gloves/gloves = user.gloves
var/siemens = 1
if(gloves)
siemens = gloves.siemens_coefficient
//Excuse the copypasta.
var/datum/component/antag/changeling/comp = is_changeling(user)
if(istype(target,/mob/living/carbon))
var/mob/living/carbon/C = target
if(comp.chem_charges < shock_cost)
to_chat(src, span_warning("We require more chemicals to electrocute [C]!"))
return FALSE
C.electrocute_act(electrocute_amount * siemens,src,1.0,BP_TORSO)
C.stun_effect_act(0, agony_amount * siemens, BP_TORSO, src)
add_attack_logs(user,C,"Shocked with [src]")
if(siemens)
visible_message(span_warning("Arcs of electricity strike [C]!"),
span_warning("Our hand channels raw electricity into [C]"),
span_warningplain("You hear sparks!"))
else
to_chat(src, span_warning("Our gloves block us from shocking \the [C]."))
comp.chem_charges -= shock_cost
return TRUE
else if(istype(target,/mob/living/silicon))
var/mob/living/silicon/S = target
if(comp.chem_charges < 10)
to_chat(src, span_warning("We require more chemicals to electrocute [S]!"))
return FALSE
S.electrocute_act(60,src,0.75) //If only they had surge protectors.
if(siemens)
visible_message(span_warning("Arcs of electricity strike [S]!"),
span_warning("Our hand channels raw electricity into [S]"),
span_warningplain("You hear sparks!"))
to_chat(S, span_danger("Warning: Electrical surge detected!"))
comp.chem_charges -= 10
return TRUE
else
if(istype(target,/obj/))
var/success = FALSE
var/obj/T = target
//We can also recharge things we touch, such as APCs or hardsuits.
for(var/obj/item/cell/cell in T.contents)
visible_message(span_warning("Some sparks fall out from \the [target]!"),
span_warning("Our hand channels raw electricity into \the [target]."),
span_warningplain("You hear sparks!"))
cell.gradual_charge(10, siemens, TRUE, src)
success = TRUE
if(success == FALSE)
to_chat(src, span_warning("We are unable to affect \the [target]."))
else
qdel(src)
return TRUE

View File

@@ -0,0 +1,35 @@
//Updated
/datum/power/changeling/blind_sting
name = "Blind Sting"
desc = "We silently sting a human, completely blinding them for a short time."
enhancedtext = "Duration is extended."
ability_icon_state = "ling_sting_blind"
genomecost = 2
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_blind_sting
/mob/proc/changeling_blind_sting()
set category = "Changeling"
set name = "Blind sting (20)"
set desc="Sting target"
var/datum/component/antag/changeling/comp = is_changeling(src)
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting)
if(!T)
return FALSE
add_attack_logs(src,T,"Blind sting (changeling)")
to_chat(T, span_danger("Your eyes burn horrificly!"))
T.disabilities |= NEARSIGHTED
var/duration = 30 SECONDS
if(comp.recursive_enhancement)
duration = duration + 15 SECONDS
to_chat(src, span_notice("They will be deprived of sight for longer."))
addtimer(CALLBACK(T, PROC_REF(nearsighted_sting_complete),T), duration, TIMER_DELETE_ME)
T.Blind(10)
T.eye_blurry = 20
feedback_add_details("changeling_powers","BS")
return TRUE
/mob/proc/nearsighted_sting_complete(mob/target, mode)
if(!target)
return
target.disabilities &= ~NEARSIGHTED

View File

@@ -0,0 +1,35 @@
//Updated
/datum/power/changeling/boost_range
name = "Boost Range"
desc = "We evolve the ability to shoot our stingers at humans, with some preperation."
helptext = "Allows us to prepare the next sting to have a range of two tiles."
enhancedtext = "The range is extended to five tiles."
ability_icon_state = "ling_sting_boost_range"
genomecost = 1
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_boost_range
//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/component/antag/changeling/changeling = changeling_power(10,0,100)
if(!changeling)
return FALSE
if(!changeling.recursive_enhancement && changeling.sting_range > 1)
to_chat(src, span_notice("We have already empowered our sting!"))
return
else if(changeling.recursive_enhancement && changeling.sting_range > 2)
to_chat(src, span_notice("We have already empowered our sting!"))
return
changeling.chem_charges -= 10
to_chat(src, span_notice("Your throat adjusts to launch the sting."))
var/range = 2
if(changeling.recursive_enhancement)
range = range + 3
to_chat(src, span_notice("We can fire our next sting from five squares away."))
changeling.sting_range = range
feedback_add_details("changeling_powers","RS")
return TRUE

View File

@@ -0,0 +1,37 @@
/datum/power/changeling/cryo_sting
name = "Cryogenic Sting"
desc = "We silently sting a biological with a cocktail of chemicals that freeze them."
helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing. Has \
a three minute cooldown between uses."
enhancedtext = "Increases the amount of chemicals injected."
ability_icon_state = "ling_sting_cryo"
genomecost = 1
verbpath = /mob/proc/changeling_cryo_sting
/mob/proc/changeling_cryo_sting()
set category = "Changeling"
set name = "Cryogenic Sting (20)"
set desc = "Chills and freezes a biological creature."
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_cryo_sting, CRYO_STING)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!T)
return FALSE
if(comp.is_on_cooldown(CRYO_STING))
to_chat(src, span_notice("We are still recovering. We will be able to sting again in [(comp.get_cooldown(CRYO_STING) - world.time)/10] seconds."))
return
add_attack_logs(src,T,"Cryo sting (changeling)")
var/inject_amount = 10
if(comp.recursive_enhancement)
inject_amount = inject_amount * 1.5
to_chat(src, span_notice("We inject extra chemicals."))
if(T.reagents)
T.reagents.add_reagent(REAGENT_ID_CRYOTOXIN, inject_amount)
feedback_add_details("changeling_powers","CS")
comp.set_cooldown(CRYO_STING, 3 MINUTES) //Set the cooldown to 3 minutes.
addtimer(CALLBACK(src, PROC_REF(changeling_cryo_sting_ready)), 3 MINUTES, TIMER_DELETE_ME) //Calling a proc with arguments
return TRUE
/mob/proc/changeling_cryo_sting_ready()
to_chat(src, span_notice("Our cryogenic string is ready to be used once more."))

View File

@@ -0,0 +1,26 @@
/datum/power/changeling/darksight
name = "Dark Sight"
desc = "We change the composition of our eyes, banishing the shadows from our vision."
helptext = "We will be able to see in the dark."
ability_icon_state = "ling_augmented_eyesight"
genomecost = 0
verbpath = /mob/proc/changeling_darksight
/mob/proc/changeling_darksight()
set category = "Changeling"
set name = "Toggle Darkvision"
set desc = "We are able see in the dark."
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100,UNCONSCIOUS)
if(!changeling)
return 0
if(istype(src,/mob/living/carbon))
var/mob/living/carbon/C = src
C.seedarkness = !C.seedarkness
if(C.seedarkness)
to_chat(C, span_notice("We allow the shadows to return."))
else
to_chat(C, span_notice("We no longer need light to see."))
return 0

View File

@@ -0,0 +1,28 @@
/datum/power/changeling/deaf_sting
name = "Deaf Sting"
desc = "We silently sting a human, completely deafening them for a short time."
enhancedtext = "Deafness duration is extended."
ability_icon_state = "ling_sting_deafen"
genomecost = 1
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_deaf_sting
/mob/proc/changeling_deaf_sting()
set category = "Changeling"
set name = "Deaf sting (5)"
set desc="Sting target:"
var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!T) return 0
add_attack_logs(src,T,"Deaf sting (changeling)")
var/duration = 300
if(comp.recursive_enhancement)
duration = duration + 100
to_chat(src, span_notice("They will be unable to hear for a little longer."))
to_chat(T, span_danger("Your ears pop and begin ringing loudly!"))
T.sdisabilities |= DEAF
spawn(duration) T.sdisabilities &= ~DEAF
feedback_add_details("changeling_powers","DS")
return 1

View File

@@ -0,0 +1,42 @@
/datum/power/changeling/delayed_toxic_sting
name = "Delayed Toxic Sting"
desc = "We silently sting a biological, causing a significant amount of toxins after a few minutes, allowing us to not \
implicate ourselves."
helptext = "The toxin takes effect in about two minutes. Multiple applications within the two minutes will not cause increased toxicity."
enhancedtext = "The toxic damage is doubled."
ability_icon_state = "ling_sting_del_toxin"
genomecost = 1
verbpath = /mob/proc/changeling_delayed_toxic_sting
/datum/modifier/delayed_toxin_sting
name = "delayed toxin injection"
hidden = TRUE
stacks = MODIFIER_STACK_FORBID
on_expired_text = span_danger("You feel a burning sensation flowing through your veins!")
/datum/modifier/delayed_toxin_sting/on_expire()
holder.adjustToxLoss(rand(20, 30))
/datum/modifier/delayed_toxin_sting/strong/on_expire()
holder.adjustToxLoss(rand(40, 60))
/mob/proc/changeling_delayed_toxic_sting()
set category = "Changeling"
set name = "Delayed Toxic Sting (20)"
set desc = "Injects the target with a toxin that will take effect after a few minutes."
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_delayed_toxic_sting)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!T)
return 0
add_attack_logs(src,T,"Delayed toxic sting (chagneling)")
var/type_to_give = /datum/modifier/delayed_toxin_sting
if(comp.recursive_enhancement)
type_to_give = /datum/modifier/delayed_toxin_sting/strong
to_chat(src, span_notice("Our toxin will be extra potent, when it strikes."))
T.add_modifier(type_to_give, 2 MINUTES)
feedback_add_details("changeling_powers","DTS")
return 1

View File

@@ -0,0 +1,33 @@
/datum/power/changeling/digital_camoflague
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."
ability_icon_state = "ling_digital_camo"
genomecost = 1
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_digitalcamo
//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/component/antag/changeling/changeling = changeling_power()
if(!changeling)
return 0
var/mob/living/carbon/human/C = src
if(C.digitalcamo)
to_chat(C, span_notice("We return to normal."))
else
to_chat(C, span_notice("We distort our form to prevent AI-tracking."))
C.digitalcamo = !C.digitalcamo
spawn(0)
while(C && C.digitalcamo && C.mind && changeling)
changeling.chem_charges = max(changeling.chem_charges - 1, 0)
sleep(40)
feedback_add_details("changeling_powers","CAM")
return 1

View File

@@ -0,0 +1,97 @@
/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 = 3
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/component/antag/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/finger_lockpick,0,5)) //Chemical cost is handled in the equip proc.
return 1
return 0
/obj/item/finger_lockpick
name = "finger lockpick"
desc = "This finger appears to be an organic datajack."
icon = 'icons/obj/weapons.dmi'
icon_state = "electric_hand"
show_examine = FALSE
/obj/item/finger_lockpick/Initialize(mapload)
. = ..()
if(ismob(loc))
to_chat(loc, span_notice("We shape our finger to fit inside electronics, and are ready to force them open."))
/obj/item/finger_lockpick/dropped(mob/user)
..()
to_chat(user, span_notice("We discreetly shape our finger back to a less suspicious form."))
spawn(1)
if(src)
qdel(src)
/obj/item/finger_lockpick/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target)
return
if(!proximity)
return
var/datum/component/antag/changeling/ling_datum = is_changeling(user)
if(!ling_datum)
return
if(ling_datum.chem_charges < 10)
to_chat(user, span_warning("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, span_notice("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, span_notice("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, span_notice("We've opened \the [airlock]."))
else
door.open() //If we're a windoor, open the windoor.
to_chat(user, span_notice("We've opened \the [door]."))
else //Probably broken or no power.
to_chat(user, span_warning("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, span_notice("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

View File

@@ -0,0 +1,22 @@
//Updated
/datum/power/changeling/endoarmor
name = "Endoarmor"
desc = "We grow hard plating underneath our skin, making us more resilient to harm by increasing our maximum health potential by 50 points."
helptext = "Our maximum health is increased by 50 points."
genomecost = 1
isVerb = FALSE
verbpath = /mob/proc/changeling_endoarmor
/datum/modifier/endoarmor
name = "endoarmor"
desc = "We have hard plating underneath our skin, making us more durable."
on_created_text = span_notice("We feel protective plating form underneath our skin.")
on_expired_text = span_notice("Our protective armor underneath our skin fades as we absorb it.")
max_health_flat = 50
/mob/proc/changeling_endoarmor()
if(ishuman(src))
var/mob/living/carbon/human/H = src
H.add_modifier(/datum/modifier/endoarmor)
return 1

View File

@@ -0,0 +1,48 @@
//Updated
/datum/power/changeling/enfeebling_string
name = "Enfeebling String"
desc = "We sting a biological with a potent toxin that will greatly weaken them for a short period of time."
helptext = "Lowers the maximum health of the victim for a few minutes, as well as making them more frail and weak. This sting will also warn them of this."
enhancedtext = "Maximum health and outgoing melee damage is lowered further. Incoming damage is increased."
ability_icon_state = "ling_sting_enfeeble"
genomecost = 1
verbpath = /mob/proc/changeling_enfeebling_string
/datum/modifier/enfeeble
name = "enfeebled"
desc = "You feel really weak and frail for some reason."
stacks = MODIFIER_STACK_EXTEND
max_health_percent = 0.7
outgoing_melee_damage_percent = 0.75
incoming_damage_percent = 1.1
on_created_text = span_danger("You feel a small prick and you feel extremly weak!")
on_expired_text = span_notice("You no longer feel extremly weak.")
// Now YOU'RE the Teshari!
/datum/modifier/enfeeble/strong
max_health_percent = 0.5
outgoing_melee_damage_percent = 0.5
incoming_damage_percent = 1.35
/mob/proc/changeling_enfeebling_string()
set category = "Changeling"
set name = "Enfeebling Sting (30)"
set desc = "Reduces the maximum health of a victim for a few minutes.."
var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_enfeebling_string)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!T)
return 0
if(ishuman(T))
var/mob/living/carbon/human/H = T
add_attack_logs(src,T,"Enfeebling sting (changeling)")
var/type_to_give = /datum/modifier/enfeeble
if(comp.recursive_enhancement)
type_to_give = /datum/modifier/enfeeble/strong
to_chat(src, span_notice("We make them extremely weak."))
H.add_modifier(type_to_give, 2 MINUTES)
feedback_add_details("changeling_powers","ES")
return 1

View File

@@ -0,0 +1,15 @@
//Updated
/datum/power/changeling/engorged_glands
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 30 units of chemicals, and doubles production rate."
genomecost = 1
isVerb = 0
verbpath = /mob/proc/changeling_engorgedglands
//Increases macimum chemical storage
/mob/proc/changeling_engorgedglands()
var/datum/component/antag/changeling/comp = is_changeling(src)
comp.chem_storage += 30
comp.chem_recharge_rate *= 2
return 1

View File

@@ -0,0 +1,34 @@
//Updated
/datum/power/changeling/enrage
name = "Enrage"
desc = "We evolve modifications to our mind and body, allowing us to call on intense periods of rage for our benefit."
helptext = "Berserks us, giving massive bonuses to fighting in close quarters for thirty seconds, and losing the ability to \
be accurate at ranged while active. Afterwards, we will suffer extreme amounts of exhaustion for a period of two minutes, \
during which we will be much weaker and slower than before. We cannot berserk again while exhausted. This ability requires \
a significant amount of nutrition to use, and cannot be used if too hungry. Using this ability will end most forms of disables."
enhancedtext = "The length of exhaustion after berserking is reduced to one minute, from two, and requires half as much nutrition."
ability_icon_state = "ling_berserk"
genomecost = 2
allowduringlesserform = TRUE
verbpath = /mob/living/proc/changeling_berserk
// Makes the ling very upset.
/mob/living/proc/changeling_berserk()
set category = "Changeling"
set name = "Enrage (30)"
set desc = "Causes you to go Berserk."
var/datum/component/antag/changeling/changeling = changeling_power(30,0,100)
if(!changeling)
return 0
var/modifier_to_use = /datum/modifier/berserk/changeling
if(changeling.recursive_enhancement)
modifier_to_use = /datum/modifier/berserk/changeling/recursive
to_chat(src, span_notice("We optimize our levels of anger, which will avoid excessive stress on ourselves."))
if(add_modifier(modifier_to_use, 30 SECONDS))
changeling.chem_charges -= 30
feedback_add_details("changeling_powers","EN")
return 1

View File

@@ -0,0 +1,67 @@
//Updated
/datum/power/changeling/epinephrine_overdose
name = "Epinephrine Overdose"
desc = "We evolve additional sacs of adrenaline throughout our body."
helptext = "We can instantly recover from stuns and reduce the effect of future stuns, but we will suffer toxicity in the long term. Can be used while unconscious."
enhancedtext = "Immunity from most disabling effects for 30 seconds."
ability_icon_state = "ling_epinepherine_overdose"
genomecost = 2
verbpath = /mob/proc/changeling_epinephrine_overdose
/datum/modifier/unstoppable
name = "unstoppable"
desc = "We feel limitless amounts of energy surge in our veins. Nothing can stop us!"
stacks = MODIFIER_STACK_EXTEND
on_created_text = span_notice("We feel unstoppable!")
on_expired_text = span_warning("We feel our newfound energy fade...")
disable_duration_percent = 0
//Recover from stuns.
/mob/proc/changeling_epinephrine_overdose()
set category = "Changeling"
set name = "Epinephrine Overdose (30)"
set desc = "Removes all stuns instantly, and reduces future stuns."
var/datum/component/antag/changeling/changeling = changeling_power(30,0,100,UNCONSCIOUS)
if(!changeling)
return 0
changeling.chem_charges -= 30
var/mob/living/carbon/human/C = src
to_chat(C, span_notice("Energy rushes through us. [C.lying ? "We arise." : ""]"))
C.set_stat(CONSCIOUS)
C.SetParalysis(0)
C.SetStunned(0)
C.SetWeakened(0)
C.lying = 0
C.update_canmove()
C.reagents.add_reagent("epinephrine", 20)
if(changeling.recursive_enhancement)
C.add_modifier(/datum/modifier/unstoppable, 30 SECONDS)
feedback_add_details("changeling_powers","UNS")
return 1
/datum/reagent/epinephrine
name = REAGENT_EPINEPHRINE
id = REAGENT_ID_EPINEPHRINE
description = "A chemically naturally produced by the body while in fight-or-flight mode. Greatly increases one's strength."
reagent_state = LIQUID
color = "#C8A5DC"
metabolism = REM * 2
wiki_flag = WIKI_SPOILER
/datum/reagent/epinephrine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
return
M.add_chemical_effect(CE_SPEEDBOOST, 3)
M.add_chemical_effect(CE_PAINKILLER, 60)
M.adjustHalLoss(-30)
M.AdjustParalysis(-2)
M.AdjustStunned(-2)
M.AdjustWeakened(-2)
M.adjustToxLoss(removed * 2.5) //It gives you 20units of epinephrine. 50 toxins damage. 1 Toxin per tick.
..()
return

View File

@@ -0,0 +1,71 @@
/datum/power/changeling/escape_restraints
name = "Escape Restraints"
desc = "We evolve more complex joints"
helptext = "We can instantly escape from most restraints and bindings, but we cannot do it often."
enhancedtext = "More frequent escapes."
ability_icon_state = "ling_escape_restraints"
genomecost = 2
verbpath = /mob/proc/changeling_escape_restraints
//Escape Cuffs. By design this does not escape from straight jackets
/mob/proc/changeling_escape_restraints()
set category = "Changeling"
set name = "Escape Restraints (40)"
set desc = "Removes handcuffs and legcuffs instantly."
var/escape_cooldown = 5 MINUTES //This is used later to prevent spamming
var/mob/living/carbon/human/C = src
var/datum/component/antag/changeling/changeling = changeling_power(40,0,100,CONSCIOUS)
if(!changeling)
return FALSE
if(changeling.is_on_cooldown(ESCAPE_RESTRAINTS))
to_chat(src, span_notice("We are still recovering from our last escape. We will be able to escape again in [(changeling.get_cooldown(ESCAPE_RESTRAINTS) - world.time)/10] seconds."))
return FALSE
if(!(C.handcuffed || C.legcuffed || istype(C.wear_suit,/obj/item/clothing/suit/straight_jacket))) // No need to waste chems if there's nothing to break out of
to_chat(C, span_warning("We are are not restrained in a way we can escape..."))
return FALSE
changeling.chem_charges -= 40
to_chat(C,span_notice("We contort our extremities and slip our cuffs."))
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
if(C.handcuffed)
var/obj/item/W = C.handcuffed
C.handcuffed = null
if(C.buckled && C.buckled.buckle_require_restraints)
C.buckled.unbuckle_mob()
C.update_handcuffed()
if (C.client)
C.client.screen -= W
W.forceMove(C.loc)
W.dropped(C)
if(W)
W.layer = initial(W.layer)
if(C.legcuffed)
var/obj/item/W = C.legcuffed
C.legcuffed = null
C.update_inv_legcuffed()
if(C.client)
C.client.screen -= W
W.forceMove(C.loc)
W.dropped(C)
if(W)
W.layer = initial(W.layer)
if(istype(C.wear_suit, /obj/item/clothing/suit/straight_jacket))
var/obj/item/clothing/suit/straight_jacket/SJ = C.wear_suit
SJ.forceMove(C.loc)
SJ.dropped(C)
C.wear_suit = null
escape_cooldown *= 1.5 // Straight jackets are tedious compared to cuffs.
if(changeling.recursive_enhancement)
escape_cooldown *= 0.5
changeling.set_cooldown(ESCAPE_RESTRAINTS, escape_cooldown)
addtimer(CALLBACK(src, PROC_REF(changeling_escape_restraints_ready)), escape_cooldown, TIMER_DELETE_ME)
feedback_add_details("changeling_powers","ESR")
return TRUE
/mob/proc/changeling_escape_restraints_ready()
to_chat(src, span_notice("We are able to escape our restraints once more."))

View File

@@ -0,0 +1,46 @@
//Updated
/datum/power/changeling/extract_dna
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."
ability_icon_state = "ling_sting_extract"
genomecost = 0
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_extract_dna_sting
/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/component/antag/changeling/changeling = null
if(src.mind && changeling)
changeling = changeling
if(!changeling)
return FALSE
var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting)
if(!T)
return
if(!istype(T) || T.isSynthetic())
to_chat(src, span_warning("\The [T] is not compatible with our biology."))
return FALSE
if(T.species.flags & (NO_DNA|NO_SLEEVE))
to_chat(src, span_warning("We do not know how to parse this creature's DNA!"))
return FALSE
if(HUSK in T.mutations)
to_chat(src, span_warning("This creature's DNA is ruined beyond useability!"))
return FALSE
add_attack_logs(src,T,"DNA extraction sting (changeling)")
var/saved_dna = T.dna.Clone() /// Prevent transforming bugginess.
var/datum/absorbed_dna/newDNA = new(T.real_name, saved_dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts, T.modifiers)
absorbDNA(newDNA)
feedback_add_details("changeling_powers","ED")
return TRUE

View File

@@ -0,0 +1,292 @@
//Needs a BIG rework.
var/global/list/changeling_fabricated_clothing = list(
"w_uniform" = /obj/item/clothing/under/chameleon/changeling,
"head" = /obj/item/clothing/head/chameleon/changeling,
"wear_suit" = /obj/item/clothing/suit/chameleon/changeling,
"shoes" = /obj/item/clothing/shoes/chameleon/changeling,
"gloves" = /obj/item/clothing/gloves/chameleon/changeling,
"wear_mask" = /obj/item/clothing/mask/chameleon/changeling,
"glasses" = /obj/item/clothing/glasses/chameleon/changeling,
"back" = /obj/item/storage/backpack/chameleon/changeling,
"belt" = /obj/item/storage/belt/chameleon/changeling,
"wear_id" = /obj/item/card/id/syndicate/changeling
)
/datum/power/changeling/fabricate_clothing
name = "Fabricate Clothing"
desc = "We reform our flesh to resemble various cloths, leathers, and other materials, allowing us to quickly create a disguise. \
We cannot be relieved of this clothing by others."
helptext = "The disguise we create offers no defensive ability. Each equipment slot that is empty will be filled with fabricated equipment. \
To remove our new fabricated clothing, use this ability again."
ability_icon_state = "ling_fabricate_clothing"
genomecost = 1
verbpath = /mob/proc/changeling_fabricate_clothing
//Grows biological versions of chameleon clothes.
/mob/proc/changeling_fabricate_clothing()
set category = "Changeling"
set name = "Fabricate Clothing (10)"
if(changeling_generic_equip_all_slots(changeling_fabricated_clothing, cost = 10))
return 1
return 0
/obj/item/clothing/under/chameleon/changeling
name = "malformed flesh"
icon_state = "lingchameleon"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_uniforms.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_uniforms.dmi',
)
item_state = "lingchameleon"
worn_state = "lingchameleon"
desc = "The flesh all around us has grown a new layer of cells that can shift appearance and create a biological fabric that cannot be distinguished from \
ordinary cloth, allowing us to make ourselves appear to wear almost anything."
origin_tech = list() //The base chameleon items have origin technology, which we will inherit if we don't null out this variable.
canremove = FALSE //Since this is essentially flesh impersonating clothes, tearing someone's skin off as if it were clothing isn't possible.
/obj/item/clothing/under/chameleon/changeling/emp_act(severity) //As these are purely organic, EMP does nothing to them.
return
/obj/item/clothing/under/chameleon/changeling/verb/shred() //Remove individual pieces if needed.
set name = "Shred Jumpsuit"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/head/chameleon/changeling
name = "malformed head"
icon_state = "lingchameleon"
desc = "Our head is swelled with a large quanity of rapidly shifting skin cells. We can reform our head to resemble various hats and \
helmets that biologicals are so fond of wearing."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/head/chameleon/changeling/emp_act(severity)
return
/obj/item/clothing/head/chameleon/changeling/verb/shred() //The copypasta is real.
set name = "Shred Helmet"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/suit/chameleon/changeling
name = "chitinous chest"
icon_state = "lingchameleon"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_suits.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_suits.dmi',
)
item_state = "armor"
desc = "The cells in our chest are rapidly shifting, ready to reform into material that can resemble most pieces of clothing."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/suit/chameleon/changeling/emp_act(severity)
return
/obj/item/clothing/suit/chameleon/changeling/verb/shred()
set name = "Shred Suit"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/shoes/chameleon/changeling
name = "malformed feet"
icon_state = "lingchameleon"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_shoes.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_shoes.dmi',
)
item_state = "black"
desc = "Our feet are overlayed with another layer of flesh and bone on top. We can reform our feet to resemble various boots and shoes."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/shoes/chameleon/changeling/emp_act()
return
/obj/item/clothing/shoes/chameleon/changeling/verb/shred()
set name = "Shred Shoes"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/storage/backpack/chameleon/changeling
name = "backpack"
icon_state = "backpack"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_storage.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_storage.dmi',
)
item_state = "backpack"
desc = "A large pouch imbedded in our back, it can shift form to resemble many common backpacks that other biologicals are fond of using."
origin_tech = list()
canremove = FALSE
/obj/item/storage/backpack/chameleon/changeling/emp_act()
return
/obj/item/storage/backpack/chameleon/changeling/verb/shred()
set name = "Shred Backpack"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
for(var/atom/movable/AM in src.contents) //Dump whatever's in the bag before deleting.
AM.forceMove(get_turf(loc))
qdel(src)
/obj/item/clothing/gloves/chameleon/changeling
name = "malformed hands"
icon_state = "ling"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_gloves.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi',
)
item_state = "ling"
desc = "Our hands have a second layer of flesh on top. We can reform our hands to resemble a large variety of fabrics and materials that biologicals \
tend to wear on their hands. Remember that these won't protect your hands from harm."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/gloves/chameleon/changeling/emp_act()
return
/obj/item/clothing/gloves/chameleon/changeling/verb/shred()
set name = "Shred Gloves"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/mask/chameleon/changeling
name = "chitin visor"
icon_state = "lingchameleon"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_masks.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_masks.dmi',
)
item_state = "gas_alt"
desc = "A transparent visor of brittle chitin covers our face. We can reform it to resemble various masks that biologicals use. It can also utilize internal \
tanks.."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/mask/chameleon/changeling/emp_act()
return
/obj/item/clothing/mask/chameleon/changeling/verb/shred()
set name = "Shred Mask"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/glasses/chameleon/changeling
name = "chitin goggles"
icon_state = "lingchameleon"
item_state = "glasses"
desc = "A transparent piece of eyewear made out of brittle chitin. We can reform it to resemble various glasses and goggles."
origin_tech = list()
canremove = FALSE
/obj/item/clothing/glasses/chameleon/changeling/emp_act()
return
/obj/item/clothing/glasses/chameleon/changeling/verb/shred()
set name = "Shred Glasses"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/storage/belt/chameleon/changeling
name = "waist pouch"
desc = "We can store objects in this, as well as shift it's appearance, so that it resembles various common belts."
icon_state = "lingchameleon"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_storage.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_storage.dmi',
)
item_state = "utility"
origin_tech = list()
canremove = FALSE
/obj/item/storage/belt/chameleon/changeling/emp_act()
return
/obj/item/storage/belt/chameleon/changeling/verb/shred()
set name = "Shred Belt"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/card/id/syndicate/changeling
name = "chitinous card"
desc = "A card that we can reform to resemble identification cards. Due to the nature of the material this is made of, it cannot store any access codes."
icon_state = "changeling"
assignment = "Harvester"
origin_tech = list()
electronic_warfare = 1 //The lack of RFID stuff makes it hard for AIs to track, I guess. *handwaves*
registered_user = null
access = null
canremove = FALSE
/obj/item/card/id/syndicate/changeling/Initialize(mapload)
. = ..()
if(ismob(loc))
registered_user = loc
/obj/item/card/id/syndicate/changeling/Initialize(mapload)
. = ..()
access = null
/obj/item/card/id/syndicate/changeling/verb/shred()
set name = "Shred ID Card"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message(span_warning("[H] tears off [src]!"),
span_notice("We remove [src]."))
qdel(src)
/obj/item/card/id/syndicate/changeling/Click() //Since we can't hold it in our hands, and attack_hand() doesn't work if it in inventory...
if(!registered_user)
registered_user = usr
usr.set_id_info(src)
tgui_interact(registered_user)
..()

View File

@@ -0,0 +1,52 @@
/datum/power/changeling/fake_death
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."
ability_icon_state = "ling_regenerative_stasis"
genomecost = 0
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_fakedeath
//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/component/antag/changeling/changeling = changeling_power(CHANGELING_STASIS_COST,1,100,DEAD)
if(!changeling)
return
var/mob/living/carbon/C = src
if(changeling.max_geneticpoints < 0) //Absorbed by another ling
to_chat(src, span_danger("We have no genomes, not even our own, and cannot regenerate."))
return 0
if(!C.stat && tgui_alert(src, "Are we sure we wish to regenerate? We will appear to be dead while doing so.","Revival",list("Yes","No")) != "Yes")
return
C.update_canmove()
changeling.chem_charges -= CHANGELING_STASIS_COST
if(C.suiciding)
C.suiciding = FALSE
if(C.does_not_breathe)
C.does_not_breathe = FALSE //This means they don't autoheal the oxy damage from the next step
if(C.stat != DEAD)
C.adjustOxyLoss(C.getMaxHealth() * 2)
C.forbid_seeing_deadchat = TRUE
var/resurrection_time = rand(2 MINUTES, 4 MINUTES)
changeling.set_cooldown(FAKE_DEATH, resurrection_time)
changeling.is_reviving = TRUE
to_chat(C, span_notice("We will attempt to regenerate our form. This will take [(changeling.get_cooldown(FAKE_DEATH) - world.time)/600] minutes."))
addtimer(CALLBACK(src, PROC_REF(finish_changeling_revive)), resurrection_time, TIMER_DELETE_ME)
feedback_add_details("changeling_powers","FD")
return 1
/mob/proc/finish_changeling_revive()
//Lets the ling know it's revive time.
to_chat(src, span_notice(span_giant("We are ready to rise. Use the <b>Revive</b> verb when you are ready.")))

View File

@@ -0,0 +1,53 @@
/datum/power/changeling/fleshmend
name = "Fleshmend"
desc = "Begins a slow regeneration of our form. Does not effect stuns or chemicals."
helptext = "Can be used while unconscious."
enhancedtext = "Healing is twice as effective."
ability_icon_state = "ling_fleshmend"
genomecost = 1
verbpath = /mob/proc/changeling_fleshmend
//Starts healing you every second for 50 seconds. Can be used whilst unconscious.
/mob/proc/changeling_fleshmend()
set category = "Changeling"
set name = "Fleshmend (10)"
set desc = "Begins a slow rengeration of our form. Does not effect stuns or chemicals."
var/mob/living/C = src
var/datum/component/antag/changeling/changeling = changeling_power(10,0,100,UNCONSCIOUS)
if(!changeling)
return FALSE
if(C.has_modifier_of_type(/datum/modifier/fleshmend))
to_chat(src, span_notice("We are already under the effect of fleshmend."))
return FALSE
changeling.chem_charges -= 10
if(changeling.recursive_enhancement)
to_chat(src, span_notice("We will heal much faster."))
C.add_modifier(/datum/modifier/fleshmend/recursive, 50 SECONDS)
else
C.add_modifier(/datum/modifier/fleshmend, 50 SECONDS)
feedback_add_details("changeling_powers","FM")
return TRUE
/datum/modifier/fleshmend
name = "Fleshmend"
desc = "We are regenerating"
// For changelings who bought the Recursive Enhancement evolution.
/datum/modifier/fleshmend/recursive
name = "Advanced Fleshmend"
desc = "We are regenerating more rapidly."
//These were previously 2 or 4 per second, now it's 4 or 8 per 2 seconds
/datum/modifier/fleshmend/tick()
holder.adjustBruteLoss(-4)
holder.adjustOxyLoss(-4)
holder.adjustFireLoss(-4)
/datum/modifier/fleshmend/recursive/tick()
holder.adjustBruteLoss(-8)
holder.adjustOxyLoss(-8)
holder.adjustFireLoss(-8)

View File

@@ -0,0 +1,85 @@
//Updated
// 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
make_hud_button = FALSE
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
make_hud_button = FALSE
verbpath = /mob/proc/changeling_hivedownload
// HIVE MIND UPLOAD/DOWNLOAD DNA
var/list/datum/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/component/antag/changeling/changeling = changeling_power(10,1)
if(!changeling)
return
var/list/names = list()
for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
if(!(DNA in hivemind_bank))
names += DNA.name
if(names.len <= 0)
to_chat(src, span_notice("The airwaves already have all of our DNA."))
return
var/S = tgui_input_list(src, "Select a DNA to channel:", "Channel DNA", 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, span_notice("We channel the DNA of [S] to the air."))
feedback_add_details("changeling_powers","HU")
return TRUE
/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/component/antag/changeling/changeling = changeling_power(20,1)
if(!changeling)
return
var/list/names = list()
for(var/datum/absorbed_dna/DNA in hivemind_bank)
if(!(DNA in changeling.absorbed_dna))
names[DNA.name] = DNA
if(names.len <= 0)
to_chat(src, span_notice("There's no new DNA to absorb from the air."))
return
var/S = tgui_input_list(src, "Select a DNA to absorb:", "Absorb DNA", names)
if(!S)
return
var/datum/absorbed_dna/chosen_dna = names[S]
if(!chosen_dna)
return
changeling.chem_charges -= 20
absorbDNA(chosen_dna)
to_chat(src, span_notice("We absorb the DNA of [S] from the air."))
feedback_add_details("changeling_powers","HD")
return TRUE

View File

@@ -0,0 +1,116 @@
/datum/power/changeling/lesser_form
name = "Lesser Form"
desc = "We debase ourselves and become lesser. We become a monkey."
genomecost = 1
verbpath = /mob/proc/changeling_lesser_form
//Transform into a monkey.
/mob/proc/changeling_lesser_form()
set category = "Changeling"
set name = "Lesser Form (1)"
var/datum/component/antag/changeling/changeling = changeling_power(1,0,0)
if(!changeling)
return
if(has_brain_worms())
to_chat(src, span_warning("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, span_warning("We cannot perform this ability in this form!"))
return
changeling.chem_charges--
H.remove_changeling_powers()
H.visible_message(span_warning("[H] transforms!"))
changeling.geneticdamage = 30
to_chat(H, span_warning("Our genes cry out!"))
var/list/implants = list() //Try to preserve implants.
for(var/obj/item/implant/W in H)
implants += W
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/component/antag/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 = tgui_input_list(src, "Select the target DNA:", "Target DNA", names)
if(!S)
return
var/datum/dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
var/mob/living/carbon/C = src
changeling.chem_charges--
C.remove_changeling_powers()
C.visible_message(span_warning("[C] transforms!"))
qdel_swap(C.dna, chosen_dna.Clone())
var/list/implants = list()
for (var/obj/item/implant/I in C) //Still preserving implants
implants += I
C.transforming = 1
C.canmove = 0
C.icon = null
C.cut_overlays()
C.invisibility = INVISIBILITY_ABSTRACT
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
qdel_swap(O.dna, C.dna.Clone())
QDEL_NULL(C.dna)
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/implant/I in implants)
I.loc = 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

View File

@@ -0,0 +1,20 @@
//This only exists to be abused, so it's highly recommended to ensure this file is unchecked.
/datum/power/changeling/lsd_sting
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
/mob/proc/changeling_lsdsting()
set category = "Changeling"
set name = "Hallucination Sting (15)"
set desc = "Causes terror in the target."
var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting)
if(!T)
return FALSE
add_attack_logs(src,T,"Hallucination sting (changeling)")
addtimer(VARSET_CALLBACK(T, hallucination, min(T.hallucination+400, 400)), rand(30 SECONDS, 60 SECONDS), TIMER_DELETE_ME) //No going ABOVE 400 hallucinations.
feedback_add_details("changeling_powers","HS")
return TRUE

View File

@@ -0,0 +1,41 @@
/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"
ability_icon_state = "ling_mimic_voice"
genomecost = 1
verbpath = /mob/proc/changeling_mimicvoice
// 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/component/antag/changeling/changeling = changeling_power()
if(!changeling) return
if(changeling.mimicing)
changeling.mimicing = ""
to_chat(src, span_notice("We return our vocal glands to their original location."))
return
var/mimic_voice = sanitize(tgui_input_text(src, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN), MAX_NAME_LEN)
if(!mimic_voice)
return
changeling.mimicing = mimic_voice
to_chat(src, span_notice("We shape our glands to take the voice of <b>[mimic_voice]</b>, this will stop us from regenerating chemicals while active."))
to_chat(src, span_notice("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 && changeling && changeling.mimicing)
changeling.chem_charges = max(changeling.chem_charges - 1, 0)
sleep(40)
if(src && src.mind && changeling)
changeling.mimicing = ""

View File

@@ -0,0 +1,56 @@
/datum/power/changeling/panacea
name = "Anatomic Panacea"
desc = "Expels impurifications from our form; curing diseases, removing toxins, chemicals, radiation, and resetting our genetic code completely."
helptext = "Can be used while unconscious. This will also purge any reagents inside ourselves, both harmful and beneficial."
enhancedtext = "We heal more toxins."
ability_icon_state = "ling_anatomic_panacea"
genomecost = 1
verbpath = /mob/proc/changeling_panacea
//Heals the things that the other regenerative abilities don't.
/mob/proc/changeling_panacea()
set category = "Changeling"
set name = "Anatomic Panacea (20)"
set desc = "Clense ourselves of impurities."
var/datum/component/antag/changeling/changeling = changeling_power(20,0,100,UNCONSCIOUS)
if(!changeling)
return 0
changeling.chem_charges -= 20
to_chat(src, span_notice("We cleanse impurities from our form."))
var/mob/living/carbon/human/C = src
C.radiation = 0
C.sdisabilities = 0
C.disabilities = 0
C.reagents.clear_reagents()
C.ingested.clear_reagents()
var/heal_amount = 5
if(changeling.recursive_enhancement)
heal_amount = heal_amount * 2
to_chat(src, span_notice("We will heal much faster."))
//TODO: Replace with a modifier.
for(var/i = 0, i<10,i++)
if(C)
C.adjustToxLoss(-heal_amount)
sleep(10)
for(var/obj/item/organ/external/E in C.organs)
var/obj/item/organ/external/G = E
if(G.germ_level)
var/germ_heal = heal_amount * 100
G.germ_level = min(0, G.germ_level - germ_heal)
for(var/obj/item/organ/internal/I in C.internal_organs)
var/obj/item/organ/internal/G = I
if(G.germ_level)
var/germ_heal = heal_amount * 100
G.germ_level = min(0, G.germ_level - germ_heal)
feedback_add_details("changeling_powers","AP")
return 1

View File

@@ -0,0 +1,20 @@
//Updated
/datum/power/changeling/paralysis_sting
name = "Paralysis Sting"
desc = "We silently sting a human, paralyzing them for a short time."
genomecost = 3
verbpath = /mob/proc/changeling_paralysis_sting
/mob/proc/changeling_paralysis_sting()
set category = "Changeling"
set name = "Paralysis sting (30)"
set desc="Sting target"
var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting)
if(!T)
return FALSE
add_attack_logs(src,T,"Paralysis sting (changeling)")
to_chat(T, span_danger("Your muscles begin to painfully tighten."))
T.Weaken(20)
feedback_add_details("changeling_powers","PS")
return TRUE

View File

@@ -0,0 +1,56 @@
/datum/power/changeling/rapid_regen
name = "Rapid Regeneration"
desc = "We quickly heal ourselves, removing most advanced injuries, at a high chemical cost."
helptext = "This will heal a significant amount of brute, fire, oxy, clone, and brain damage, and heal broken bones, internal bleeding, low blood, \
and organ damage. The process is fast, but anyone who sees us do this will likely realize we are not what we seem."
enhancedtext = "Healing increased to heal up to maximum health."
ability_icon_state = "ling_rapid_regeneration"
genomecost = 2
verbpath = /mob/proc/changeling_rapid_regen
//Gives a big heal, removing various injuries that might shut down normal people, like IB or fractures.
/mob/proc/changeling_rapid_regen()
set category = "Changeling"
set name = "Rapid Regeneration (50)"
set desc = "Heal ourselves of most injuries instantly."
var/datum/component/antag/changeling/changeling = changeling_power(50,0,100,UNCONSCIOUS)
if(!changeling)
return 0
changeling.chem_charges -= 50
if(ishuman(src))
var/mob/living/carbon/human/C = src
var/healing_amount = 40
if(changeling.recursive_enhancement)
healing_amount = C.getMaxHealth()
to_chat(src, span_notice("We completely heal ourselves."))
spawn(0)
C.adjustBruteLoss(-healing_amount)
C.adjustFireLoss(-healing_amount)
C.adjustOxyLoss(-healing_amount)
C.adjustCloneLoss(-healing_amount)
C.adjustBrainLoss(-healing_amount)
C.restore_blood()
C.species.create_organs(C)
C.restore_all_organs()
C.blinded = 0
C.SetBlinded(0)
C.eye_blurry = 0
C.ear_deaf = 0
C.ear_damage = 0
// make the icons look correct
C.regenerate_icons()
C.UpdateAppearance()
// now make it obvious that we're not human (or whatever xeno race they are impersonating)
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
var/T = get_turf(src)
new /obj/effect/gibspawner/human(T)
visible_message(span_warning("With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!"),
span_notice("We reform our body. We are whole once more."),
span_warningplain("You hear organic matter ripping and tearing!"))
feedback_add_details("changeling_powers","RR")
return 1

View File

@@ -0,0 +1,25 @@
//Updated
/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/component/antag/changeling/changeling = changeling_power(0,0,100,UNCONSCIOUS)
if(!changeling)
return FALSE
if(changeling.recursive_enhancement)
to_chat(src, span_warning("We will no longer empower our abilities."))
changeling.recursive_enhancement = FALSE
return FALSE
to_chat(src, span_notice("We empower ourselves. Our abilities will now be extra potent."))
changeling.recursive_enhancement = TRUE
feedback_add_details("changeling_powers","RE")
return TRUE

View File

@@ -0,0 +1,32 @@
/mob/proc/changeling_respec()
set category = "Changeling"
set name = "Re-adapt"
set desc = "Allows us to refund our purchased abilities."
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100)
if(!changeling)
return
if(changeling.readapts <= 0)
to_chat(src, span_warning("We must first absorb another compatible creature!"))
changeling.readapts = 0
return
src.remove_changeling_powers() //First, remove the verbs.
var/datum/component/antag/changeling/ling_datum = changeling
ling_datum.readapts--
ling_datum.purchased_powers = list() //Then wipe all the powers we bought.
ling_datum.geneticpoints = ling_datum.max_geneticpoints //Now refund our points to the maximum.
ling_datum.chem_recharge_rate = 0.5 //If glands were bought, revert that upgrade.
ling_datum.thermal_sight = FALSE
changeling.recursive_enhancement = 0 //Ensures this is cleared
ling_datum.chem_storage = 50
if(ishuman(src))
var/mob/living/carbon/human/H = src
// H.does_not_breathe = 0 //If self respiration was bought, revert that too.
H.remove_modifiers_of_type(/datum/modifier/endoarmor) //Revert endoarmor too.
src.make_changeling() //And give back our freebies.
to_chat(src, span_notice("We have removed our evolutions from this form, and are now ready to readapt."))
ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])")

View File

@@ -0,0 +1,106 @@
/datum/power/changeling/changeling_revive
name = "Revive"
desc = "We revive from our death-like state."
helptext = "Regeneration must first be started via Regenerative Stasis."
ability_icon_state = "ling_revive"
genomecost = 0
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_revive
//Revive from revival stasis
/mob/proc/changeling_revive()
set category = "Changeling"
set name = "Revive"
set desc = "We are ready to revive ourselves on command."
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100,DEAD)
if(!changeling)
return FALSE
if(stat != DEAD)
to_chat(src, span_danger("We are not dead."))
return FALSE
if(!changeling.is_reviving)
to_chat(src, span_danger("We have not begun the regeneration process yet.."))
return FALSE
if(changeling.is_on_cooldown(FAKE_DEATH))
to_chat(src, span_danger("We are still recovering. We will be able to revive again in [(changeling.get_cooldown(FAKE_DEATH) - world.time)/10] seconds."))
return FALSE
if(changeling.max_geneticpoints < 0) //Absorbed by another ling
to_chat(src, span_danger("You have no genomes, not even your own, and cannot revive."))
return FALSE
if(src.stat == DEAD)
dead_mob_list -= src
living_mob_list += src
var/mob/living/carbon/C = src
C.tod = null
C.setToxLoss(0)
C.setOxyLoss(0)
C.setCloneLoss(0)
C.SetParalysis(0)
C.SetStunned(0)
C.SetWeakened(0)
C.radiation = 0
C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss())
C.reagents.clear_reagents()
if(ishuman(C))
var/mob/living/carbon/human/H = src
H.species.create_organs(H)
H.restore_all_organs(ignore_prosthetic_prefs=1) //Covers things like fractures and other things not covered by the above.
H.restore_blood()
H.mutations.Remove(HUSK)
H.status_flags &= ~DISFIGURED
H.update_icons_body()
for(var/limb in H.organs_by_name)
var/obj/item/organ/external/current_limb = H.organs_by_name[limb]
if(current_limb)
current_limb.relocate()
current_limb.open = 0
BITSET(H.hud_updateflag, HEALTH_HUD)
BITSET(H.hud_updateflag, STATUS_HUD)
BITSET(H.hud_updateflag, LIFE_HUD)
if(H.handcuffed)
var/obj/item/W = H.handcuffed
H.handcuffed = null
if(H.buckled && H.buckled.buckle_require_restraints)
H.buckled.unbuckle_mob()
H.update_handcuffed()
if (H.client)
H.client.screen -= W
W.forceMove(H.loc)
W.dropped(H)
if(W)
W.layer = initial(W.layer)
if(H.legcuffed)
var/obj/item/W = H.legcuffed
H.legcuffed = null
H.update_inv_legcuffed()
if(H.client)
H.client.screen -= W
W.forceMove(H.loc)
W.dropped(H)
if(W)
W.layer = initial(W.layer)
if(istype(H.wear_suit, /obj/item/clothing/suit/straight_jacket))
var/obj/item/clothing/suit/straight_jacket/SJ = H.wear_suit
SJ.forceMove(H.loc)
SJ.dropped(H)
H.wear_suit = null
H.UpdateAppearance()
C.halloss = 0
C.shock_stage = 0 //Pain
to_chat(C, span_notice("We have regenerated."))
C.update_canmove()
feedback_add_details("changeling_powers","CR")
C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
changeling.is_reviving = FALSE
return TRUE

View File

@@ -0,0 +1,32 @@
//Updated
/datum/power/changeling/self_respiration
name = "Self Respiration"
desc = "We evolve our body to no longer require drawing oxygen from the atmosphere."
helptext = "We will no longer require internals, and we cannot inhale any gas, including harmful ones."
ability_icon_state = "ling_toggle_breath"
genomecost = 0
verbpath = /mob/proc/changeling_self_respiration
//No breathing required
/mob/proc/changeling_self_respiration()
set category = "Changeling"
set name = "Toggle Breathing"
set desc = "We choose whether or not to breathe."
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100,UNCONSCIOUS)
if(!changeling)
return FALSE
if(istype(src,/mob/living/carbon))
var/mob/living/carbon/C = src
if(C.suiciding)
to_chat(src, "You're committing suicide, this isn't going to work.")
return FALSE
if(C.does_not_breathe == FALSE)
C.does_not_breathe = TRUE
to_chat(src, span_notice("We stop breathing, as we no longer need to."))
return TRUE
else
C.does_not_breathe = FALSE
to_chat(src, span_notice("We resume breathing, as we now need to again."))
return FALSE

View File

@@ -0,0 +1,148 @@
//Updated
/datum/power/changeling/resonant_shriek
name = "Resonant Shriek"
desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
helptext = "Lights are blown, organics are disoriented, and synthetics act as if they were flashed."
enhancedtext = "Range is doubled."
ability_icon_state = "ling_resonant_shriek"
genomecost = 2
verbpath = /mob/proc/changeling_resonant_shriek
/datum/power/changeling/dissonant_shriek
name = "Dissonant Shriek"
desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics."
helptext = "Creates a moderate sized EMP."
enhancedtext = "Range is doubled."
ability_icon_state = "ling_dissonant_shriek"
genomecost = 2
verbpath = /mob/proc/changeling_dissonant_shriek
//A flashy ability, good for crowd control and sewing chaos.
/mob/proc/changeling_resonant_shriek()
set category = "Changeling"
set name = "Resonant Shriek (20)"
set desc = "Emits a high-frequency sound that confuses and deafens organics, blows out nearby lights, and overloads synthetics' sensors."
var/datum/component/antag/changeling/changeling = changeling_power(20,0,100,CONSCIOUS)
if(!changeling)
return FALSE
if(changeling.is_on_cooldown(CHANGELING_SCREECH))
to_chat(src, span_notice("We are still recovering. We will be able to screech again in [(changeling.get_cooldown(CHANGELING_SCREECH) - world.time)/10] seconds."))
return
if(is_muzzled())
to_chat(src, span_danger("Mmmf mrrfff!"))
return FALSE
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.silent)
to_chat(src, span_danger("You can't speak!"))
return FALSE
if(!isturf(loc))
to_chat(src, span_warning("Shrieking here would be a bad idea."))
return FALSE
src.break_cloak() //No more invisible shrieking
changeling.chem_charges -= 20
var/range = 4
if(changeling.recursive_enhancement)
range = range * 2
to_chat(src, span_notice("We are extra loud."))
visible_message(span_notice("[src] appears to shout."))
var/list/affected = list()
for(var/mob/living/M in range(range, src))
if(iscarbon(M))
var/datum/component/antag/changeling/m_comp = M.GetComponent(/datum/component/antag/changeling)
if(!M.mind || !m_comp)
if(M.get_ear_protection() >= 2)
continue
to_chat(M, span_danger("You hear an extremely loud screeching sound! It \
[pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you."))
M.adjustEarDamage(0,30)
M.Confuse(20)
M << sound('sound/effects/screech.ogg')
affected += M
else
if(M != src)
to_chat(M, span_notice("You hear a familiar screech from nearby. It has no effect on you."))
M << sound('sound/effects/screech.ogg')
if(issilicon(M))
M << sound('sound/weapons/flash.ogg')
to_chat(M, span_notice("Auditory input overloaded. Reinitializing..."))
M.Weaken(rand(5,10))
affected += M
for(var/obj/machinery/light/L in range(range, src))
L.on = TRUE
L.broken()
changeling.set_cooldown(CHANGELING_SCREECH, 10 SECONDS)
addtimer(CALLBACK(src, PROC_REF(changeling_screech_ready)), 10 SECONDS, TIMER_DELETE_ME)
add_attack_logs(src,affected,"Used resonant shriek")
feedback_add_details("changeling_powers","RS")
return TRUE
//EMP version
/mob/proc/changeling_dissonant_shriek()
set category = "Changeling"
set name = "Dissonant Shriek (20)"
set desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics."
var/datum/component/antag/changeling/changeling = changeling_power(20,0,100,CONSCIOUS)
if(!changeling)
return FALSE
if(is_muzzled())
to_chat(src, span_danger("Mmmf mrrfff!"))
return FALSE
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.silent)
to_chat(src, span_danger("You can't speak!"))
return FALSE
if(changeling.is_on_cooldown(CHANGELING_SCREECH))
to_chat(src, span_notice("We are still recovering. We will be able to screech again in [(changeling.get_cooldown(CHANGELING_SCREECH) - world.time)/10] seconds."))
return
if(!isturf(loc))
to_chat(src, span_warning("Shrieking here would be a bad idea."))
return FALSE
break_cloak() //No more invisible shrieking
changeling.chem_charges -= 20
var/range_heavy = 1
var/range_med = 2
var/range_light = 4
var/range_long = 6
if(changeling.recursive_enhancement)
range_heavy = range_heavy * 2
range_med = range_med * 2
range_light = range_light * 2
range_long = range_long * 2
to_chat(src, span_notice("We are extra loud."))
changeling.recursive_enhancement = FALSE
for(var/obj/machinery/light/L in range(range_light, src))
L.on = TRUE
L.broken()
empulse(get_turf(src), range_heavy, range_med, range_light, range_long)
changeling.set_cooldown(CHANGELING_SCREECH, 10 SECONDS)
addtimer(CALLBACK(src, PROC_REF(changeling_screech_ready)), 10 SECONDS, TIMER_DELETE_ME)
visible_message(span_notice("[src] appears to shout."))
add_attack_logs(src,null,"Use dissonant shriek")
return TRUE
/mob/proc/changeling_screech_ready()
to_chat(src, span_notice("We are ready to release another screech."))

View File

@@ -0,0 +1,28 @@
//Updated
/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."
enhancedtext = "Silence duration is extended."
ability_icon_state = "ling_sting_mute"
genomecost = 2
allowduringlesserform = TRUE
verbpath = /mob/proc/changeling_silence_sting
/mob/proc/changeling_silence_sting()
set category = "Changeling"
set name = "Silence sting (10)"
set desc="Sting target"
var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting)
var/datum/component/antag/changeling/comp = is_changeling(src)
if(!T)
return FALSE
add_attack_logs(src,T,"Silence sting (changeling)")
var/duration = 30
if(comp.recursive_enhancement)
duration = duration + 10
to_chat(src, span_notice("They will be unable to cry out in fear for a little longer."))
T.silent += duration
feedback_add_details("changeling_powers","SS")
return TRUE

View File

@@ -0,0 +1,62 @@
/datum/power/changeling/transform
name = "Transform"
desc = "We take on the appearance and voice of one we have absorbed."
ability_icon_state = "ling_transform"
genomecost = 0
verbpath = /mob/proc/changeling_transform
//Change our DNA to that of somebody we've absorbed.
/mob/proc/changeling_transform()
set category = "Changeling"
set name = "Transform (5)"
var/datum/component/antag/changeling/changeling = changeling_power(5,1,0)
if(!changeling)
return
if(!isturf(loc))
to_chat(src, span_warning("Transforming here would be a bad idea."))
return 0
var/list/names = list()
for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
names += "[DNA.name]"
var/S = tgui_input_list(src, "Select the target DNA:", "Target DNA", names)
if(!S)
return
var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
changeling.chem_charges -= 5
src.visible_message(span_warning("[src] transforms!"))
changeling.geneticdamage = 5
if(ishuman(src))
var/mob/living/carbon/human/H = src
var/newSpecies = chosen_dna.speciesName
H.set_species(newSpecies)
qdel_swap(src.dna, chosen_dna.dna.Clone())
if(ishuman(src))
var/mob/living/carbon/human/H = src
H.identifying_gender = chosen_dna.identifying_gender
H.flavor_texts = chosen_dna.flavour_texts ? chosen_dna.flavour_texts.Copy() : null
real_name = chosen_dna.name
UpdateAppearance()
domutcheck(src, null)
UpdateAppearance()
changeling_update_languages(changeling.absorbed_languages)
if(chosen_dna.genMods)
var/mob/living/carbon/human/self = src
for(var/datum/modifier/mod in self.modifiers)
self.modifiers.Remove(mod.type)
for(var/datum/modifier/mod in chosen_dna.genMods)
self.modifiers.Add(mod.type)
regenerate_icons()
feedback_add_details("changeling_powers","TR")
return TRUE

View File

@@ -0,0 +1,44 @@
//Suggested to leave unchecked because this is why we can't have nice things.
/datum/power/changeling/transformation_sting
name = "Transformation Sting"
desc = "We silently sting a human, injecting a retrovirus that forces them to transform into another."
helptext = "Does not provide a warning to others. The victim will transform much like a changeling would."
ability_icon_state = "ling_sting_transform"
genomecost = 3
verbpath = /mob/proc/changeling_transformation_sting
/mob/proc/changeling_transformation_sting()
set category = "Changeling"
set name = "Transformation sting (40)"
set desc="Sting target"
var/datum/component/antag/changeling/changeling = changeling_power(40)
if(!changeling)
return FALSE
var/list/names = list()
for(var/datum/dna/DNA in changeling.absorbed_dna)
names += "[DNA.real_name]"
var/S = tgui_input_list(src, "Select the target DNA:", "Target DNA", names)
if(!S)
return
var/datum/dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting)
if(!T)
return FALSE
if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T)))
to_chat(src, span_warning("Our sting appears ineffective against its DNA."))
return FALSE
add_attack_logs(src,T,"Transformation sting (changeling)")
T.visible_message(span_warning("[T] transforms!"))
qdel_swap(T.dna, chosen_dna.Clone())
T.real_name = chosen_dna.real_name
T.UpdateAppearance()
domutcheck(T, null)
feedback_add_details("changeling_powers","TS")
return TRUE

View File

@@ -0,0 +1,20 @@
//Updated
/datum/power/changeling/unfat_sting
name = "Unfat Sting"
desc = "We silently sting a human, forcing them to rapidly metabolize their fat."
genomecost = 1
verbpath = /mob/proc/changeling_unfat_sting
/mob/proc/changeling_unfat_sting()
set category = "Changeling"
set name = "Unfat sting (5)"
set desc = "Sting target"
var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting)
if(!T)
return FALSE
add_attack_logs(src,T,"Unfat sting (changeling)")
to_chat(T, span_danger("you feel a small prick as stomach churns violently and you become to feel skinnier."))
T.adjust_nutrition(-max(100, T.nutrition/1.15)) //Decrease their nutrition by 100 or 85%, whatever is higher. Ex: 1000 nutrition becomes ~130. 6000 nutrition becomes 800.
feedback_add_details("changeling_powers","US")
return TRUE

View File

@@ -0,0 +1,92 @@
/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 = 3
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."
var/datum/component/antag/changeling/changeling = changeling_power(0,0,100,CONSCIOUS)
if(!changeling)
return
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(changeling.cloaked)
changeling.cloaked = FALSE
return TRUE
if(H.has_modifier_of_type(/datum/modifier/changeling_camouflage)) //If they double-clicked the button while invis.
to_chat(H, span_warning("We are already camouflaged!"))
return TRUE
//We delay the check, so that people can uncloak without needing 10 chemicals to do so.
changeling = changeling_power(10,0,100,CONSCIOUS)
if(!changeling)
return FALSE
changeling.chem_charges -= 10
to_chat(H, span_notice("We vanish from sight, and will remain hidden, so long as we move carefully."))
changeling.cloaked = TRUE
if(changeling.recursive_enhancement)
to_chat(src, span_notice("We may move at our normal speed while hidden."))
H.add_modifier(/datum/modifier/changeling_camouflage/recursive, 0)
else
H.add_modifier(/datum/modifier/changeling_camouflage, 0)
/datum/modifier/changeling_camouflage
name = "Camoflauge"
desc = "We are near-impossible to see."
var/must_walk = TRUE
var/datum/component/antag/changeling/comp
var/old_regen_rate
var/mob/living/carbon/human/owner
/datum/modifier/changeling_camouflage/recursive
must_walk = FALSE
/datum/modifier/changeling_camouflage/can_apply(var/mob/living/L, var/suppress_failure = FALSE)
comp = L.GetComponent(/datum/component/antag/changeling)
if(!comp)
return FALSE
/datum/modifier/changeling_camouflage/on_applied()
comp = holder.GetComponent(/datum/component/antag/changeling)
if(must_walk)
holder.set_m_intent(I_WALK)
old_regen_rate = comp.chem_recharge_rate
comp.chem_recharge_rate = 0
animate(holder,alpha = 255, alpha = 10, time = 10)
/datum/modifier/changeling_camouflage/on_expire()
animate(holder,alpha = 10, alpha = 255, time = 10)
owner.invisibility = initial(owner.invisibility)
holder.visible_message(span_warning("[holder] suddenly fades in, seemingly from nowhere!"),
span_notice("We revert our camouflage, revealing ourselves."))
holder.set_m_intent(I_RUN)
comp.cloaked = FALSE
comp.chem_recharge_rate = old_regen_rate
comp = null
owner = null
/datum/modifier/changeling_camouflage/tick()
if(holder.m_intent != I_WALK && must_walk) // Moving too fast uncloaks you.
expire(silent = TRUE)
if(!comp.cloaked)
expire(silent = TRUE)
if(holder.stat) // Dead or unconscious lings can't stay cloaked.
expire(silent = TRUE)
if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned lings also can't stay cloaked.
expire(silent = TRUE)
if(comp.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 += comp.chem_recharge_rate
comp.chem_recharge_rate = 0