From 0ba2d3c171d1ae16af11443ebf2be7529b5e7eaf Mon Sep 17 00:00:00 2001 From: "natakilar@gmail.com" Date: Fri, 17 Mar 2023 19:04:54 -0400 Subject: [PATCH] Cloning fixes --- .../subsystems/initialization/chargen.dm | 4 + .../cloning/device_types/cloning_pod.dm | 26 ++- mods/persistence/modules/mob/death.dm | 3 +- mods/persistence/modules/mob/living/living.dm | 11 ++ .../persistence/modules/mob/observer/limbo.dm | 27 +++- .../file_system/programs/cloning.dm | 112 +++++++------ .../modules/organs/internal/stack.dm | 14 +- .../world_save/saved_vars/saved_misc.dm | 9 -- nano/templates/cloning_program.tmpl | 148 +++++++++--------- 9 files changed, 186 insertions(+), 168 deletions(-) diff --git a/mods/persistence/controllers/subsystems/initialization/chargen.dm b/mods/persistence/controllers/subsystems/initialization/chargen.dm index e2a36e0fe24..37a2eb29b83 100644 --- a/mods/persistence/controllers/subsystems/initialization/chargen.dm +++ b/mods/persistence/controllers/subsystems/initialization/chargen.dm @@ -8,6 +8,8 @@ SUBSYSTEM_DEF(chargen) flags = SS_NO_FIRE var/map_z // What z-level is being used for the pods. + var/obj/abstract/limbo_holder + /datum/controller/subsystem/chargen/Initialize() INCREMENT_WORLD_Z_SIZE map_z = world.maxz @@ -31,6 +33,8 @@ SUBSYSTEM_DEF(chargen) maploader.load_map(file("maps/chargen/chargen.dmm"), ((x - 1) * width) + 1, ((y - 1) * height) + 1, map_z, no_changeturf = TRUE) CHECK_TICK + limbo_holder = new(locate(world.maxx / 2, world.maxy / 2, map_z)) + /datum/controller/subsystem/chargen/proc/assign_spawn_pod(var/area/chargen/pod) chargen_areas[pod] += 1 diff --git a/mods/persistence/modules/cloning/device_types/cloning_pod.dm b/mods/persistence/modules/cloning/device_types/cloning_pod.dm index 0610befe83c..7e79ad0a7d9 100644 --- a/mods/persistence/modules/cloning/device_types/cloning_pod.dm +++ b/mods/persistence/modules/cloning/device_types/cloning_pod.dm @@ -5,11 +5,11 @@ var/occupied = FALSE var/scanning = FALSE var/cloning = FALSE - var/cloning_progress = 0 // Used to display messages to whoever is being clone while they're in the vat. + var/cloning_progress = 0 // Used to display messages to whoever is being clone while they're in the vat. var/task_started_on var/current_task // Timer ID of task - var/datum/file_transfer/scan + var/datum/computer_file/data/cloning/finished_scan // Checks if this is a valid place for a mob to use as a cloning respawn point. /datum/extension/network_device/cloning_pod/proc/is_valid_respawn(var/mind_id) @@ -46,15 +46,16 @@ new_character.sync_organ_dna() new_character.add_language(/decl/language/human/common) new_character.default_language = /decl/language/human/common + mind.transfer_to(new_character) // The body forms 'around' the stack, so reinstall it. if(stack) var/obj/item/organ/O = new_character.get_organ(stack.parent_organ) new_character.add_organ(stack, O) + qdel(stack.stackmob) else mind.philotic_damage += 10 - mind.transfer_to(new_character) // TODO: More feedback on philotic damage in general. if(mind.philotic_damage > 75) to_chat(new_character, SPAN_WARNING("Colors seem to lack the vibrance they used to have. It would be easy to just go to sleep and never wake up.")) @@ -99,7 +100,7 @@ return cloning_progress += 1 -/datum/extension/network_device/cloning_pod/proc/begin_scan(var/mob/caller, var/filesource) +/datum/extension/network_device/cloning_pod/proc/begin_scan(var/mob/caller) if(!check_scan()) return cancel_task() // Delete any in progress timers just in case. @@ -109,24 +110,17 @@ scanning = TRUE task_started_on = world.time - var/datum/computer_file/data/cloning/cloneFile = new() - cloneFile.initialize_backup(occupant) - scan = new(null, filesource, cloneFile) current_task = addtimer(CALLBACK(src, /datum/extension/network_device/cloning_pod/proc/finish_scan), TASK_SCAN_TIME, TIMER_STOPPABLE) to_chat(occupant, SPAN_NOTICE("Lights flash around you as a cortical scan begins.")) /datum/extension/network_device/cloning_pod/proc/finish_scan() + scanning = FALSE var/atom/movable/occupant = get_occupant() if(!occupant) return - scanning = FALSE - if(!scan || !scan.transfer_to) - return - scan.transfer_to.store_file(scan.transferring) - - qdel(scan) - scan = null + finished_scan = new() + finished_scan.initialize_backup(occupant) /datum/extension/network_device/cloning_pod/proc/cancel_task() deltimer(current_task) @@ -134,7 +128,7 @@ cloning = FALSE /datum/extension/network_device/cloning_pod/proc/check_clone() - if(cloning || scanning) + if(cloning || scanning || finished_scan) return FALSE var/atom/movable/occupant = get_occupant() if(!istype(occupant, /obj/item/organ/internal/stack)) @@ -146,7 +140,7 @@ return FALSE /datum/extension/network_device/cloning_pod/proc/check_scan() - if(cloning || scanning) + if(cloning || scanning || finished_scan) return FALSE var/atom/movable/occupant = get_occupant() if(!istype(occupant, /mob/living/carbon)) diff --git a/mods/persistence/modules/mob/death.dm b/mods/persistence/modules/mob/death.dm index 560f8c31e5e..78c595a50f5 100644 --- a/mods/persistence/modules/mob/death.dm +++ b/mods/persistence/modules/mob/death.dm @@ -12,8 +12,7 @@ to_chat(stack.stackmob, SPAN_NOTICE("Darkness envelopes you. Your character has died and you are now in limbo. Resleeve to continue playing as your character, or wait until a kind soul clones you from your cortical stack.")) else hide_fullscreens() - var/mob/living/limbo/brainmob = new(src) - brainmob.forceMove(null) + var/mob/living/limbo/brainmob = new(SSchargen.limbo_holder) brainmob.SetName(real_name) brainmob.real_name = real_name // brainmob.timeofhostdeath = timeofdeath diff --git a/mods/persistence/modules/mob/living/living.dm b/mods/persistence/modules/mob/living/living.dm index a940478cb7d..93b542f5dc6 100644 --- a/mods/persistence/modules/mob/living/living.dm +++ b/mods/persistence/modules/mob/living/living.dm @@ -3,5 +3,16 @@ return . = ..() +/mob/living/switch_from_dead_to_living_mob_list() + . = ..() + if(.) + // If there's a mob in limbo or the player has a stack, restore them to their body. + if(last_ckey) + for(var/mob/living/limbo/limbo in player_list) + if(limbo.mind && limbo.mind.name == real_name && limbo.ckey == last_ckey) + limbo.mind.transfer_to(src) + qdel(limbo) + break + SAVED_VAR(/mob/living, pronoun_gender) SAVED_VAR(/mob/living, pronouns) \ No newline at end of file diff --git a/mods/persistence/modules/mob/observer/limbo.dm b/mods/persistence/modules/mob/observer/limbo.dm index b1e4beb0cfe..9e97b1be188 100644 --- a/mods/persistence/modules/mob/observer/limbo.dm +++ b/mods/persistence/modules/mob/observer/limbo.dm @@ -2,22 +2,41 @@ // still floating around .. somewhere. /mob/living/limbo use_me = 0 + stat = UNCONSCIOUS -/mob/living/limbo/Initialize() - . = ..() + var/obj/item/organ/internal/stack/cortical_stack + +/mob/living/limbo/Initialize(mapload, obj/item/organ/internal/stack/new_stack) + ..() verbs |= /mob/proc/resleeve verbs |= /mob/proc/death_give_up + if(new_stack) + cortical_stack = new_stack + var/datum/action/resleeve/resleeve_act = new(src) resleeve_act.Grant(src) var/datum/action/death_give_up/give_up_act = new(src) give_up_act.Grant(src) + return INITIALIZE_HINT_LATELOAD + +/mob/living/limbo/LateInitialize() + if(cortical_stack) + if(loc != cortical_stack) + forceMove(cortical_stack) + else if(loc != SSchargen.limbo_holder) + forceMove(SSchargen.limbo_holder) + . = ..() + /mob/living/limbo/Destroy() for(var/datum/action/death_action in actions) death_action.SetTarget(null) qdel(death_action) + + cortical_stack?.stackmob = null + cortical_stack = null . = ..() // Do not call parent, as we do not want the area text to appear. @@ -42,4 +61,6 @@ procname = "death_give_up" action_type = AB_GENERIC button_icon = 'mods/persistence/icons/obj/action_buttons/actions.dmi' - button_icon_state = "give_up" \ No newline at end of file + button_icon_state = "give_up" + +SAVED_VAR(/mob/living/limbo, cortical_stack) \ No newline at end of file diff --git a/mods/persistence/modules/modular_computers/file_system/programs/cloning.dm b/mods/persistence/modules/modular_computers/file_system/programs/cloning.dm index f80b5c52cf5..13f7c194b88 100644 --- a/mods/persistence/modules/modular_computers/file_system/programs/cloning.dm +++ b/mods/persistence/modules/modular_computers/file_system/programs/cloning.dm @@ -12,16 +12,56 @@ size = 12 nanomodule_path = /datum/nano_module/program/cloning - var/error - var/datum/file_storage/network/current_filesource = /datum/file_storage/network - -/datum/computer_file/program/cloning/on_startup(var/mob/living/user, var/datum/extension/interactive/os/new_host) +/datum/computer_file/program/cloning/on_file_select(datum/file_storage/disk, datum/computer_file/directory/dir, datum/computer_file/selected, selecting_key, mob/user) + // We pass the weakref instead of the network tag for safety reasons. + var/weakref/CP_ref = selecting_key + if(istype(CP_ref)) + var/datum/extension/network_device/cloning_pod/CP = CP_ref.resolve() + if(istype(CP)) + CP.finished_scan = null . = ..() - current_filesource = new(new_host) -/datum/computer_file/program/cloning/on_shutdown() +/datum/computer_file/program/cloning/Topic(href, href_list) . = ..() - qdel(current_filesource) + if(.) + return + + var/mob/user = usr + var/datum/computer_network/network = computer.get_network() + if(!network) + return + + if(href_list["backup"]) + var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) + if(!istype(CP)) + return TOPIC_REFRESH + CP.begin_scan(user) + return TOPIC_REFRESH + + if(href_list["save"]) + var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) + if(!istype(CP)) + return TOPIC_REFRESH + + if(!CP.finished_scan) + return TOPIC_REFRESH + var/browser_desc = "Save cloning scan as:" + view_file_browser(user, weakref(CP), /datum/computer_file/data/cloning, OS_WRITE_ACCESS, browser_desc, CP.finished_scan) + return TOPIC_HANDLED + + if(href_list["clone"]) + var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) + if(!istype(CP)) + return TOPIC_REFRESH + CP.begin_clone(user) + return TOPIC_REFRESH + + if(href_list["eject"]) + var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) + if(!istype(CP)) + return TOPIC_REFRESH + CP.eject_occupant(user) + return TOPIC_REFRESH /datum/nano_module/program/cloning name = "Organic Backup System" @@ -29,17 +69,8 @@ /datum/nano_module/program/cloning/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nanoui/master_ui, datum/topic_state/state) var/list/data = host.initial_data() var/datum/computer_file/program/cloning/PRG = program - if(PRG.error) - data["error"] = PRG.error - var/datum/computer_network/network = PRG.computer.get_network() - if(!PRG.error && network) - data["fileserver"] = PRG.current_filesource.server - var/datum/extension/network_device/mainframe/MF = PRG.current_filesource.get_mainframe() - if(MF) - data["used_space"] = MF.get_used() - data["total_space"] = MF.get_capacity() - + if(network) var/list/cloning_pods = list() for(var/datum/extension/network_device/cloning_pod/CP in network.devices) var/obj/machinery/machine = CP.holder @@ -51,13 +82,16 @@ "total_progress" = 1 ) cloning_pod["can_clone"] = CP.check_clone() - cloning_pod["can_backup"] = CP.check_scan() + cloning_pod["can_backup"] = CP.check_scan() + cloning_pod["can_save"] = !!CP.finished_scan if(!cloning_pod["online"]) cloning_pod["status"] = "Offline." else if(CP.occupied) cloning_pod["status"] = "Occupied." - if(CP.scanning || CP.cloning) - cloning_pod["operation"] = CP.scanning ? "Scanning." : "Cloning." + if(CP.finished_scan) + cloning_pod["operation"] = "Scan complete" + else if(CP.scanning || CP.cloning) + cloning_pod["operation"] = CP.scanning ? "Scanning" : "Cloning" cloning_pod["progress"] = (world.time - CP.task_started_on) / (TASK_SCAN_TIME) cloning_pod["remaining"] = round((TASK_SCAN_TIME + CP.task_started_on - world.time) / 10) var/atom/movable/occupant = CP.get_occupant() @@ -84,40 +118,4 @@ ui.auto_update_layout = 1 ui.set_initial_data(data) ui.set_auto_update(1) - ui.open() - -/datum/computer_file/program/cloning/Topic(href, href_list) - . = ..() - if(.) - return - - var/mob/user = usr - if(href_list["refresh"]) - error = null - - var/datum/computer_network/network = computer.get_network() - if(!network) - return - - if(href_list["change_file_server"]) - var/list/file_servers = network.get_file_server_tags(MF_ROLE_CLONING, computer.get_access(user)) - var/file_server = input(usr, "Choose a fileserver to view files on:", "Select File Server") as null|anything in file_servers - if(file_server) - current_filesource.server = file_server - - if(href_list["backup"]) - error = current_filesource.check_errors() - if(error) - return - var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) - CP.begin_scan(user, current_filesource) - - if(href_list["clone"]) - var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) - CP.begin_clone(user) - - if(href_list["eject"]) - var/datum/extension/network_device/cloning_pod/CP = network.get_device_by_tag(href_list["machine"]) - CP.eject_occupant(user) - - return TOPIC_REFRESH \ No newline at end of file + ui.open() \ No newline at end of file diff --git a/mods/persistence/modules/organs/internal/stack.dm b/mods/persistence/modules/organs/internal/stack.dm index 5ba1d300d42..2ef219b1ec1 100644 --- a/mods/persistence/modules/organs/internal/stack.dm +++ b/mods/persistence/modules/organs/internal/stack.dm @@ -2,14 +2,14 @@ var/global/list/cortical_stacks = list() /proc/switchToStack(var/obj/stack_holder, var/datum/mind/mind) // See if we can find the stack in whatever the holder was, usually a person. var/obj/item/organ/internal/stack/target = locate() in stack_holder - if(!target) + if(!target || target.mind_id != mind.unique_id) for(var/obj/item/organ/internal/stack/S in global.cortical_stacks) if(S.mind_id == mind.unique_id) target = S break if(!target) return null - target.stackmob = new(target) + target.stackmob = new(target, target) target.stackmob.SetName(mind.current.real_name) target.stackmob.real_name = mind.current.real_name mind.transfer_to(target.stackmob) @@ -40,7 +40,8 @@ var/global/list/cortical_stacks = list() global.cortical_stacks -= src QDEL_NULL(backup) if(stackmob) - stackmob.forceMove(null) // Move the stackmob to null space to allow it to otherwise resleeve. + stackmob.forceMove(SSchargen.limbo_holder) // Move the stackmob to the limbo holder to allow it to otherwise resleeve. + stackmob.cortical_stack = null stackmob = null . = ..() @@ -126,4 +127,9 @@ var/global/list/cortical_stacks = list() add_language(/decl/language/cortical) stack.verbs |= /obj/item/organ/internal/stack/proc/change_cortical_alias if(!stack.cortical_alias) - stack.cortical_alias = Gibberish(name, 100) \ No newline at end of file + stack.cortical_alias = Gibberish(name, 100) + +SAVED_VAR(/obj/item/organ/internal/stack, stackmob) +SAVED_VAR(/obj/item/organ/internal/stack, backup) +SAVED_VAR(/obj/item/organ/internal/stack, cortical_alias) +SAVED_VAR(/obj/item/organ/internal/stack, mind_id) diff --git a/mods/persistence/modules/world_save/saved_vars/saved_misc.dm b/mods/persistence/modules/world_save/saved_vars/saved_misc.dm index bb2b03a00b4..02ce8e6b798 100644 --- a/mods/persistence/modules/world_save/saved_vars/saved_misc.dm +++ b/mods/persistence/modules/world_save/saved_vars/saved_misc.dm @@ -899,15 +899,6 @@ SAVED_VAR(/obj/item/integrated_circuit/time/delay, delay) SAVED_VAR(/obj/item/integrated_circuit/time/ticker, delay) SAVED_VAR(/obj/item/integrated_circuit/time/ticker, is_running) -/////////////////////////////////////////////////////////////////////////////// -// item/organ -/////////////////////////////////////////////////////////////////////////////// -SAVED_VAR(/obj/item/organ/internal/stack, stackmob) -SAVED_VAR(/obj/item/organ/internal/stack, backup) -SAVED_VAR(/obj/item/organ/internal/stack, cortical_alias) -SAVED_VAR(/obj/item/organ/internal/stack, mind_id) - - /////////////////////////////////////////////////////////////////////////////// //Effects /////////////////////////////////////////////////////////////////////////////// diff --git a/nano/templates/cloning_program.tmpl b/nano/templates/cloning_program.tmpl index 8829e9cff07..dd532802154 100644 --- a/nano/templates/cloning_program.tmpl +++ b/nano/templates/cloning_program.tmpl @@ -1,114 +1,108 @@ -{{if data.error}} -

