/singleton/psionic_power/commune name = "Commune" desc = "Psionically commune with the target. Use on an adjacent object to store a mental image for sending. Use in hand with a mental image to warp and add to its description, or clear a warped one." icon_state = "tech_audibledeception" point_cost = 0 ability_flags = PSI_FLAG_FOUNDATIONAL spell_path = /obj/item/spell/commune /obj/item/spell/commune name = "commune" desc = "Déjà-vu." icon_state = "overload" item_icons = null cast_methods = CAST_RANGED|CAST_MELEE|CAST_USE aspect = ASPECT_PSIONIC cooldown = 10 psi_cost = 15 //For shared/remote-examine Communes, similar to Show-Held-Object var/object var/note //desc var/image //chat icon var/warpdesc //Custom text added right after normal note desc var/popup //Remote popups like paper & photos var/obj/item/photo/psiphoto var/savedscribble var/realscribble var/obj/item/paper/psipaper var/savedinfo var/realinfo /obj/item/spell/commune/proc/ShowSavedScribble(mob/target, saved, psi_deaf = FALSE) //Likely a better way, but the trick is quickly swapping real and saved realscribble = "[psiphoto.scribble]" psiphoto.scribble = "[(saved)]" if(psi_deaf && prob(60)) //Psi-deaf targets that do receieve a photo, have it in black & white more than not var/icon/realimg = icon(psiphoto.img) psiphoto.img.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) psiphoto.show(target) psiphoto.img = icon(realimg) to_chat(target, SPAN_ALIEN("...Even the colors are half-formed.")) else if(psi_deaf && prob(60)) //Or with random colors var/icon/realimg = icon(psiphoto.img) psiphoto.img.MapColors(rgb(rand(0,255), rand(0,255), rand(0,255)), rgb(rand(0,255), rand(0, 255), rand(0,255)), rgb(rand(0,255), rand(0,255), rand(0,255)), rgb(rand(0,255), rand(0,255), rand(0,255))) psiphoto.show(target) psiphoto.img = icon(realimg) to_chat(target, SPAN_ALIEN("...Even the colors are off.")) else if(prob(10) && (SSatlas.current_sector.name in list(SECTOR_LEMURIAN_SEA, SECTOR_LEMURIAN_SEA_FAR))) //Lemurian Sea jumpscare! var/icon/realimg = icon(psiphoto.img) psiphoto.img.MapColors(rgb(0,0,0), rgb(0,0,0), rgb(0,0,0), rgb(0,0,0)) target.eye_blind += 20 psiphoto.show(target) psiphoto.img = icon(realimg) to_chat(target, SPAN_ALIEN("An eerie void momentarily blanks your perception.")) sleep(50) target.eye_blind -= 20 else psiphoto.show(target) psiphoto.scribble = "[realscribble]" /obj/item/spell/commune/proc/ShowSavedInfo(var/mob/target, saved) realinfo = "[psipaper.info]" psipaper.info = "[(saved)]" psipaper.show_content(target) psipaper.info = "[realinfo]" /obj/item/spell/commune/proc/TranslateWritten(mob/target, mob/user, can_read = TRUE) //This is just parse_languages() & paperwork reuse var/regex/written_lang_regex = new(@"(\[lang=([#_a-zA-Z0-9\^]{1})])(.*?)(\[\/lang])", "g") while(written_lang_regex.Find(psipaper.info)) var/datum/language/L = GLOB.language_keys[written_lang_regex.group[2]] if(!L || !L.written_style) continue var/content = written_lang_regex.group[3] var/user_understands = user.say_understands(null, L) if(!user_understands) content = L.scramble(content) psipaper.info = replacetext(psipaper.info, written_lang_regex.match, "[L.short && user_understands ? "([L.short]) [content]" : content]") simple_asset_ensure_is_sent(target, /datum/asset/simple/paper) var/datum/browser/paper_win = new(target, "Mental Image", null, 450, 500, null, TRUE) paper_win.set_content("(Mental Image)[can_read ? psipaper.info : stars(psipaper.info)][psipaper.stamps]") paper_win.add_stylesheet("paper_languages", 'html/browser/paper_languages.css') paper_win.open() /obj/item/spell/commune/Destroy() object = null note = null psiphoto = null psipaper = null return ..() /obj/item/spell/commune/on_use_cast(mob/user) . = ..() if(warpdesc) warpdesc = null to_chat(user, SPAN_NOTICE("You rein back to your initial mental image of \the [object], clearing the warped additions.")) else if(warpdesc == null && (object)) warpdesc = tgui_input_text(user, "How would you warp the mental image of \the [object]? This will only add to its existing description, never override or delete.", "Warp Mental Image", "", MAX_MESSAGE_LEN, TRUE) if(!warpdesc) warpdesc = null return to_chat(user, SPAN_NOTICE("You rethink your mental image of \the [object], warping in additions to its details.")) else return /obj/item/spell/commune/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) . = ..() if(!.) return if(object) to_chat(user, SPAN_NOTICE("You already have a mental image in mind of \the [object].")) return else if(istype(hit_atom, /obj/item/photo) && !object) psiphoto = hit_atom object = "[hit_atom.name]" note = ("[hit_atom.desc]" + " [psiphoto.picture_desc]") savedscribble = "[psiphoto.scribble]" //To later compare & prevent displaying a new scribble the psion never saved image = icon2html(psiphoto, user) popup = TRUE to_chat(user, SPAN_NOTICE("You note and refine a mental replica of \the [object] for sending.")) else if(istype(hit_atom, /obj/item/paper) && !object) psipaper = hit_atom object = "[hit_atom.name]" note = "[hit_atom.desc]" savedinfo = "[psipaper.info]" image = icon2html(psipaper, user) popup = TRUE to_chat(user, SPAN_NOTICE("You note and refine a mental copy of \the [object] for sending.")) else if(isobj(hit_atom) && !object) object = "[hit_atom.name]" //Save a snapshot of its info so they don't auto-update. note = ("[hit_atom.desc]" + " [hit_atom.desc_feedback]") image = icon2html(hit_atom, user) to_chat(user, SPAN_NOTICE("You note and refine a mental image of \the [object] for sending.")) /obj/item/spell/commune/on_ranged_cast(atom/hit_atom, mob/user) . = ..() if(!.) return commune(hit_atom, user) /obj/item/spell/commune/proc/commune(atom/hit_atom, mob/user) if(!isliving(hit_atom)) return var/mob/living/target = hit_atom if(target.stat == DEAD) to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead.")) return var/psi_blocked = target.is_psi_blocked(user, FALSE) if(psi_blocked) to_chat(user, psi_blocked) return //Checks psi-sensitivity for remote item examines, because normal Commune gets blocked if(object) to_chat(user, SPAN_CULT("You psionically project to [target]: [image] [object]\n[note]" + " [warpdesc]")) var/mob/living/carbon/human/T = target var/target_sensitivity = T.check_psi_sensitivity() if(target_sensitivity >= 1) //Small detail, psions can subtly tell apart warped descriptions easier with the new line. to_chat(T, SPAN_NOTICE("[user] blinks, their eyes briefly developing an unnatural shine.")) to_chat(T, SPAN_CULT("What must be [user]'s mental image of \a [image] [object] appears in your mind.\n[note]\n[warpdesc]")) if(popup) if(psipaper) realinfo = "[psipaper.info]" psipaper.info = "[savedinfo]" TranslateWritten(T, user) //High-sensitives get papers translated to what the psion knew to_chat(T, SPAN_NOTICE("You sense [user]'s psyche link so well, you understand the sheet just as they do.")) psipaper.info = "[realinfo]" else ShowSavedScribble(T, savedscribble) else if(target_sensitivity >= 0) //Info span so it feels like an actual examine at a glance to_chat(T, SPAN_INFO("A mental image of \a [image] [object] suddenly builds in your mind.\n[note]" + " [warpdesc]")) if(popup) if(psipaper) ShowSavedInfo(T, savedinfo) else ShowSavedScribble(T, savedscribble) else //60% chance low-targets don't even get the icon. 35% (per point) of the object's name is scrambled, but base desc can still clue the item var/scrmbldobject = stars(object, (abs(target_sensitivity) * 35)) var/scrmbldnote = stars(note, (abs(target_sensitivity) * 25)) var/scrmbldwarp = stars(warpdesc, (abs(target_sensitivity) * 45)) //Warped descriptions are even more abnormal, so extra scrambled to_chat(T, SPAN_ALIEN("A mental image of \a [prob(40)?"[image] ":""][scrmbldobject] attempts to form in your mind.\n[scrmbldnote]" + " [scrmbldwarp]")) if(prob(45) && popup) if(psipaper) var/scrmbldinfo = stars(psipaper.info, (abs(target_sensitivity) * 35)) //upped ratio as pencode itself gets scrambled too ShowSavedInfo(T, scrmbldinfo) //that technically makes text in other langs slightly decipherable ICly, buuut... to_chat(T, SPAN_ALIEN("It's so nonsensical, you can't tell what's even real.")) //plant doubt by saying it's nonsense. else var/scrmbldscribble = stars(psiphoto.scribble, (abs(target_sensitivity) * 25)) ShowSavedScribble(T, scrmbldscribble, TRUE) log_say("[key_name(user)] communed to [key_name(target)]: [image] [object]\n[note]" + " [warpdesc]") for(var/mob/M as anything in GLOB.player_list) if(M.stat == DEAD && M.client.prefs.toggles & CHAT_GHOSTEARS) to_chat(M, "[user] psionically says to [target]: [image] [object]\n[note]" + " [warpdesc]") return var/text = tgui_input_text(user, "What would you like to say?", "Commune", "", MAX_MESSAGE_LEN, TRUE) if(!text) return text = formalize_text(text) if(target.stat == DEAD) to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead.")) return log_say("[key_name(user)] communed to [key_name(target)]: [text]") to_chat(user, SPAN_CULT("You psionically say to [target]: [text]")) for (var/mob/M in GLOB.player_list) if (istype(M, /mob/abstract/new_player)) continue else if(M.stat == DEAD && M.client.prefs.toggles & CHAT_GHOSTEARS) to_chat(M, "[user] psionically says to [target]: [text]") var/mob/living/carbon/human/H = target var/target_sensitivity = H.check_psi_sensitivity() if(target_sensitivity >= 1) // Augmented case for anyone with enhancements to their psi-sensitivity. to_chat(H, SPAN_NOTICE("[user] blinks, their eyes briefly developing an unnatural shine.")) to_chat(H, SPAN_CULT("You instinctively sense [user] passing a thought into your mind: [text]")) else if (target_sensitivity >= 0) // Standard case for most characters. to_chat(H, SPAN_ALIEN("A thought from outside your consciousness slips into your mind: [text]")) else // Negative sensitivity case, message arrives scrambled. // 25% of the message is scrambled per negative point of psi-sensitivity. Allowing fractional points. var/scrambled_message = stars(text, (abs(target_sensitivity) * 25)) to_chat(H, SPAN_ALIEN("A half-formed thought passes through your mind: [scrambled_message]"))