var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob //SleeveMate! /obj/item/sleevemate name = "\improper SleeveMate 3700" desc = "A hand-held sleeve management tool for performing one-time backups and managing mindstates." icon = 'icons/obj/device_alt.dmi' icon_state = "sleevemate" item_state = "healthanalyzer" slot_flags = SLOT_BELT throwforce = 3 w_class = ITEMSIZE_SMALL throw_speed = 5 throw_range = 10 matter = list(MAT_STEEL = 200) origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) var/datum/mind/stored_mind var/ooc_notes = null //For holding prefs var/ooc_notes_favs = null var/ooc_notes_likes = null var/ooc_notes_maybes = null var/ooc_notes_dislikes = null var/ooc_notes_style = FALSE // Resleeving database this machine interacts with. Blank for default database // Needs a matching /datum/transcore_db with key defined in code var/db_key var/datum/transcore_db/our_db // These persist all round and are never destroyed, just keep a hard ref pickup_sound = 'sound/items/pickup/device.ogg' drop_sound = 'sound/items/drop/device.ogg' /obj/item/sleevemate/Initialize(mapload) . = ..() our_db = SStranscore.db_by_key(db_key) //These don't perform any checks and need to be wrapped by checks /obj/item/sleevemate/proc/clear_mind() stored_mind = null ooc_notes = null ooc_notes_likes = null ooc_notes_dislikes = null //CHOMPEdit Start ooc_notes_favs = null ooc_notes_maybes = null ooc_notes_style = FALSE //CHOMPEdit End update_icon() /obj/item/sleevemate/proc/get_mind(mob/living/M) ASSERT(M.mind) ooc_notes = M.ooc_notes ooc_notes_likes = M.ooc_notes_likes ooc_notes_dislikes = M.ooc_notes_dislikes ooc_notes_favs = M.ooc_notes_favs ooc_notes_maybes = M.ooc_notes_maybes ooc_notes_style = M.ooc_notes_style stored_mind = M.mind M.ghostize() stored_mind.current = null update_icon() /obj/item/sleevemate/proc/put_mind(mob/living/M) stored_mind.active = TRUE stored_mind.transfer_to(M) M.ooc_notes = ooc_notes M.ooc_notes_likes = ooc_notes_likes M.ooc_notes_dislikes = ooc_notes_dislikes M.ooc_notes_favs = ooc_notes_favs M.ooc_notes_maybes = ooc_notes_maybes M.ooc_notes_style = ooc_notes_style SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESLEEVED_MIND, M, stored_mind) clear_mind() /obj/item/sleevemate/attack(mob/living/M, mob/living/user) // Gather potential subtargets var/list/choices = list(M) if(istype(M)) for(var/obj/belly/B as anything in M.vore_organs) for(var/mob/living/carbon/human/H in B) // I do want an istype choices += H // Subtargets if(choices.len > 1) var/mob/living/new_M = tgui_input_list(user, "Ambiguous target. Please validate target:", "Target Validation", choices, M) if(!new_M || !M.Adjacent(user)) return M = new_M if(isrobot(M)) var/mob/living/silicon/robot/R = M var/obj/item/dogborg/sleeper/S = locate() in R.module.modules if(S && S.patient) scan_mob(S.patient, user) return if(ishuman(M)) scan_mob(M, user) else to_chat(user,span_warning("Not a compatible subject to work with!")) /obj/item/sleevemate/attack_self(mob/living/user) if(!stored_mind) to_chat(user,span_warning("No stored mind in \the [src].")) return var/choice = tgui_alert(user,"What would you like to do?","Stored: [stored_mind.name]",list("Delete","Backup","Cancel")) if(!stored_mind || user.get_active_hand() != src) return switch(choice) if("Delete") to_chat(user,span_notice("Internal copy of [stored_mind.name] deleted.")) clear_mind() if("Backup") to_chat(user,span_notice("Internal copy of [stored_mind.name] backed up to database.")) our_db.m_backup(stored_mind,null,one_time = TRUE) if("Cancel") return /obj/item/sleevemate/proc/scan_mob(mob/living/carbon/human/H, mob/living/user) var/output = "" output += "

