mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-23 00:22:12 +00:00
Hey remember when ling reworks were a thing? Anyway this implements the hivemind thing that Geeves was working on (And then I was working on). It actually works for messages, ghosting, kicking, etc now. Succ'd people can now remain as part of the changeling's local hivemind and chat with them. If they salt, ling can kick them. If they don't want to participate this way, they can ghost. If I actually get around to it, this also serves as the basis for allowing the ling to do things with them, such as creating horror mobs, injecting them into corpses, or other ideas that might get the succ'd person back into the round in a different way. Which, should hopefully reduce complaints and make ling way cooler.
166 lines
5.7 KiB
Plaintext
166 lines
5.7 KiB
Plaintext
var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
|
|
|
|
/datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
|
|
var/list/datum/absorbed_dna/absorbed_dna = list()
|
|
var/list/absorbed_languages = list()
|
|
var/list/hivemind_members = list()
|
|
var/absorbedcount = 0
|
|
var/chem_charges = 20
|
|
var/chem_recharge_rate = 0.5
|
|
var/chem_storage = 50
|
|
var/sting_range = 1
|
|
var/changelingID = "Changeling"
|
|
var/geneticdamage = 0
|
|
var/isabsorbing = 0
|
|
var/geneticpoints = 5
|
|
var/list/purchasedpowers = list()
|
|
var/mimicing = ""
|
|
var/mimiced_accent = "Biesellite"
|
|
var/justate
|
|
|
|
/datum/changeling/New(var/gender=FEMALE)
|
|
..()
|
|
var/honorific = (gender == FEMALE) ? "Ms." : "Mr."
|
|
if(possible_changeling_IDs.len)
|
|
changelingID = pick(possible_changeling_IDs)
|
|
possible_changeling_IDs -= changelingID
|
|
changelingID = "[honorific] [changelingID]"
|
|
else
|
|
changelingID = "[honorific] [rand(1,999)]"
|
|
|
|
/datum/changeling/proc/regenerate()
|
|
chem_charges = min(max(0, chem_charges + chem_recharge_rate), chem_storage)
|
|
geneticdamage = max(0, geneticdamage - 1)
|
|
|
|
/datum/changeling/proc/GetDNA(var/dna_owner)
|
|
for(var/datum/absorbed_dna/DNA in absorbed_dna)
|
|
if(dna_owner == DNA.name)
|
|
return DNA
|
|
|
|
/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA)
|
|
var/datum/changeling/changeling = null
|
|
if(src.mind && src.mind.changeling)
|
|
changeling = src.mind.changeling
|
|
if(!changeling)
|
|
return
|
|
|
|
for(var/language in newDNA.languages)
|
|
changeling.absorbed_languages |= language
|
|
|
|
changeling_update_languages(changeling.absorbed_languages)
|
|
|
|
if(!changeling.GetDNA(newDNA.name)) // Don't duplicate - I wonder if it's possible for it to still be a different DNA? DNA code could use a rewrite
|
|
changeling.absorbed_dna += newDNA
|
|
|
|
//Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human
|
|
/mob/proc/make_changeling()
|
|
|
|
if(!mind)
|
|
return
|
|
if(!mind.changeling)
|
|
mind.changeling = new /datum/changeling(gender)
|
|
|
|
verbs += /datum/changeling/proc/EvolutionMenu
|
|
add_language("Changeling")
|
|
|
|
var/lesser_form = !ishuman(src)
|
|
|
|
if(!powerinstances.len)
|
|
for(var/P in powers)
|
|
powerinstances += new P()
|
|
|
|
// Code to auto-purchase free powers.
|
|
for(var/datum/power/changeling/P in powerinstances)
|
|
if(!P.genomecost) // Is it free?
|
|
if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already?
|
|
mind.changeling.purchasePower(mind, P.name, 0) // Purchase it. Don't remake our verbs, we're doing it after this.
|
|
|
|
for(var/datum/power/changeling/P in mind.changeling.purchasedpowers)
|
|
if(P.isVerb)
|
|
if(lesser_form && !P.allowduringlesserform) continue
|
|
if(!(P in src.verbs))
|
|
src.verbs += P.verbpath
|
|
|
|
for(var/language in languages)
|
|
mind.changeling.absorbed_languages |= language
|
|
|
|
var/mob/living/carbon/human/H = src
|
|
if(istype(H))
|
|
var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.get_cloning_variant(), H.languages)
|
|
absorbDNA(newDNA)
|
|
mind.changeling.mimiced_accent = H.accent
|
|
|
|
return TRUE
|
|
|
|
//removes our changeling verbs
|
|
/mob/proc/remove_changeling_powers()
|
|
if(!mind || !mind.changeling)
|
|
return
|
|
for(var/datum/power/changeling/P in mind.changeling.purchasedpowers)
|
|
if(P.isVerb)
|
|
verbs -= P.verbpath
|
|
|
|
|
|
//Helper proc. Does all the checks and stuff for us to avoid copypasta
|
|
/mob/proc/changeling_power(var/required_chems=0, var/required_dna=0, var/max_genetic_damage=100, var/max_stat=0)
|
|
|
|
if(!src.mind)
|
|
return
|
|
if(!iscarbon(src))
|
|
return
|
|
|
|
var/datum/changeling/changeling = src.mind.changeling
|
|
if(!changeling)
|
|
log_and_message_admins("has the changeling_transform() verb but is not a changeling.", src, get_turf(src))
|
|
return
|
|
if(src.stat > max_stat)
|
|
to_chat(src, "<span class='warning'>We are incapacitated.</span>")
|
|
return
|
|
if(changeling.absorbed_dna.len < required_dna)
|
|
to_chat(src, "<span class='warning'>We require at least [required_dna] samples of compatible DNA.</span>")
|
|
return
|
|
if(changeling.chem_charges < required_chems)
|
|
to_chat(src, "<span class='warning'>We require at least [required_chems] units of chemicals to do that!</span>")
|
|
return
|
|
if(changeling.geneticdamage > max_genetic_damage)
|
|
to_chat(src, "<span class='warning'>Our genomes are still reassembling. We need time to recover first.</span>")
|
|
return
|
|
return changeling
|
|
|
|
//Used to dump the languages from the changeling datum into the actual mob.
|
|
/mob/proc/changeling_update_languages(var/updated_languages)
|
|
languages = list()
|
|
for(var/language in updated_languages)
|
|
languages += language
|
|
//This isn't strictly necessary but just to be safe...
|
|
add_language("Changeling")
|
|
return
|
|
|
|
//DNA related datums
|
|
|
|
/datum/absorbed_dna
|
|
var/name
|
|
var/datum/dna/dna
|
|
var/speciesName
|
|
var/list/languages
|
|
|
|
/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages)
|
|
..()
|
|
name = newName
|
|
dna = newDNA
|
|
speciesName = newSpecies
|
|
languages = newLanguages
|
|
|
|
//Helper for stingcode
|
|
|
|
/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1)
|
|
if(M.loc == src.loc)
|
|
return TRUE //target and source are in the same thing
|
|
if(!isturf(src.loc) || !isturf(M.loc))
|
|
to_chat(src, "<span class='warning'>We cannot reach \the [M] with a sting!</span>")
|
|
return FALSE //One is inside, the other is outside something.
|
|
// Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising
|
|
if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail
|
|
to_chat(src, "<span class='warning'>We cannot find a path to sting \the [M] by!</span>")
|
|
return FALSE
|
|
return TRUE |