diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 838b11542a..59123c1254 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -699,3 +699,33 @@
hear |= recursive_mob_check(A, hear, 3, 1, 0, 1)
return hear
+<<<<<<< HEAD
+=======
+
+/proc/get_belly(var/atom/A) // return a belly we're in, one way or another; and if we aren't (or are too deep to comprehend being in belly), returns null
+ var/atom/loc_check = A.loc
+ var/recursion_level = 0
+ while(loc_check && !isbelly(loc_check) && !isturf(loc_check))
+ if(recursion_level > 7) // abstractly picked number, but basically means we tried going 8 levels up. Something is wrong if youre THAT deep anyway
+ break
+ loc_check = loc_check.loc
+ recursion_level++
+ if(isbelly(loc_check))
+ return loc_check
+ return null
+
+/proc/get_all_prey_recursive(var/mob/living/L, var/client_check = 1) // returns all prey inside the target as well all prey of target's prey, as well as all prey inside target's prey, etc.
+ var/list/result = list()
+
+ if(!istype(L) || !(L.vore_organs) || !(L.vore_organs.len))
+ return result
+
+ for(var/obj/belly/B in L.vore_organs)
+ for(var/mob/living/P in B.contents)
+ if(istype(P))
+ if(client_check && P.client)
+ result |= P
+ result |= get_all_prey_recursive(P, client_check)
+
+ return result
+>>>>>>> 71677c47a8... Merge pull request #15139 from Heroman3003/custom-subtle
diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm
index 8d5d8012a2..9b3dc91644 100644
--- a/code/modules/mob/say_vr.dm
+++ b/code/modules/mob/say_vr.dm
@@ -10,13 +10,11 @@
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)
+ message = sanitize_or_reflect(message,src) // Reflect too-long messages (within reason)
if(!message)
return
@@ -26,7 +24,33 @@
else
usr.emote_vr(message)
+<<<<<<< HEAD
/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
+=======
+/mob/verb/me_verb_subtle_custom(message as message) // Literally same as above but with mode_selection set to true
+ set name = "Subtle (Custom)"
+ set category = "IC"
+ set desc = "Emote to nearby people, with ability to choose which specific portion of people you wish to target."
+
+ if(say_disabled) //This is here to try to identify lag problems
+ to_chat(usr, "Speech is currently admin-disabled.")
+ return
+ if(forced_psay)
+ pme(message)
+ return
+
+ message = sanitize_or_reflect(message,src) // Reflect too-long messages (within reason)
+ if(!message)
+ return
+
+ set_typing_indicator(FALSE)
+ if(use_me)
+ usr.emote_vr("me",4,message,TRUE)
+ else
+ usr.emote_vr(message)
+
+/mob/proc/custom_emote_vr(var/m_type=1,var/message = null,var/mode_selection = FALSE) //This would normally go in emote.dm
+>>>>>>> 71677c47a8... Merge pull request #15139 from Heroman3003/custom-subtle
if(stat || !use_me && usr == src)
to_chat(src, "You are unable to emote.")
return
@@ -40,6 +64,17 @@
var/muzzled = is_muzzled()
if(m_type == 2 && muzzled) return
+ var/subtle_mode
+ if(mode_selection)
+ subtle_mode = tgui_input_list(src, "Select Custom Subtle Mode", "Custom Subtle Mode", list("Adjacent Turfs (Default)", "My Turf", "My Table", "Current Belly (Prey)", "Specific Belly (Pred)", "Specific Person"))
+ if(!subtle_mode)
+ if(mode_selection)
+ if(message)
+ to_chat(src, "Subtle mode not selected. Your input has not been sent, but preserved: [message]")
+ return
+ else
+ subtle_mode = "Adjacent Turfs (Default)"
+
var/input
if(!message)
input = sanitize_or_reflect(tgui_input_text(src,"Choose an emote to display."), src)
@@ -49,6 +84,8 @@
if(input)
log_subtle(message,src)
message = "[src] [input]"
+ if(!(subtle_mode == "Adjacent Turfs (Default)"))
+ message = "(T) " + message
else
return
@@ -56,9 +93,110 @@
var/undisplayed_message = "[src] does something too subtle for you to see."
message = encode_html_emphasis(message)
- var/list/vis = get_mobs_and_objs_in_view_fast(get_turf(src),1,2) //Turf, Range, and type 2 is emote
- var/list/vis_mobs = vis["mobs"]
- var/list/vis_objs = vis["objs"]
+ var/list/vis
+ var/list/vis_mobs
+ var/list/vis_objs
+
+ switch(subtle_mode)
+ if("Adjacent Turfs (Default)")
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),1,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = vis["objs"]
+ if("My Turf")
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),0,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = vis["objs"]
+ if("My Table")
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),7,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = vis["objs"]
+ var/list/tablelist = list()
+ var/list/newmoblist = list()
+ var/list/newobjlist = list()
+ for(var/obj/structure/table/T in range(src, 1))
+ if(istype(T) && !(T in tablelist) && !istype(T, /obj/structure/table/rack) && !istype(T, /obj/structure/table/bench))
+ tablelist |= T.get_all_connected_tables()
+ if(!(tablelist.len))
+ to_chat(src, "No nearby tables detected. Your input has not been sent, but preserved: [input]")
+ return
+ for(var/obj/structure/table/T in tablelist)
+ for(var/mob/M in vis_mobs)
+ var/dist = get_dist(T, M)
+ if(dist >= 0 && dist <= 1)
+ newmoblist |= M
+ for(var/obj/O in vis_objs)
+ var/dist = get_dist(T, O)
+ if(dist >= 0 && dist <= 1)
+ newobjlist |= O
+ vis_mobs = newmoblist
+ vis_objs = newobjlist
+ if("Current Belly (Prey)")
+ var/obj/belly/B = get_belly(src)
+ if(!istype(B))
+ to_chat(src, "You are currently not in the belly. Your input has not been sent, but preserved: [input]")
+ return
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),0,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = vis["objs"]
+ for(var/mob/M in vis_mobs) // Clean out everyone NOT in our specific belly
+ if(M == B.owner)
+ continue
+ var/obj/belly/BB = get_belly(M)
+ if(!(istype(BB)) || !(BB == B))
+ vis_mobs -= M
+ for(var/mob/M in vis_mobs) // Re-add anything in bellies of people in our belly
+ if(M == B.owner)
+ continue
+ vis_mobs |= get_all_prey_recursive(M, TRUE)
+ for(var/obj/O in vis_objs) // Clean out everyone NOT in our specific belly but for objs. No re-adding will happen there. Just don't be that deep and youre an obj anyway.
+ var/obj/belly/BB = get_belly(O)
+ if(!(istype(BB)) || !(BB == B))
+ vis_objs -= O
+ if("Specific Belly (Pred)")
+ if(!isliving(src))
+ to_chat(src, "You do not appear to be a living mob capable of having bellies. Your input has not been sent, but preserved: [input]")
+ return
+ var/mob/living/L = src
+ if(!(L.vore_organs) || !(L.vore_organs.len))
+ to_chat(src, "You do not have any bellies. Your input has not been sent, but preserved: [input]")
+ return
+ var/obj/belly/B = tgui_input_list(src, "Which belly do you want to sent the subtle to?","Select Belly", L.vore_organs)
+ if(!B || !istype(B))
+ to_chat(src, "You have not selected a valid belly. Your input has not been sent, but preserved: [input]")
+ return
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),0,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = vis["objs"]
+ for(var/mob/M in vis_mobs) // Clean out everyone NOT in our specific belly
+ if(M == B.owner)
+ continue
+ var/obj/belly/BB = get_belly(M)
+ if(!(istype(BB)) || !(BB == B))
+ vis_mobs -= M
+ for(var/mob/M in vis_mobs) // Re-add anything in bellies of people in our belly
+ if(M == B.owner)
+ continue
+ vis_mobs |= get_all_prey_recursive(M, TRUE)
+ for(var/obj/O in vis_objs) // Clean out everyone NOT in our specific belly but for objs. No re-adding will happen there. Just don't be that deep and youre an obj anyway.
+ var/obj/belly/BB = get_belly(O)
+ if(!(istype(BB)) || !(BB == B))
+ vis_objs -= O
+ if("Specific Person")
+ vis = get_mobs_and_objs_in_view_fast(get_turf(src),1,2)
+ vis_mobs = vis["mobs"]
+ vis_objs = list()
+ vis_mobs -= src
+ for(var/mob/M in vis_mobs) // ghosts get ye gone
+ if(isobserver(M) || (M.stat == DEAD))
+ vis_mobs -= M
+ if(!(vis_mobs.len))
+ to_chat(src, "No valid targets found. Your input has not been sent, but preserved: [input]")
+ return
+ var/target = tgui_input_list(src, "Who do we send our message to?","Select Target", vis_mobs)
+ if(!(target))
+ to_chat(src, "No target selected. Your input has not been sent, but preserved: [input]")
+ return
+ vis_mobs = list(target, src)
//CHOMPEdit: subtle target selection
var/all_targets_mobs = list()
@@ -187,9 +325,9 @@
spawn(0)
O.see_emote(src, message, 2)
-/mob/proc/emote_vr(var/act, var/type, var/message) //This would normally go in say.dm
+/mob/proc/emote_vr(var/act, var/type, var/message, var/mode_selection) //This would normally go in say.dm
if(act == "me")
- return custom_emote_vr(type, message)
+ return custom_emote_vr(type, message, mode_selection)
#define MAX_HUGE_MESSAGE_LEN 8192
#define POST_DELIMITER_STR "\<\>"
diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm
index 9a71cbdba7..3e682a518d 100644
--- a/code/modules/tables/tables.dm
+++ b/code/modules/tables/tables.dm
@@ -417,6 +417,27 @@ var/list/table_icon_cache = list()
if(carpeted)
add_overlay("carpet_flip[type]")
+/obj/structure/table/proc/get_all_connected_tables(var/list/connections)
+ if(!connections)
+ connections = list(src)
+ else
+ connections |= src
+ if(istype(src, /obj/structure/table/rack))
+ return connections
+
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src, direction)
+ if(T)
+ var/obj/structure/table/nextT = locate(/obj/structure/table) in T
+ if(!nextT || !istype(nextT))
+ continue
+ if(istype(nextT, /obj/structure/table/rack) || (istype(nextT, /obj/structure/table/bench) && !istype(src, /obj/structure/table/bench)) || (!istype(nextT, /obj/structure/table/bench) && istype(src, /obj/structure/table/bench)))
+ continue
+ if(!(nextT in connections))
+ connections |= nextT.get_all_connected_tables(connections)
+
+ return connections
+
#define CORNER_NONE 0
#define CORNER_COUNTERCLOCKWISE 1