mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-05-17 20:30:46 +01:00
a64992c509
* antag subsystem * antag subsystem
257 lines
11 KiB
Plaintext
257 lines
11 KiB
Plaintext
GLOBAL_LIST_EMPTY(active_autoresleevers)
|
|
|
|
/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/Initialize(mapload)
|
|
. = ..()
|
|
GLOB.active_autoresleevers += src
|
|
|
|
/obj/machinery/transhuman/autoresleever/Destroy()
|
|
. = ..()
|
|
GLOB.active_autoresleevers -= src
|
|
|
|
/obj/machinery/transhuman/autoresleever/update_icon()
|
|
. = ..()
|
|
if(stat & (BROKEN | MAINT | EMPED))
|
|
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 & (BROKEN | MAINT | EMPED)) // Let it still work when power is just off, it has it's own backup reserve or something.
|
|
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)
|
|
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?.read_preference(/datum/preference/choiced/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
|
|
|
|
/* // Comments out NO_SLEEVE restriction, as per headmin/maintainer request.
|
|
var/datum/species/chosen_species
|
|
var/pref_species = ghost.client.prefs.read_preference(/datum/preference/choiced/species)
|
|
if(pref_species) // In case we somehow don't have a species set here.
|
|
chosen_species = GLOB.all_species[pref_species]
|
|
|
|
if(chosen_species.flags & NO_SLEEVE) // Sanity. Prevents species like Xenochimera, Proteans, etc from rejoining the round via resleeve, as they should have their own methods of doing so already, as agreed to when you whitelist as them.
|
|
to_chat(ghost, span_warning("This species cannot be resleeved!"))
|
|
return
|
|
*/
|
|
|
|
//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.read_preference(/datum/preference/name/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")
|
|
if(respawn >= world.time - ghost.timeofdeath) //We were given the option to resleeve due to an outside event, but closed the input box (be it by typing or otherwise) so we allow clicking the autosleever to revive.
|
|
ghost.timeofdeath = world.time - respawn
|
|
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.sync_addictions() // These are addicitions our profile wants... May as well give them!
|
|
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 = SSantag_job.get_antag_data(new_character.mind.special_role)
|
|
if(antag_data)
|
|
antag_data.add_antagonist(new_character.mind)
|
|
antag_data.place_mob(new_character)
|
|
if(new_character.mind.antag_holder)
|
|
new_character.mind.antag_holder.apply_antags(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
|
|
|
|
SEND_SIGNAL(new_character, COMSIG_HUMAN_DNA_FINALIZED)
|
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESLEEVED_MIND, new_character, new_character.mind)
|
|
|
|
//If desired, apply equipment.
|
|
if(equip_body)
|
|
if(charjob)
|
|
GLOB.job_master.EquipRank(new_character, charjob, 1)
|
|
new_character.mind.assigned_role = charjob
|
|
new_character.mind.role_alt_title = GLOB.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)
|
|
GLOB.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
|