Files
Aurora.3/code/game/gamemodes/changeling/helpers/_framework.dm
Doxxmedearly 480ab2efab Actually gets ling hivemind in (#9473)
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.
2020-07-29 21:55:27 +03:00

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