From b5c67d1fbf08d64c2f9ed0a273f13dec6151174d Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Tue, 14 Mar 2023 23:03:16 -0500 Subject: [PATCH] Paradox clones spawns with "copies" of their target's memories (#73988) ## About The Pull Request Paradox clones spawn with a "quick copy" of their target's memories. These are notably limited in that they can't be used for stories (engraving or tattoos), but if people metagame Paradox clones by saying "engrave something for me" there's no hope for this community Closes #73931 ## Why It's Good For The Game Stops a meta-y exploit ## Changelog :cl: Melbert fix: Paradox Clones now know that their target knows. /:cl: --- code/__HELPERS/memory_helpers.dm | 8 ++++++ code/datums/elements/wall_engraver.dm | 2 +- code/datums/memory/_memory.dm | 28 ++++++++++++++++++- code/datums/memory/tattoo_kit.dm | 2 +- .../paradox_clone/paradox_clone.dm | 4 +++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/code/__HELPERS/memory_helpers.dm b/code/__HELPERS/memory_helpers.dm index e1e9212cef2..bc916b2d20f 100644 --- a/code/__HELPERS/memory_helpers.dm +++ b/code/__HELPERS/memory_helpers.dm @@ -112,3 +112,11 @@ /// Small helper to clean out memories. /datum/mind/proc/wipe_memory() QDEL_LIST_ASSOC_VAL(memories) + +/// Helper to create quick copies of all of our memories +/// Quick copies aren't full copies - just basic copies containing necessities. +/// They cannot be used in stories. +/datum/mind/proc/quick_copy_all_memories(datum/mind/new_memorizer) + for(var/memory_path in memories) + var/datum/memory/prime_memory = memories[memory_path] + new_memorizer.memories[memory_path] = prime_memory.quick_copy_memory(new_memorizer) diff --git a/code/datums/elements/wall_engraver.dm b/code/datums/elements/wall_engraver.dm index 4a82eabbf82..72e74c7d35c 100644 --- a/code/datums/elements/wall_engraver.dm +++ b/code/datums/elements/wall_engraver.dm @@ -37,7 +37,7 @@ if(HAS_TRAIT_FROM(wall, TRAIT_NOT_ENGRAVABLE, TRAIT_GENERIC)) user.balloon_alert(user, "wall has already been engraved!") return - if(!user.mind?.memories?.len) + if(!length(user.mind?.memories)) user.balloon_alert(user, "nothing memorable to engrave!") return var/datum/memory/memory_to_engrave = user.mind.select_memory("engrave") diff --git a/code/datums/memory/_memory.dm b/code/datums/memory/_memory.dm index f6f51888fba..98dbea10170 100644 --- a/code/datums/memory/_memory.dm +++ b/code/datums/memory/_memory.dm @@ -57,7 +57,7 @@ src.deuteragonist_name = build_story_character(deuteragonist) src.antagonist_name = build_story_character(antagonist) - if(protagonist && !(memory_flags & MEMORY_FLAG_NOLOCATION)) + if(!src.where && isatom(protagonist) && !(memory_flags & MEMORY_FLAG_NOLOCATION)) src.where = get_area_name(protagonist) if(!(memory_flags & MEMORY_FLAG_NOMOOD)) @@ -380,3 +380,29 @@ // Generic result - mobs get "the guy", objs / turfs get "a thing" return ismob(character) ? "\the [character]" : "\a [character]" + +/** + * Creates a "quick copy" of the memory for another mind, + * copying just basic memory information (name, major charactecrs) over. + * + * The copied memory cannot be used for stories or anything. + * They should generally only be used to give a new mind an idea of another mind's memories. + */ +/datum/memory/proc/quick_copy_memory(datum/mind/new_memorizer) + var/datum/memory/copy/new_copy = new(new_memorizer, protagonist_name, deuteragonist_name, antagonist_name, where, memory_flags) + new_copy.name = name + new_copy.story_value = story_value + return new_copy + +// To only be used by quick copies of memories +/datum/memory/copy + memory_flags = MEMORY_NO_STORY + +/datum/memory/copy/New(datum/mind/memorizer_mind, atom/protagonist, atom/deuteragonist, atom/antagonist, where, new_memory_flags) + src.where = where + src.memory_flags |= new_memory_flags + return ..() + +/datum/memory/copy/generate_memory_name() + // We just copy the original memory's name anyways + return diff --git a/code/datums/memory/tattoo_kit.dm b/code/datums/memory/tattoo_kit.dm index 93859571af4..98d47eaa285 100644 --- a/code/datums/memory/tattoo_kit.dm +++ b/code/datums/memory/tattoo_kit.dm @@ -38,7 +38,7 @@ if(!uses) balloon_alert(tattoo_artist, "not enough ink!") return - if(!tattoo_artist.mind.memories) + if(!length(tattoo_artist.mind.memories)) balloon_alert(tattoo_artist, "nothing memorable to engrave!") return var/selected_zone = tattoo_artist.zone_selected diff --git a/code/modules/antagonists/paradox_clone/paradox_clone.dm b/code/modules/antagonists/paradox_clone/paradox_clone.dm index 012d13902b5..feff552e1b2 100644 --- a/code/modules/antagonists/paradox_clone/paradox_clone.dm +++ b/code/modules/antagonists/paradox_clone/paradox_clone.dm @@ -73,6 +73,10 @@ sensor_clothes.sensor_mode = SENSOR_OFF clone_human.update_suit_sensors() + // Perform a quick copy of existing memories. + // This may result in some minutely imperfect memories, but it'll do + original_mind.quick_copy_all_memories(owner) + /datum/antagonist/paradox_clone/roundend_report_header() return "A paradox clone appeared on the station!
"