" + span_boldnotice("[src.name] Scan Results") + "
" //Mind name output += span_bold("Sleeved Mind:") + " " if(H.mind) output += "[H.mind.name]
" else output += span_warning("Unknown/None") + "
" //Mind status output += span_bold("Mind Status:") + " " if(H.client) output += "Healthy
" else output += "Space Sleep Disorder
" //Body status output += span_bold("Sleeve Status:") + " " switch(H.stat) if(CONSCIOUS) output += "Alive
" if(UNCONSCIOUS) output += "Unconscious
" if(DEAD) output += span_warning("Deceased") + "
" else output += span_warning("Unknown") + "
" //Mind/body comparison output += span_bold("Sleeve Pair:") if(!H.ckey) output += span_warning("No mind in that body") + " [stored_mind != null ? "\[Upload\]" : null]
" else if(H.mind && ckey(H.mind.key) != H.ckey) output += span_warning("May not be correct body") + "
" else if(H.mind && ckey(H.mind.key) == H.ckey) output += "Appears to be correct mind in body
" else output += "Unable to perform comparison
" //Actions output += "
-- Possible Actions --
" output += span_bold("Mind-Scan (One Time): ") + "\[Perform\]
" output += span_bold("Body-Scan (One Time): ") + "\[Perform\]
" //Saving a mind output += span_bold("Store Full Mind:") + " " if(stored_mind) output += span_notice("Already Stored") + " ([stored_mind.name])
" else if(H.mind) output += "\[Perform\]
" else output += span_warning("Unable") + "
" //Soulcatcher transfer if(H.nif) var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER) if(SC) output += "
" output += span_bold("Soulcatcher detected ([SC.brainmobs.len] minds)") + "
" for(var/mob/living/carbon/brain/caught_soul/mind in SC.brainmobs) output += "[mind.name]: [mind.transient == FALSE ? "\[Load\]" : span_warning("Incompatible")]
" if(stored_mind) output += span_bold("Store in Soulcatcher: ") + "\[Perform\]
" to_chat(user,output) /obj/item/sleevemate/Topic(href, href_list) usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //Sanity checking/href-hacking checking if(usr.get_active_hand() != src) to_chat(usr,span_warning("You're not holding \the [src].")) return var/target_ref = href_list["target"] var/mob/living/target = locate(target_ref) in GLOB.mob_list if(!target) to_chat(usr,span_warning("Unable to operate on that target.")) return if(!usr.Adjacent(target)) to_chat(usr,span_warning("You are too far from that target.")) return //The actual options if(href_list["mindscan"]) if(!target.mind || (target.mind.name in GLOB.prevent_respawns)) to_chat(usr,span_warning("Target seems totally braindead.")) return var/nif if(ishuman(target)) var/mob/living/carbon/human/H = target nif = H.nif persist_nif_data(H) usr.visible_message("[usr] begins scanning [target]'s mind.",span_notice("You begin scanning [target]'s mind.")) if(do_after(usr, 8 SECONDS, target)) our_db.m_backup(target.mind,nif,one_time = TRUE) to_chat(usr,span_notice("Mind backed up!")) else to_chat(usr,span_warning("You must remain close to your target!")) return if(href_list["bodyscan"]) if(!ishuman(target)) to_chat(usr,span_warning("Target is not of an acceeptable body type.")) return var/mob/living/carbon/human/H = target usr.visible_message("[usr] begins scanning [target]'s body.",span_notice("You begin scanning [target]'s body.")) if(do_after(usr, 8 SECONDS, target)) var/datum/transhuman/body_record/BR = new() BR.init_from_mob(H, TRUE, TRUE, database_key = db_key) to_chat(usr,span_notice("Body scanned!")) else to_chat(usr,span_warning("You must remain close to your target!")) return if(href_list["mindsteal"]) if(!target.mind || (target.mind.name in GLOB.prevent_respawns)) to_chat(usr,span_warning("Target seems totally braindead.")) return if(stored_mind) to_chat(usr,span_warning("There is already someone's mind stored inside")) return var/choice = tgui_alert(usr,"This will remove the target's mind from their body (and from the game as long as they're in the sleevemate). You can put them into a (mindless) body, a NIF, or back them up for normal resleeving, but you should probably have a plan in advance so you don't leave them unable to interact for too long. Continue?","Confirmation",list("Continue","Cancel")) if(choice == "Continue" && usr.get_active_hand() == src && usr.Adjacent(target)) usr.visible_message(span_warning("[usr] begins downloading [target]'s mind!"),span_notice("You begin downloading [target]'s mind!")) if(do_after(usr, 35 SECONDS, target)) //This is powerful, yo. if(!stored_mind && target.mind) get_mind(target) to_chat(usr,span_notice("Mind downloaded!")) return if(href_list["mindput"]) if(!stored_mind) to_chat(usr,span_warning("\The [src] no longer has a stored mind.")) return var/mob/living/carbon/human/H = target if(!istype(target)) return //href hacking only if(!H.nif) return //Lost it? or href hacking var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER) if(!SC) return //Uninstalled it? //Lazzzyyy. if(!sleevemate_mob) sleevemate_mob = new() put_mind(sleevemate_mob) SC.catch_mob(sleevemate_mob) to_chat(usr,span_notice("Mind transferred into Soulcatcher!")) if(href_list["mindupload"]) if(!stored_mind) to_chat(usr,span_warning("\The [src] no longer has a stored mind.")) return if(!istype(target)) return if(ishuman(target)) var/mob/living/carbon/human/H = target if(H.resleeve_lock && stored_mind.loaded_from_ckey != H.resleeve_lock) to_chat(usr,span_warning("\The [H] is protected from impersonation!")) return //Changeling bodies. Only changelings can be put in them. if(H.changeling_locked && !is_changeling(stored_mind)) to_chat(usr,span_warning("\The [H] is too complex to put this mind into!")) return usr.visible_message(span_warning("[usr] begins uploading someone's mind into [target]!"),span_notice("You begin uploading a mind into [target]!")) if(do_after(usr, 35 SECONDS, target)) if(!stored_mind) to_chat(usr,span_warning("\The [src] no longer has a stored mind.")) return put_mind(target) to_chat(usr,span_notice("Mind transferred into [target]!")) if(href_list["mindrelease"]) if(stored_mind) to_chat(usr,span_warning("There is already someone's mind stored inside")) return var/mob/living/carbon/human/H = target var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER) if(!SC) return for(var/mob/living/carbon/brain/caught_soul/soul in SC.brainmobs) if(soul.name == href_list["mindrelease"]) get_mind(soul) qdel(soul) to_chat(usr,span_notice("Mind downloaded!")) return to_chat(usr,span_notice("Unable to find that mind in Soulcatcher!")) /obj/item/sleevemate/update_icon() if(stored_mind) icon_state = "[initial(icon_state)]_on" else icon_state = initial(icon_state) /obj/item/sleevemate/emag_act(var/remaining_charges, var/mob/user) //CHOMPEdit Start var/list/choices = list("Body Snatcher","Mind Binder") var/choice = tgui_input_list(user, "How would you like to modify the [src]?", "", choices) if(!choice || !(choice in choices)) return //CHOMPEdit End to_chat(user,span_danger("You hack [src]!")) var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() spark_system.set_up(5, 0, src.loc) spark_system.start() playsound(src, "sparks", 50, 1) if(isliving(src.loc)) var/mob/living/L = src.loc L.unEquip(src) src.forceMove(get_turf(src)) //CHOMPEdit Start if(choice == "Body Snatcher") new /obj/item/bodysnatcher(src.loc) if(choice == "Mind Binder") new /obj/item/mindbinder(src.loc) //CHOMPEdit End qdel(src) return 1