diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 22bafbe41f..0b43b6ea3e 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1596,7 +1596,8 @@
else
clear_alert("high")
- if(!isbelly(loc) && !previewing_belly) //VOREStation Add - Belly fullscreens safety //CHOMPEdit
+ //CHOMPEdit - surrounding_belly() used instead of isbelly(loc) to not clear indirect vorefx
+ if(!surrounding_belly() && !previewing_belly) //VOREStation Add - Belly fullscreens safety //CHOMPEdit
clear_fullscreen("belly")
//clear_fullscreen("belly2") //Chomp disable, using our own implementation
//clear_fullscreen("belly3") //Chomp disable, using our own implementation
diff --git a/code/modules/vore/eating/belly_obj_ch.dm b/code/modules/vore/eating/belly_obj_ch.dm
index 224f80ce67..5e767363b4 100644
--- a/code/modules/vore/eating/belly_obj_ch.dm
+++ b/code/modules/vore/eating/belly_obj_ch.dm
@@ -137,6 +137,8 @@
var/item_digest_logs = FALSE // Chat messages for digested items.
var/storing_nutrition = FALSE // Storing gained nutrition as paste instead of absorbing it.
+ var/list/belly_surrounding = list() // A list of living mobs surrounded by this belly, including inside containers, food, on mobs, etc. Exclusing inside other bellies.
+
/obj/belly/proc/GetFullnessFromBelly()
if(!affects_vore_sprites)
return 0
@@ -521,9 +523,9 @@
/////////////////////////// CHOMP PCL END ///////////////////////////
/obj/belly/proc/update_internal_overlay()
- if(LAZYLEN(contents))
+ if(LAZYLEN(belly_surrounding))
SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, TRUE) // Signals vore_fx() to listening atoms. Atoms must handle appropriate isliving() checks.
- for(var/A in contents)
+ for(var/A in belly_surrounding)
if(isliving(A))
vore_fx(A,1)
if(owner.previewing_belly == src)
@@ -609,4 +611,25 @@
stored_nutrition = 0
qdel(src)
return
- .=..()
\ No newline at end of file
+ .=..()
+
+// Updates the belly_surrounding list variable. Called in bellymodes_vr.dm
+/obj/belly/proc/update_belly_surrounding()
+ if(!contents.len)
+ belly_surrounding = list()
+ return
+ belly_surrounding = get_belly_surrounding(contents)
+
+// Recursive proc that returns all living mobs directly and indirectly inside a belly
+// This can also be called more generically to get all living mobs not in bellies within any contents list
+/obj/belly/proc/get_belly_surrounding(var/list/C)
+ var/list/surrounding = list()
+ for(var/thing in C)
+ if(istype(thing,/mob/living))
+ var/mob/living/L = thing
+ surrounding.Add(L)
+ surrounding.Add(get_belly_surrounding(L.contents))
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ surrounding.Add(get_belly_surrounding(I.contents))
+ return surrounding
diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm
index 81f116e2b4..89d3b632a8 100644
--- a/code/modules/vore/eating/belly_obj_vr.dm
+++ b/code/modules/vore/eating/belly_obj_vr.dm
@@ -538,8 +538,17 @@
if(reagents.total_volume >= 5 && !isliving(thing) && (item_digest_mode == IM_DIGEST || item_digest_mode == IM_DIGEST_PARALLEL)) //CHOMPAdd
reagents.trans_to(thing, reagents.total_volume * 0.1, 1 / max(LAZYLEN(contents), 1), FALSE) //CHOMPAdd
//Messages if it's a mob
+ //CHOMPEdit Start - Include indirect viewers in seeing vorefx
+ var/list/startfx = list()
if(isliving(thing))
- var/mob/living/M = thing
+ var/mob/living/L = thing
+ startfx.Add(L)
+ startfx.Add(get_belly_surrounding(L.contents))
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ startfx.Add(get_belly_surrounding(I.contents))
+
+ for(var/mob/living/M in startfx) //CHOMPEdit End of indirect vorefx changes
M.updateVRPanel()
var/raw_desc //Let's use this to avoid needing to write the reformat code twice
if(absorbed_desc && M.absorbed)
@@ -570,7 +579,7 @@
if(digest_mode == DM_DIGEST)
reagents.trans_to(M, reagents.total_volume * 0.1, 1 / max(LAZYLEN(contents), 1), FALSE)
to_chat(M, "You splash into a pool of [reagent_name]!")
- else if(count_items_for_sprite) //CHOMPEdit - If this is enabled also update fullness for non-living things
+ if(!isliving(thing) && count_items_for_sprite) //CHOMPEdit - If this is enabled also update fullness for non-living things
owner.update_fullness() //CHOMPEdit - This is run whenever a belly's contents are changed.
//if(istype(thing, /obj/item/capture_crystal)) //CHOMPEdit start: Capture crystal occupant gets to see belly text too. Moved to modular_chomp capture_crystal.dm.
//var/obj/item/capture_crystal/CC = thing
@@ -596,18 +605,31 @@
if(count_items_for_sprite && !NB.count_items_for_sprite)
owner.update_fullness()
return //CHOMPEdit End
- if(isliving(thing) && !isbelly(thing.loc))
- owner.update_fullness() //CHOMPEdit - This is run whenever a belly's contents are changed.
+
+ //CHOMPEdit Start - Remove vorefx from all those indirectly viewing as well
+ var/list/endfx = list()
+ if(isliving(thing))
var/mob/living/L = thing
- L.clear_fullscreen("belly")
- //L.clear_fullscreen("belly2") // CHOMP Disable - using our implementation, not upstream's
- //L.clear_fullscreen("belly3") // CHOMP Disable - using our implementation, not upstream's
- //L.clear_fullscreen("belly4") // CHOMP Disable - using our implementation, not upstream's
- if(L.hud_used)
- if(!L.hud_used.hud_shown)
- L.toggle_hud_vis()
- if((L.stat != DEAD) && L.ai_holder)
- L.ai_holder.go_wake()
+ endfx.Add(L)
+ endfx.Add(get_belly_surrounding(L.contents))
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ endfx.Add(get_belly_surrounding(I.contents))
+ if(!isbelly(thing.loc))
+ for(var/mob/living/L in endfx) //CHOMPEdit End
+ if(L.surrounding_belly()) continue
+ owner.update_fullness() //CHOMPEdit - This is run whenever a belly's contents are changed.
+ L.clear_fullscreen("belly")
+ //L.clear_fullscreen("belly2") // CHOMP Disable - using our implementation, not upstream's
+ //L.clear_fullscreen("belly3") // CHOMP Disable - using our implementation, not upstream's
+ //L.clear_fullscreen("belly4") // CHOMP Disable - using our implementation, not upstream's
+ if(L.hud_used)
+ if(!L.hud_used.hud_shown)
+ L.toggle_hud_vis()
+ if((L.stat != DEAD) && L.ai_holder)
+ L.ai_holder.go_wake()
+ L.stop_sound_channel(CHANNEL_PREYLOOP) //CHOMPAdd - This was on release_specific_contents proc, why is it not here on belly exit?
+ //CHOMPEdit End of indirect vorefx changes
if(isitem(thing) && !isbelly(thing.loc)) //CHOMPEdit: Digest stage effects. Don't bother adding overlays to stuff that won't make it back out.
if(count_items_for_sprite) //CHOMPEdit - If this is enabled also update fullness for non-living things
owner.update_fullness() //CHOMPEdit - This is run whenever a belly's contents are changed.
diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm
index 2fddac73f2..58b9af7e07 100644
--- a/code/modules/vore/eating/bellymodes_vr.dm
+++ b/code/modules/vore/eating/bellymodes_vr.dm
@@ -11,6 +11,7 @@
return
HandleBellyReagents() //CHOMP reagent belly stuff, here to jam it into subsystems and avoid too much cpu usage
+ update_belly_surrounding() //CHOMPAdd - Updates belly_surrounding list for indirect vore usage
// VERY early exit
if(!contents.len)
return
@@ -46,10 +47,11 @@
log_debug("Digest mode [digest_mode] didn't exist in the digest_modes list!!")
return FALSE
if(digest_mode == DM_EGG)
+ prey_loop() //CHOMPAdd - Apparently on Egg mode the sound loop never played before? Just slapping this here to fix that
if(DM.handle_atoms(src, contents))
updateVRPanels()
return
- if(!length(touchable_atoms))
+ if(!length(touchable_atoms) && !belly_surrounding.len) //CHOMPEdit - Needed to not exit early for indirect vorefx
return
/////////////////////////// Sound Selections ///////////////////////////
@@ -93,7 +95,7 @@
SEND_SOUND(M, prey_digest)
play_sound = pred_digest
- if(!LAZYLEN(touchable_mobs))
+ if(!LAZYLEN(belly_surrounding)) //CHOMPEdit - Changed to belly_surrounding from touchable_mobs so indirect vore viewers get this too
if(to_update)
updateVRPanels()
if(play_sound)
@@ -263,7 +265,7 @@
return list("to_update" = to_update, "touchable_mobs" = touchable_mobs, "digestion_noise_chance" = digestion_noise_chance)
/obj/belly/proc/prey_loop()
- for(var/mob/living/M in contents)
+ for(var/mob/living/M in belly_surrounding) //CHOMPEdit - contents changed to belly_surrounding to loop sound for indirect viewers too
//We don't bother executing any other code if the prey doesn't want to hear the noises.
if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
@@ -272,7 +274,7 @@
// We don't want the sounds to overlap, but we do want them to steadily replay.
// We also don't want the sounds to play if the pred hasn't marked this belly as fleshy, or doesn't
// have the right sounds to play.
- if(isbelly(M.loc) && is_wet && wet_loop && (world.time > M.next_preyloop))
+ if(is_wet && wet_loop && (world.time > M.next_preyloop)) //CHOMPEdit - Removed isbelly(M.loc) as some viewers might be indirectly in the belly
M.stop_sound_channel(CHANNEL_PREYLOOP)
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
M.playsound_local(get_turf(src), preyloop, 80, 0, channel = CHANNEL_PREYLOOP, frequency = noise_freq) //CHOMPEdit
@@ -388,7 +390,7 @@
owner_adjust_nutrition(oldnutrition) //CHOMPedit end
/obj/belly/proc/updateVRPanels()
- for(var/mob/living/M in contents)
+ for(var/mob/living/M in belly_surrounding) //CHOMPEdit - Changed to belly_surrounding from contents so updates happen for indirect viewers too
if(M.client)
M.updateVRPanel()
if(owner.client)
diff --git a/code/modules/vore/eating/living_ch.dm b/code/modules/vore/eating/living_ch.dm
index 44e1afe5d8..875d1c328d 100644
--- a/code/modules/vore/eating/living_ch.dm
+++ b/code/modules/vore/eating/living_ch.dm
@@ -351,3 +351,12 @@
set category = "Abilities"
set desc = "Check your current nutrition level."
to_chat(src, "Current nutrition level: [nutrition].")
+
+// This proc will either return the first belly the mob is in or return null if they're not in one
+/mob/living/proc/surrounding_belly()
+ var/atom/curloc = src.loc
+ while(curloc && !isbelly(curloc))
+ if(istype(curloc, /turf)) break
+ if(!curloc.loc || curloc == curloc.loc) break
+ curloc = curloc.loc
+ if(isbelly(curloc)) return curloc
diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm
index 7ef59d38c9..8884a2eb7e 100644
--- a/code/modules/vore/eating/vorepanel_vr.dm
+++ b/code/modules/vore/eating/vorepanel_vr.dm
@@ -120,6 +120,11 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
data["show_pictures"] = show_pictures
var/atom/hostloc = host.loc
+ //CHOMPAdd Start - Allow VorePanel to show pred belly details even while indirectly inside
+ if(istype(host, /mob/living))
+ var/mob/living/H = host
+ hostloc = H.surrounding_belly()
+ //CHOMPAdd End of indirect vorefx additions
var/list/inside = list()
if(isbelly(hostloc))
var/obj/belly/inside_belly = hostloc
@@ -1950,11 +1955,14 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
return TRUE // Aren't here anymore, need to update menu
var/intent = "Examine"
- if(isliving(target))
- intent = tgui_alert(usr, "What do you want to do to them?","Query",list("Examine","Help Out","Devour"))
+ //CHOMPEdit Start - Only allow indirect belly viewers to examine
+ if(user in OB)
+ if(isliving(target))
+ intent = tgui_alert(usr, "What do you want to do to them?","Query",list("Examine","Help Out","Devour"))
- else if(istype(target, /obj/item))
- intent = tgui_alert(usr, "What do you want to do to that?","Query",list("Examine","Use Hand"))
+ else if(istype(target, /obj/item))
+ intent = tgui_alert(usr, "What do you want to do to that?","Query",list("Examine","Use Hand"))
+ //CHOMPEdit End of indirect vorefx changes
switch(intent)
if("Examine") //Examine a mob inside another mob
@@ -2050,6 +2058,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
for(var/atom/movable/target in host.vore_selected)
to_chat(target,"You're squished from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!")
+ //CHOMPAdd - Send the transfer message to indirect targets as well. Slightly different message because why not.
+ to_chat(host.vore_selected.get_belly_surrounding(target.contents),"You're squished along with [target] from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!")
host.vore_selected.transfer_contents(target, choice, 1)
return TRUE
return
@@ -2095,6 +2105,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(!choice || !(target in host.vore_selected))
return TRUE
to_chat(target,"You're squished from [host]'s [lowertext(host.vore_selected.name)] to their [lowertext(choice.name)]!")
+ //CHOMPAdd - Send the transfer message to indirect targets as well. Slightly different message because why not.
+ to_chat(host.vore_selected.get_belly_surrounding(target.contents),"You're squished along with [target] from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!")
host.vore_selected.transfer_contents(target, choice)
diff --git a/modular_chomp/code/game/objects/items/weapons/capture_crystal.dm b/modular_chomp/code/game/objects/items/weapons/capture_crystal.dm
index 9c7ce07ef5..56b72ca24c 100644
--- a/modular_chomp/code/game/objects/items/weapons/capture_crystal.dm
+++ b/modular_chomp/code/game/objects/items/weapons/capture_crystal.dm
@@ -2,6 +2,7 @@
var/spawn_mob_name = "A mob"
var/obj/belly/in_gut = null
+/* No longer need the vorefx additions as these will be handled for all indirect viewers now, including those in capture crystals
// Signals detect important procs from the host belly. Necessary to update visuals and sound loop for the player inside.
/obj/item/capture_crystal/enter_belly(obj/belly/B)
if(isbelly(B)) // Sanity
@@ -128,6 +129,7 @@
UnregisterSignal(in_gut, COMSIG_BELLY_UPDATE_VORE_FX)
UnregisterSignal(in_gut, COMSIG_BELLY_UPDATE_PREY_LOOP)
in_gut = null
+*/
/obj/item/capture_crystal/loadout
active = TRUE