An error has occured:

- Additional information: {{:data.error}}
- Please try again. If the problem persists contact your system administrator for assistance. - {{:helper.link('Back to menu', null, { 'refresh' : 1 })}} -{{else}} -
-
File Server
- {{:helper.link(data.fileserver, null, { "change_file_server" : 1 }, null)}} - {{if data.total_space}} -
-
Used storage
-
- {{:helper.displayBar(data.used_space, 0, data.total_space, 'average')}} {{:data.used_space}} / {{:data.total_space}} (GQ) -
+{{for data.cloning_pods}} +

{{:value.id}}

+ {{if value.online}} +
+
+ Status
- {{/if}} -
- {{for data.cloning_pods}} -

{{:value.id}}

- {{if value.online}} +
+ {{:value.status}} +
+
+
- Status + Actions
- {{:value.status}} {{if value.can_backup}} + {{:helper.link('Begin backup', null, {'machine': value.id, 'backup': 1})}} + {{:helper.link('Eject', null, {'machine': value.id, 'eject': 1})}} + {{else value.can_save}}
- {{:helper.link('Begin backup.', null, {'machine': value.id, 'backup': 1})}} - {{:helper.link('Eject.', null, {'machine': value.id, 'eject': 1})}} - {{/if}} - {{if value.can_clone}} + {{:helper.link('Save backup', null, {'machine': value.id, 'save': 1})}} + {{:helper.link('Eject', null, {'machine': value.id, 'eject': 1})}} + {{else value.can_clone}}
- {{:helper.link('Begin clone.', null, {'machine': value.id, 'clone': 1})}} - {{:helper.link('Eject.', null, {'machine': value.id, 'eject': 1})}} + {{:helper.link('Begin clone', null, {'machine': value.id, 'clone': 1})}} + {{:helper.link('Eject', null, {'machine': value.id, 'eject': 1})}} + {{else}} + No actions available, please wait. {{/if}}
-
-
- Contents -
-
- {{:value.contents}} -
+
+
+
+ Contents
+
+ {{:value.contents}} +
+
+
+
+ Current operation +
+
+ {{:value.operation}} +
+
+ {{if value.progress}}
- Current operation + Progress
- {{:value.operation}} + {{:helper.displayBar(value.progress, 0, value.total_progress, 'average')}} {{:value.remaining}} seconds remaining
- {{if value.progress}} + {{/if}} + {{if value.detailed}} +
- Progress + Last backup
- {{:helper.displayBar(value.progress, 0, value.total_progress, 'average')}} {{:value.remaining}} seconds remaining + {{:value.last_backup}}
- {{/if}} - {{if value.detailed}} -
-
-
- Last backup -
-
- {{:value.last_backup}} -
-
-
-
- Filename -
-
- {{:value.filename}} -
+
+
+ Filename
-
-
- Backup size -
-
- {{:value.backup_size}} GQ -
+
+ {{:value.filename}}
- {{/if}} - {{else}} -
-
- Error: -
-
- Cloning pod offline. +
+
+ Backup size +
+
+ {{:value.backup_size}} GQ +
{{/if}} - {{empty}} + {{else}}
Error:
- No cloning pods connected. + Cloning pod offline
- {{/for}} -{{/if}} \ No newline at end of file + {{/if}} +{{empty}} +
+
+ Error: +
+
+ No cloning pods connected +
+
+{{/for}} \ No newline at end of file