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