diff --git a/code/modules/mob/say_ch.dm b/code/modules/mob/say_ch.dm new file mode 100644 index 0000000000..9f0225f7ef --- /dev/null +++ b/code/modules/mob/say_ch.dm @@ -0,0 +1,53 @@ +/mob/proc/get_all_in_bellies() + var/list/mobs_in_belly = list() + for (var/obj/belly/belly in contents) //dogborg sleeper, etc + for (var/mob/M in belly.contents) + mobs_in_belly |= M.get_all_in_bellies() + mobs_in_belly |= M + return mobs_in_belly + +/atom/proc/get_ultimate_mob() + var/mob/ultimate_mob + var/atom/to_check = loc + var/n = 0 + while (to_check && !isturf(to_check) && n < 6) + if (ismob(to_check)) + ultimate_mob = to_check + to_check = to_check.loc + n = 0 + n++ + return ultimate_mob + +/atom/proc/get_ultimate_belly() + var/obj/belly/ultimate_belly + var/atom/to_check = loc + var/n = 0 + while (to_check && !isturf(to_check) && n < 6) + if (isbelly(to_check)) + ultimate_belly = to_check + to_check = to_check.loc + n = 0 + n++ + return ultimate_belly + +/mob/verb/me_verb_subtle_distanced(message as message) //This would normally go in say.dm + set name = "Subtle-Targeted" + set category = "IC" + set desc = "Emote to nearby people (and your pred/prey), picking from selected targets afterwards." + + if(say_disabled) //This is here to try to identify lag problems + to_chat(usr, "Speech is currently admin-disabled.") + return + //VOREStation Addition Start + if(forced_psay) + pme(message) + return + //VOREStation Addition End + + message = sanitize_or_reflect(message,src) //VOREStation Edit - Reflect too-long messages (within reason) + if(!message) + return + + set_typing_indicator(FALSE) + if(use_me) + usr.custom_emote_vr(4,message,TRUE) diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm index c0a2a4b5e2..1fb88910e1 100644 --- a/code/modules/mob/say_vr.dm +++ b/code/modules/mob/say_vr.dm @@ -26,7 +26,7 @@ else usr.emote_vr(message) -/mob/proc/custom_emote_vr(var/m_type=1,var/message = null) //This would normally go in emote.dm +/mob/proc/custom_emote_vr(var/m_type=1,var/message = null, var/distanced=FALSE) //This would normally go in emote.dm //CHOMPEdit: subtle-distance if(stat || !use_me && usr == src) to_chat(src, "You are unable to emote.") return @@ -60,7 +60,102 @@ var/list/vis_mobs = vis["mobs"] var/list/vis_objs = vis["objs"] - for(var/mob/M as anything in vis_mobs) + //CHOMPEdit: subtle target selection + var/all_targets_mobs = list() + var/all_targets_objs = list() + if (distanced) + var/obj/belly/u_belly = get_ultimate_belly() + var/mob/living/u_pred = u_belly?.owner || src + + var/valid_targets = list("One tile radius" = "otr", "Single tile" = "st", "All in belly and preds" = "aibap") + for (var/mob/M as anything in vis_mobs) + if (M == src) + continue + if (istype(M, /mob/living) && isturf(M.loc) && !u_belly) + valid_targets["[M]"] = "\ref[M]" + continue + if (get_turf(M) == get_turf(src)) //so we aren't going through everything, it's a safe bet the belly is in the mob it's supposed to be in + var/obj/belly/belly = M.get_ultimate_belly() + if (belly?.owner == u_pred || u_pred == M) + valid_targets["[M]"] = "\ref[M]" + for (var/obj/item/i in vis_objs) + if (LAZYLEN(i.possessed_voice) && i.get_ultimate_mob() == src) + valid_targets["[i]"] = "\ref[i]" + valid_targets += list("Cancel" = "c") + valid_targets += list("Cancel and print to chat" = "captc") + var/selected = input(src, "Choose the target to send it to.", "Subtle Distance", "One tile radius") as anything in valid_targets //default to one tile radius + var/target = valid_targets[selected] + if (target == "c" || isnull(target)) + return + if (target == "captc") + to_chat(src, "Cancelled message (pressed cancel): [message]") + return + + vis = get_mobs_and_objs_in_view_fast(get_turf(src),1,2) //in case it changed + vis_mobs = vis["mobs"] + vis_objs = vis["objs"] + + var/cancelled + + switch(target) + if ("otr", null) + all_targets_mobs |= vis_mobs + all_targets_objs |= vis_objs + if ("st") + for (var/mob/M as anything in vis_mobs) + if (isobserver(M) || get_dist(get_turf(src), get_turf(M)) < 1) + all_targets_mobs |= M + for (var/obj/M as anything in vis_objs) + if (isobserver(M) || get_dist(get_turf(src), get_turf(M)) < 1) + all_targets_objs |= M + if ("aibap") + var/obj/belly/belly = get_ultimate_belly() //in case it's changed + var/mob/pred = belly?.owner || src + if (pred) + all_targets_mobs |= pred.get_all_in_bellies() + for (var/mob/M as anything in vis_mobs) + if (isobserver(M)) + all_targets_mobs |= M + continue + if (get_dist(get_turf(src), get_turf(M)) > 1) + continue + if (!isturf(M.loc) && !(M in all_targets_mobs)) //possessed items, mobs in bags, etc + if (M.get_ultimate_belly() in pred.contents) + all_targets_mobs |= M + if (istype(M, /mob/living/dominated_brain) && M.get_ultimate_mob() == pred) + all_targets_mobs |= M + for (var/obj/item/i in vis_objs) + if (LAZYLEN(i.possessed_voice) && (i.get_ultimate_belly() in pred.contents)) + all_targets_objs |= i + all_targets_mobs |= i.possessed_voice + all_targets_mobs |= pred + else + cancelled = "no belly owner" + else + var/target_reffed = locate(target) + if (!target_reffed || (ismob(target_reffed) && !(target_reffed in vis_mobs)) || (isitem(target_reffed) && !(target_reffed in vis_objs))) + cancelled = "mob not available" + else + if (ismob(target_reffed)) + all_targets_mobs |= target_reffed + if (isitem(target_reffed)) + var/obj/item/i = target_reffed + all_targets_objs |= target_reffed + all_targets_mobs |= i.possessed_voice + for (var/mob/M as anything in vis_mobs) + if (isobserver(M)) + all_targets_mobs |= M + + all_targets_mobs |= src + + if (cancelled) + to_chat(src, "Cancelled message ([cancelled]): [message]") + return + else + all_targets_mobs = vis_mobs + all_targets_objs = vis_objs + + for(var/mob/M as anything in all_targets_mobs) //CHOMPEdit end if(isnewplayer(M)) continue if(isobserver(M) && !(is_preference_enabled(/datum/client_preference/whisubtle_vis) || (isbelly(M.loc) && src == M.loc:owner)) && !M.client?.holder) //CHOMPEdit - Added the belly check so that ghosts in bellies can still see their pred's messages. @@ -73,7 +168,7 @@ if(voice_sounds_list) //CHOMPEdit, changes to subtle emotes to use mob voice instead M << sound(pick(voice_sounds_list), volume = 25) - for(var/obj/O as anything in vis_objs) + for(var/obj/O as anything in all_targets_objs) //CHOMPEdit, allows for subtle distances spawn(0) O.see_emote(src, message, 2) diff --git a/vorestation.dme b/vorestation.dme index 59eaa32eb3..5df5eac1f2 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -2856,6 +2856,7 @@ #include "code\modules\mob\mob_planes_vr.dm" #include "code\modules\mob\mob_transformation_simple.dm" #include "code\modules\mob\say.dm" +#include "code\modules\mob\say_ch.dm" #include "code\modules\mob\say_vr.dm" #include "code\modules\mob\skillset.dm" #include "code\modules\mob\transform_procs.dm"