Files
CHOMPStation2/code/modules/resleeving/autoresleever.dm
2025-03-11 22:36:14 +01:00

237 lines
9.7 KiB
Plaintext

/obj/machinery/transhuman/autoresleever
name = "automatic resleever"
desc = "Uses advanced technology to detect when someone needs to be resleeved, and automatically prints and sleeves them into a new body. It even generates its own biomass!"
icon = 'icons/obj/machines/autoresleever.dmi'
icon_state = "autoresleever"
density = TRUE
anchored = TRUE
var/equip_body = FALSE //If true, this will spawn the person with equipment
var/default_job = JOB_ALT_VISITOR //The job that will be assigned if equip_body is true and the ghost doesn't have a job
var/ghost_spawns = FALSE //If true, allows ghosts who haven't been spawned yet to spawn
var/vore_respawn = 5 MINUTES //The time to wait if you died from vore
var/respawn = 30 MINUTES //The time to wait if you didn't die from vore
var/spawn_slots = -1 //How many people can be spawned from this? If -1 it's unlimited
var/spawntype //The kind of mob that will be spawned, if set.
/obj/machinery/transhuman/autoresleever/update_icon()
. = ..()
if(stat)
icon_state = "autoresleever-o"
else
icon_state = "autoresleever"
/obj/machinery/transhuman/autoresleever/power_change()
. = ..()
update_icon()
/obj/machinery/transhuman/autoresleever/attack_ghost(mob/observer/dead/user as mob)
update_icon()
if(spawn_slots == 0)
to_chat(user, span_warning("There are no more respawn slots."))
return
if(user.mind)
if(user.mind.vore_death)
if(vore_respawn <= world.time - user.timeofdeath)
autoresleeve(user)
else
to_chat(user, span_warning("You must wait [((vore_respawn - (world.time - user.timeofdeath)) * 0.1) / 60] minutes to use \the [src]."))
return
else if(respawn <= world.time - user.timeofdeath)
autoresleeve(user)
else
to_chat(user, span_warning("You must wait [((respawn - (world.time - user.timeofdeath)) * 0.1) /60] minutes to use \the [src]."))
return
else if(spawntype)
if(tgui_alert(user, "This [src] spawns something special, would you like to play as it?", "Creachur", list("No","Yes")) == "Yes")
autoresleeve(user)
else if(ghost_spawns)
if(tgui_alert(user, "Would you like to be spawned here as your presently loaded character?", "Spawn here", list("No","Yes")) == "Yes")
autoresleeve(user)
else
to_chat(user, span_warning("You need to have been spawned in order to respawn here."))
/obj/machinery/transhuman/autoresleever/attackby(var/mob/user) //Let's not let people mess with this.
update_icon()
if(isobserver(user))
attack_ghost(user)
else
return
/obj/machinery/transhuman/autoresleever/proc/autoresleeve(var/mob/observer/dead/ghost)
if(stat)
to_chat(ghost, span_warning("This machine is not functioning..."))
return
if(!isobserver(ghost))
return
if(ghost.mind && ghost.mind.current && ghost.mind.current.stat != DEAD && ghost.mind.current.enabled == TRUE) //CHOMPEdit - Disabled body shouldn't block this.
if(istype(ghost.mind.current.loc, /obj/item/mmi))
if(tgui_alert(ghost, "Your brain is still alive, using the auto-resleever will delete that brain. Are you sure?", "Delete Brain", list("No","Yes")) != "Yes")
return
if(istype(ghost.mind.current.loc, /obj/item/mmi))
qdel(ghost.mind.current.loc)
else
to_chat(ghost, span_warning("Your body is still alive, you cannot be resleeved."))
return
var/client/ghost_client = ghost.client
if(!is_alien_whitelisted(ghost.client, GLOB.all_species[ghost_client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) // Prevents a ghost ghosting in on a slot and spawning via a resleever with race they're not whitelisted for, getting around normal join restrictions.
to_chat(ghost, span_warning("You are not whitelisted to spawn as this species!"))
return
// CHOMPedit start
var/datum/species/chosen_species
if(ghost.client.prefs.species) // In case we somehow don't have a species set here.
chosen_species = GLOB.all_species[ghost_client.prefs.species]
if((chosen_species.spawn_flags & SPECIES_IS_WHITELISTED) || (chosen_species.spawn_flags & SPECIES_IS_RESTRICTED))
to_chat(ghost, span_warning("This species cannot be resleeved!"))
return
// CHOMPEdit End: Add checks for Whitelist + Resleeving
//Name matching is ugly but mind doesn't persist to look at.
var/charjob
var/datum/data/record/record_found
record_found = find_general_record("name",ghost_client.prefs.real_name)
//Found their record, they were spawned previously
if(record_found)
charjob = record_found.fields["real_rank"]
else if(equip_body || ghost_spawns)
charjob = default_job
else
to_chat(ghost, span_warning("It appears as though your loaded character has not been spawned this round, or has quit the round. If you died as a different character, please load them, and try again."))
return
//For logging later
var/player_key = ghost_client.key
var/picked_ckey = ghost_client.ckey
var/picked_slot = ghost_client.prefs.default_slot
var/spawnloc = get_turf(src)
//Did we actually get a loc to spawn them?
if(!spawnloc)
to_chat(ghost, span_warning("Could not find a valid location to spawn your character."))
return
if(spawntype)
var/spawnthing = new spawntype(spawnloc)
if(isliving(spawnthing))
var/mob/living/L = spawnthing
L.key = player_key
L.ckey = picked_ckey
log_admin("[L.ckey]'s has been spawned as [L] via \the [src].")
message_admins("[L.ckey]'s has been spawned as [L] via \the [src].")
else
to_chat(ghost, span_warning("You can't play as a [spawnthing]..."))
return
if(spawn_slots == -1)
return
else if(spawn_slots == 0)
return
else
spawn_slots --
return
var/slot = ghost.client.prefs.default_slot
if(tgui_alert(ghost, "Would you like to be resleeved?", "Resleeve", list("No","Yes")) != "Yes")
return
//This keeps people from dying in round, clicking the autoresleever, then swapping savefiles and clicking 'yes'
if(slot != ghost.client.prefs.default_slot && (!equip_body || !ghost_spawns))
var/turf/T = get_turf(src)
to_chat(ghost, span_warning("It appears as though your loaded character has not been spawned this round, or has quit the round. If you died as a different character, please load them, and try again."))
message_admins("[key_name_admin(ghost)] swapped savefiles while using the autosleever and tried to spawn as another character! [ADMIN_JMP(T)]")
return
var/mob/living/carbon/human/new_character
new_character = new(spawnloc)
//We were able to spawn them, right?
if(!new_character)
to_chat(ghost, "Something went wrong and spawning failed.")
return
//Write the appearance and whatnot out to the character
ghost_client.prefs.copy_to(new_character)
if(new_character.dna)
new_character.dna.ResetUIFrom(new_character)
new_character.sync_dna_traits(TRUE) // Traitgenes Sync traits to genetics if needed
new_character.sync_organ_dna()
new_character.initialize_vessel()
if(ghost.mind)
ghost.mind.transfer_to(new_character)
new_character.key = player_key
//Were they any particular special role? If so, copy.
if(new_character.mind)
new_character.mind.loaded_from_ckey = picked_ckey
new_character.mind.loaded_from_slot = picked_slot
var/datum/antagonist/antag_data = get_antag_data(new_character.mind.special_role)
if(antag_data)
antag_data.add_antagonist(new_character.mind)
antag_data.place_mob(new_character)
for(var/lang in ghost_client.prefs.alternate_languages)
var/datum/language/chosen_language = GLOB.all_languages[lang]
if(chosen_language)
if(is_lang_whitelisted(ghost,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
new_character.add_language(lang)
for(var/key in ghost_client.prefs.language_custom_keys)
if(ghost_client.prefs.language_custom_keys[key])
var/datum/language/keylang = GLOB.all_languages[ghost_client.prefs.language_custom_keys[key]]
if(keylang)
new_character.language_keys[key] = keylang
if(ghost_client.prefs.preferred_language) // Do we have a preferred language?
var/datum/language/def_lang = GLOB.all_languages[ghost_client.prefs.preferred_language]
if(def_lang)
new_character.default_language = def_lang
//If desired, apply equipment.
if(equip_body)
if(charjob)
job_master.EquipRank(new_character, charjob, 1)
new_character.mind.assigned_role = charjob
new_character.mind.role_alt_title = job_master.GetPlayerAltTitle(new_character, charjob)
//A redraw for good measure
new_character.regenerate_icons()
new_character.update_transform()
log_admin("[new_character.ckey]'s character [new_character.real_name] has been auto-resleeved.")
message_admins("[new_character.ckey]'s character [new_character.real_name] has been auto-resleeved.")
var/obj/item/implant/backup/imp = new(src)
if(imp.handle_implant(new_character,new_character.zone_sel.selecting))
imp.post_implant(new_character)
var/datum/transcore_db/db = SStranscore.db_by_mind_name(new_character.mind.name)
if(db)
var/datum/transhuman/mind_record/record = db.backed_up[new_character.mind.name]
if((world.time - record.last_notification) < 30 MINUTES)
global_announcer.autosay("[new_character.name] has been resleeved by the automatic resleeving system.", "TransCore Oversight", new_character.isSynthetic() ? "Science" : "Medical")
spawn(0) //Wait a second for nif to do its thing if there is one
if(record.nif_path)
var/obj/item/nif/nif
if(new_character.nif)
nif = new_character.nif
else
nif = new record.nif_path(new_character,null,record.nif_savedata)
spawn(0) //Wait another second in case we just gave them a new nif
if(nif) //Now restore the software
for(var/path in record.nif_software)
new path(nif)
nif.durability = record.nif_durability
if(!new_character.dna)
CRASH("[new_character] just came out of an autosleever and has no DNA! Species: [new_character.species] as mob: [new_character.type]. NIF Status: [new_character.nif]")
if(spawn_slots == -1)
return
else if(spawn_slots == 0)
return
else
spawn_slots --
return