mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
Co-authored-by: MeepleMuncher <76881946+MeepleMuncher@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
286 lines
8.8 KiB
Plaintext
286 lines
8.8 KiB
Plaintext
// Procs for living mobs based around mob transformation. Initially made for the mouseray, they are now used in various other places and the main procs are now called from here.
|
|
|
|
/mob/living/proc/tf_into(var/A, var/allow_emotes = FALSE, var/object_name)
|
|
if(!object_name)
|
|
object_name = name
|
|
if(isliving(A))
|
|
var/mob/living/M = A
|
|
M.mob_tf(src)
|
|
return
|
|
if(isitem(A))
|
|
var/obj/item/I = A
|
|
I.inhabit_item(src, object_name, src, allow_emotes)
|
|
var/mob/living/possessed_voice = I.possessed_voice
|
|
I.trash_eatable = devourable
|
|
I.unacidable = !digestable
|
|
forceMove(possessed_voice)
|
|
|
|
/mob/living/proc/mob_tf(var/mob/living/M)
|
|
if(!istype(M))
|
|
return
|
|
if(src && isliving(src))
|
|
faction = M.faction
|
|
if(istype(src, /mob/living/simple_mob))
|
|
var/mob/living/simple_mob/S = src
|
|
if(!S.voremob_loaded)
|
|
S.init_vore(TRUE)
|
|
new /obj/effect/effect/teleport_greyscale(M.loc)
|
|
for(var/obj/belly/B as anything in src.vore_organs)
|
|
src.vore_organs -= B
|
|
qdel(B)
|
|
src.vore_organs = list()
|
|
src.name = M.name
|
|
src.real_name = M.real_name
|
|
for(var/lang in M.languages)
|
|
src.languages |= lang
|
|
M.copy_vore_prefs_to_mob(src)
|
|
src.vore_selected = M.vore_selected
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
if(ishuman(src))
|
|
var/mob/living/carbon/human/N = src
|
|
N.gender = H.gender
|
|
N.identifying_gender = H.identifying_gender
|
|
else
|
|
src.gender = H.gender
|
|
else
|
|
src.gender = M.gender
|
|
if(ishuman(src))
|
|
var/mob/living/carbon/human/N = src
|
|
N.identifying_gender = M.gender
|
|
|
|
mob_belly_transfer(M)
|
|
M.soulgem.transfer_self(src) // Soulcatcher
|
|
|
|
nutrition = M.nutrition
|
|
src.ckey = M.ckey
|
|
if(M.ai_holder && src.ai_holder)
|
|
var/datum/ai_holder/old_AI = M.ai_holder
|
|
old_AI.set_stance(STANCE_SLEEP)
|
|
var/datum/ai_holder/new_AI = src.ai_holder
|
|
new_AI.hostile = old_AI.hostile
|
|
new_AI.retaliate = old_AI.retaliate
|
|
M.loc = src
|
|
M.forceMove(src)
|
|
src.tf_mob_holder = M
|
|
|
|
/mob/living/proc/mob_belly_transfer(var/mob/living/M)
|
|
for(var/obj/belly/B as anything in M.vore_organs)
|
|
B.loc = src
|
|
B.forceMove(src)
|
|
B.owner = src
|
|
M.vore_organs -= B
|
|
src.vore_organs += B
|
|
|
|
/mob/living
|
|
var/mob/living/tf_mob_holder = null
|
|
|
|
/mob/living/proc/revert_mob_tf()
|
|
if(!tf_mob_holder)
|
|
return
|
|
var/mob/living/ourmob = tf_mob_holder
|
|
if(soulgem) //Should always be the case, but...Safety. Done here first
|
|
soulgem.transfer_self(ourmob)
|
|
if(ourmob.loc != src)
|
|
if(isnull(ourmob.loc))
|
|
to_chat(src,span_notice("You have no body."))
|
|
tf_mob_holder = null
|
|
return
|
|
if(istype(ourmob.loc, /mob/living)) //Check for if body was transformed
|
|
ourmob = ourmob.loc
|
|
if(ourmob.ckey)
|
|
if(ourmob.tf_mob_holder && ourmob.tf_mob_holder == src)
|
|
//Body Swap
|
|
var/datum/mind/ourmind = src.mind
|
|
var/datum/mind/theirmind = ourmob.mind
|
|
ourmob.ghostize()
|
|
src.ghostize()
|
|
ourmob.mind = null
|
|
src.mind = null
|
|
ourmind.current = null
|
|
theirmind.current = null
|
|
ourmind.active = TRUE
|
|
ourmind.transfer_to(ourmob)
|
|
theirmind.active = TRUE
|
|
theirmind.transfer_to(src)
|
|
ourmob.tf_mob_holder = null
|
|
src.tf_mob_holder = null
|
|
else
|
|
to_chat(src,span_notice("Your body appears to be in someone else's control."))
|
|
return
|
|
src.mind.transfer_to(ourmob)
|
|
tf_mob_holder = null
|
|
return
|
|
new /obj/effect/effect/teleport_greyscale(src.loc)
|
|
if(ourmob.ai_holder)
|
|
var/datum/ai_holder/our_AI = ourmob.ai_holder
|
|
our_AI.set_stance(STANCE_IDLE)
|
|
tf_mob_holder = null
|
|
ourmob.ckey = ckey
|
|
var/turf/get_dat_turf = get_turf(src)
|
|
ourmob.loc = get_dat_turf
|
|
ourmob.forceMove(get_dat_turf)
|
|
if(!tf_form_ckey)
|
|
ourmob.vore_selected = vore_selected
|
|
vore_selected = null
|
|
for(var/obj/belly/B as anything in vore_organs)
|
|
B.loc = ourmob
|
|
B.forceMove(ourmob)
|
|
B.owner = ourmob
|
|
vore_organs -= B
|
|
ourmob.vore_organs += B
|
|
|
|
ourmob.Life(1)
|
|
|
|
if(ishuman(src))
|
|
for(var/obj/item/W in src)
|
|
if(istype(W, /obj/item/implant/backup) || istype(W, /obj/item/nif))
|
|
continue
|
|
src.drop_from_inventory(W)
|
|
|
|
if(tf_form == ourmob)
|
|
if(tf_form_ckey)
|
|
src.ckey = tf_form_ckey
|
|
else
|
|
src.mind = null
|
|
ourmob.tf_form = src
|
|
src.forceMove(ourmob)
|
|
else
|
|
qdel(src)
|
|
|
|
/mob/living/proc/handle_tf_holder()
|
|
if(!tf_mob_holder)
|
|
return
|
|
if(tf_mob_holder.loc != src) return // Prevent bodyswapped creatures having their life linked
|
|
if(stat != tf_mob_holder.stat)
|
|
if(stat == DEAD)
|
|
tf_mob_holder.death(FALSE, null)
|
|
if(tf_mob_holder.stat == DEAD)
|
|
death()
|
|
|
|
/mob/living/proc/copy_vore_prefs_to_mob(var/mob/living/new_mob)
|
|
//For primarily copying vore preference settings from a carbon mob to a simplemob
|
|
//It can be used for other things, but be advised, if you're using it to put a simplemob into a carbon mob, you're gonna be overriding a bunch of prefs
|
|
|
|
new_mob.ooc_notes = ooc_notes
|
|
new_mob.ooc_notes_likes = ooc_notes_likes
|
|
new_mob.ooc_notes_dislikes = ooc_notes_dislikes
|
|
new_mob.appendage_color = appendage_color
|
|
new_mob.appendage_alt_setting = appendage_alt_setting
|
|
|
|
VORE_PREF_TRANSFER(new_mob, src)
|
|
|
|
// Requires a /mob/living type path for transformation. Returns the new mob on success, null in all other cases.
|
|
// Just handles mob TF right now, but maybe we'll want to do something similar for items in the future.
|
|
/mob/living/proc/transform_into_mob(mob/living/new_form, pref_override = FALSE, revert = FALSE, shapeshifting = FALSE)
|
|
if(!src.mind)
|
|
return
|
|
if(!src.allow_spontaneous_tf && !pref_override)
|
|
return
|
|
if(src.tf_mob_holder) //If we're already transformed
|
|
if(revert)
|
|
revert_mob_tf()
|
|
return
|
|
else
|
|
return
|
|
else
|
|
if(src.stat == DEAD)
|
|
return
|
|
if(!ispath(new_form, /mob/living) && !ismob(new_form))
|
|
return
|
|
var/mob/living/new_mob
|
|
if(shapeshifting && src.tf_form)
|
|
new_mob = src.tf_form
|
|
add_verb(new_mob,/mob/living/proc/shapeshift_form)
|
|
new_mob.tf_form = src
|
|
new_mob.forceMove(src.loc)
|
|
visible_message(span_warning("[src] twists and contorts, shapeshifting into a different form!"))
|
|
if(new_mob.ckey)
|
|
new_mob.tf_form_ckey = new_mob.ckey
|
|
else
|
|
new_mob = new new_form(get_turf(src))
|
|
|
|
if(new_mob && isliving(new_mob))
|
|
new_mob.faction = src.faction
|
|
if(istype(new_mob, /mob/living/simple_mob))
|
|
var/mob/living/simple_mob/S = new_mob
|
|
if(!S.voremob_loaded)
|
|
S.init_vore(TRUE)
|
|
new /obj/effect/effect/teleport_greyscale(src.loc)
|
|
if(!new_mob.ckey)
|
|
for(var/obj/belly/B as anything in new_mob.vore_organs)
|
|
new_mob.vore_organs -= B
|
|
qdel(B)
|
|
new_mob.vore_organs = list()
|
|
new_mob.name = src.name
|
|
new_mob.real_name = src.real_name
|
|
for(var/lang in src.languages)
|
|
new_mob.languages |= lang
|
|
src.copy_vore_prefs_to_mob(new_mob)
|
|
new_mob.vore_selected = src.vore_selected
|
|
if(ishuman(src))
|
|
var/mob/living/carbon/human/H = src
|
|
if(ishuman(new_mob))
|
|
var/mob/living/carbon/human/N = new_mob
|
|
N.gender = H.gender
|
|
N.identifying_gender = H.identifying_gender
|
|
else
|
|
new_mob.gender = H.gender
|
|
else
|
|
new_mob.gender = src.gender
|
|
if(ishuman(new_mob))
|
|
var/mob/living/carbon/human/N = new_mob
|
|
N.identifying_gender = src.gender
|
|
|
|
for(var/obj/belly/B as anything in src.vore_organs)
|
|
B.loc = new_mob
|
|
B.forceMove(new_mob)
|
|
B.owner = new_mob
|
|
src.vore_organs -= B
|
|
new_mob.vore_organs += B
|
|
new_mob.nutrition = src.nutrition
|
|
|
|
src.soulgem?.transfer_self(new_mob)
|
|
|
|
new_mob.ckey = src.ckey
|
|
if(new_mob.tf_form_ckey)
|
|
src.ckey = new_mob.tf_form_ckey
|
|
if(src.ai_holder && new_mob.ai_holder)
|
|
var/datum/ai_holder/old_AI = src.ai_holder
|
|
old_AI.set_stance(STANCE_SLEEP)
|
|
var/datum/ai_holder/new_AI = new_mob.ai_holder
|
|
new_AI.hostile = old_AI.hostile
|
|
new_AI.retaliate = old_AI.retaliate
|
|
src.loc = new_mob
|
|
src.forceMove(new_mob)
|
|
new_mob.tf_mob_holder = src
|
|
return new_mob
|
|
|
|
// Used to check if THIS MOB has been transformed into a different mob, as only the NEW mob uses tf_mob_holder.
|
|
// Necessary in niche cases where a proc interacts with the old body and needs to know it's been transformed (such as transforming into a mob then dying in virtual reality).
|
|
// Use this if you cannot use the tf_mob_holder var. Returns TRUE if transformed, FALSE if not.
|
|
/mob/living/proc/tfed_into_mob_check()
|
|
if(loc && isliving(loc))
|
|
var/mob/living/M = loc
|
|
if(istype(M) && M.tf_mob_holder && (M.tf_mob_holder == src))
|
|
return TRUE
|
|
else
|
|
return FALSE
|
|
else
|
|
return FALSE
|
|
|
|
/mob/living/proc/shapeshift_form()
|
|
set name = "Shapeshift Form"
|
|
set category = "Abilities.Shapeshift"
|
|
set desc = "Shape shift between set mob forms. (Requires a spawned mob to be varedited into the user's tf_form var as mob reference.)"
|
|
if(!istype(tf_form))
|
|
to_chat(src, span_notice("No shapeshift form set. (Requires a spawned mob to be varedited into the user's tf_form var as mob reference.)"))
|
|
return
|
|
else
|
|
transform_into_mob(tf_form, TRUE, TRUE, TRUE)
|
|
|
|
/mob/living/set_dir(var/new_dir)
|
|
. = ..()
|
|
if(size_multiplier != 1 || icon_scale_x != 1 && center_offset > 0)
|
|
update_transform(TRUE)
|