Files
Paradise/code/datums/soullink.dm

215 lines
6.1 KiB
Plaintext

/mob/living
var/list/ownedSoullinks //soullinks we are the owner of
var/list/sharedSoullinks //soullinks we are a/the sharer of
/mob/living/Destroy()
for(var/s in ownedSoullinks)
var/datum/soullink/S = s
S.ownerDies(FALSE)
qdel(s) //If the owner is destroy()'d, the soullink is destroy()'d
ownedSoullinks = null
for(var/s in sharedSoullinks)
var/datum/soullink/S = s
S.sharerDies(FALSE)
S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
sharedSoullinks = null
return ..()
//Keeps track of a Mob->Mob (potentially Player->Player) connection
//Can be used to trigger actions on one party when events happen to another
//Eg: shared deaths
//Can be used to form a linked list of mob-hopping
//Does NOT transfer with minds
/datum/soullink
var/mob/living/soulowner
var/mob/living/soulsharer
var/id //Optional ID, for tagging and finding specific instances
/datum/soullink/Destroy()
if(soulowner)
LAZYREMOVE(soulowner.ownedSoullinks, src)
soulowner = null
if(soulsharer)
LAZYREMOVE(soulsharer.sharedSoullinks, src)
soulsharer = null
return ..()
/datum/soullink/proc/removeSoulsharer(mob/living/sharer)
if(soulsharer == sharer)
soulsharer = null
LAZYREMOVE(sharer.sharedSoullinks, src)
//Used to assign variables, called primarily by soullink()
//Override this to create more unique soullinks (Eg: 1->Many relationships)
//Return TRUE/FALSE to return the soullink/null in soullink()
/datum/soullink/proc/parseArgs(mob/living/owner, mob/living/sharer)
if(!owner || !sharer)
return FALSE
soulowner = owner
soulsharer = sharer
LAZYADD(owner.ownedSoullinks, src)
LAZYADD(sharer.sharedSoullinks, src)
return TRUE
//Runs after /living death()
//Override this for content
/datum/soullink/proc/ownerDies(gibbed, mob/living/owner)
//Runs after /living death()
//Override this for content
/datum/soullink/proc/sharerDies(gibbed, mob/living/owner)
//Runs after /living update_revive()
//Override this for content
/datum/soullink/proc/ownerRevives(mob/living/owner)
//Runs after /living update_revive()
//Override this for content
/datum/soullink/proc/sharerRevives(mob/living/owner)
//Quick-use helper
/proc/soullink(typepath, ...)
var/datum/soullink/S = new typepath()
if(S.parseArgs(arglist(args.Copy(2, 0))))
return S
/////////////////
// MULTISHARER //
/////////////////
//Abstract soullink for use with 1 Owner -> Many Sharer setups
/datum/soullink/multisharer
var/list/soulsharers
/datum/soullink/multisharer/parseArgs(mob/living/owner, list/sharers)
if(!owner || !LAZYLEN(sharers))
return FALSE
soulowner = owner
soulsharers = sharers
LAZYADD(owner.ownedSoullinks, src)
for(var/l in sharers)
var/mob/living/L = l
LAZYADD(L.sharedSoullinks, src)
return TRUE
/datum/soullink/multisharer/removeSoulsharer(mob/living/sharer)
LAZYREMOVE(soulsharers, sharer)
/////////////////
// SHARED FATE //
/////////////////
//When the soulowner dies, the soulsharer dies, and vice versa
//This is intended for two players(or AI) and two mobs
/datum/soullink/sharedfate/ownerDies(gibbed, mob/living/owner)
if(soulsharer)
soulsharer.death(gibbed)
/datum/soullink/sharedfate/sharerDies(gibbed, mob/living/sharer)
if(soulowner)
soulowner.death(gibbed)
/////////////////
// Demon Bind //
/////////////////
//When the soulowner dies, the soulsharer dies, but NOT vice versa
//This is intended for two players(or AI) and two mobs
/datum/soullink/oneway/ownerDies(gibbed, mob/living/owner)
if(soulsharer)
soulsharer.dust(FALSE)
/////////////////
// SHARED BODY //
/////////////////
//When the soulsharer dies, they're placed in the soulowner, who remains alive
//If the soulowner dies, the soulsharer is killed and placed into the soulowner (who is still dying)
//This one is intended for one player moving between many mobs
/datum/soullink/sharedbody/ownerDies(gibbed, mob/living/owner)
if(soulowner && soulsharer)
if(soulsharer.mind)
soulsharer.mind.transfer_to(soulowner)
soulsharer.death(gibbed)
/datum/soullink/sharedbody/sharerDies(gibbed, mob/living/sharer)
if(soulowner && soulsharer && soulsharer.mind)
soulsharer.mind.transfer_to(soulowner)
//////////////////////
// REPLACEMENT POOL //
//////////////////////
//When the owner dies, one of the sharers is placed in the owner's body, fully healed
//Sort of a "winner-stays-on" soullink
//Gibbing ends it immediately
/datum/soullink/multisharer/replacementpool/ownerDies(gibbed, mob/living/owner)
if(LAZYLEN(soulsharers) && !gibbed) //let's not put them in some gibs
var/list/souls = shuffle(soulsharers.Copy())
for(var/l in souls)
var/mob/living/L = l
if(L.stat != DEAD && L.mind)
L.mind.transfer_to(soulowner)
soulowner.revive(TRUE, TRUE)
L.death(FALSE)
//Lose your claim to the throne!
/datum/soullink/multisharer/replacementpool/sharerDies(gibbed, mob/living/sharer)
removeSoulsharer(sharer)
////////////////
// SOUL HOOK //
////////////////
// When the owner transitions from dead to alive or vice versa,
// the linked atom is notified
// Atoms that actually utilize this system are responsible for handling the GC cleanup themselves
// Splashing the GC handling onto every atom would be a big old waste
/datum/soullink/soulhook
var/atom/movable/otherend
/datum/soullink/soulhook/Destroy()
if(otherend)
LAZYREMOVE(otherend.sharedSoulhooks, src)
otherend = null
return ..()
/datum/soullink/soulhook/parseArgs(mob/living/owner, atom/movable/other)
if(!owner || !other)
return FALSE
soulowner = owner
otherend = other
LAZYADD(owner.ownedSoullinks, src)
LAZYADD(other.sharedSoulhooks, src)
return TRUE
/datum/soullink/soulhook/ownerDies(gibbed, mob/living/owner)
if(otherend)
otherend.onSoullinkDeath(gibbed, owner)
/datum/soullink/soulhook/ownerRevives(mob/living/owner)
if(otherend)
otherend.onSoullinkRevive(owner)
// oops I'm butchering the application of this
/datum/soullink/soulhook/removeSoulsharer(atom/movable/other)
if(otherend == other)
otherend = null
LAZYREMOVE(other.sharedSoulhooks, src)
qdel(src) // not much point in a soul link with one end out of the picture for good
/atom/movable
var/list/sharedSoulhooks = null
/atom/movable/proc/onSoullinkDeath(gibbed, mob/living/owner)
/atom/movable/proc/onSoullinkRevive(mob/living/owner)