From 47ec82bc71b92bb1c2b13be63543bfc84a104384 Mon Sep 17 00:00:00 2001 From: CHOMPStation2StaffMirrorBot <94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com> Date: Thu, 8 Jan 2026 14:45:40 -0700 Subject: [PATCH] [MIRROR] vore fx and resist code cleanup (#12236) Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> --- code/modules/tgs_commands/vorestation.dm | 5 +- code/modules/vore/eating/belly_obj_resist.dm | 291 +++++++++++++ code/modules/vore/eating/belly_obj_vfx.dm | 165 ++++++++ code/modules/vore/eating/belly_obj_vr.dm | 412 ------------------- vorestation.dme | 2 + 5 files changed, 461 insertions(+), 414 deletions(-) create mode 100644 code/modules/vore/eating/belly_obj_resist.dm create mode 100644 code/modules/vore/eating/belly_obj_vfx.dm diff --git a/code/modules/tgs_commands/vorestation.dm b/code/modules/tgs_commands/vorestation.dm index 2576fc63a6..b7750a9335 100644 --- a/code/modules/tgs_commands/vorestation.dm +++ b/code/modules/tgs_commands/vorestation.dm @@ -191,8 +191,9 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations) for(var/list/item in GLOB.PDA_Manifest) outp += "\n__**[item["cat"]]:**__" for(var/list/person in item["elems"]) - total |= person - outp += "\n[person["name"]] -:- [person["rank"]]" + var/output_string = "[person["name"]] -:- [person["rank"]]" + total |= output_string + outp += "\n[output_string]" return "**Total crew members:** [total.len]\n" + outp diff --git a/code/modules/vore/eating/belly_obj_resist.dm b/code/modules/vore/eating/belly_obj_resist.dm new file mode 100644 index 0000000000..1a60075c43 --- /dev/null +++ b/code/modules/vore/eating/belly_obj_resist.dm @@ -0,0 +1,291 @@ +//Handle a mob struggling +// Called from /mob/living/carbon/relaymove() +/obj/belly/proc/relay_resist(mob/living/R, obj/item/C) + if (!(R in contents)) + if(!C) + return // User is not in this belly + + R.setClickCooldown(50) + + if(owner.stat) //If owner is stat (dead, KO) we can actually escape + resist_default_escape(R, C) + return + + if(displayed_message_flags & MS_FLAG_STRUGGLE_OUTSIDE) + resist_struggle_outside(R) + + if((vore_sprite_flags & DM_FLAG_VORESPRITE_BELLY) && (owner.vore_capacity_ex[belly_sprite_to_affect] >= 1) && !private_struggle && resist_triggers_animation && affects_vore_sprites) + owner.vs_animate(belly_sprite_to_affect) + + if(!private_struggle) + resist_play_sound() + + if(prob(belchchance))//Unsure if this should go in escapable or not, leaving it here for now. + owner.emote("belch") + + if(escapable) //If the stomach has escapable enabled. + if(resist_check_escapechance(R, C)) + return + if(resist_check_transferchance(R, C)) + return + if(resist_check_secondary_transferchance(R,C)) + return + if(resist_check_absorbchance(R)) + return + if(resist_check_digestchance(R)) + return + if(resist_check_selectchance(R)) + return + + var/struggle_user_message = span_valert(belly_format_string(struggle_messages_inside, R)) + to_chat(R, struggle_user_message) + to_chat(owner, span_vwarning("Your prey appears to be unable to make any progress in escaping your [lowertext(name)].")) + + return + + var/struggle_user_message = span_valert(belly_format_string(struggle_messages_inside, R)) + to_chat(R, struggle_user_message) + +/obj/belly/proc/resist_default_escape(mob/living/R, obj/item/C) + var/escape_attempt_owner_message = span_vwarning(belly_format_string(escape_attempt_messages_owner, R)) + var/escape_attempt_prey_message = span_vwarning(belly_format_string(escape_attempt_messages_prey, R)) + var/escape_fail_owner_message = span_vwarning(belly_format_string(escape_fail_messages_owner, R)) + var/escape_fail_prey_message = span_vnotice(belly_format_string(escape_fail_messages_prey, R)) + escape_attempt_prey_message = span_vwarning("[escape_attempt_prey_message] (will take around [escapetime/10] seconds.)") + to_chat(R, escape_attempt_prey_message) + to_chat(owner, escape_attempt_owner_message) + + if(do_after(R, escapetime, owner, target = src, timed_action_flags = IGNORE_INCAPACITATED)) + if((owner.stat || escapable)) //Can still escape? + if(C) + release_specific_contents(C) + return + + if(R.loc == src) + release_specific_contents(R) + return + + if(R.loc != src) //Aren't even in the belly. Quietly fail. + return + + //Belly became inescapable or mob revived + to_chat(R, escape_fail_prey_message) + to_chat(owner, escape_fail_owner_message) + +/obj/belly/proc/resist_struggle_outside(mob/living/R) + var/struggle_outer_message = span_valert(belly_format_string(struggle_messages_outside, R)) + if(private_struggle) + to_chat(owner, struggle_outer_message) + return + + for(var/mob/M in hearers(4, owner)) + M.show_message(struggle_outer_message, 2) // hearable + +/obj/belly/proc/resist_play_sound() + if(is_wet) + var/sound/struggle_snuggle + if(!fancy_vore) + struggle_snuggle = sound(get_sfx("classic_struggle_sounds")) + else + struggle_snuggle = sound(get_sfx("fancy_prey_struggle")) + playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) + return + var/sound/struggle_rustle = sound(get_sfx("rustle")) + playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) + +/obj/belly/proc/resist_check_escapechance(mob/living/R, obj/item/C) + if(!prob(escapechance)) //Let's have it check to see if the prey escapes first. + return FALSE + + var/escape_attempt_owner_message = span_vwarning(belly_format_string(escape_attempt_messages_owner, R)) + var/escape_attempt_prey_message = span_vwarning(belly_format_string(escape_attempt_messages_prey, R)) + var/escape_fail_owner_message = span_vwarning(belly_format_string(escape_fail_messages_owner, R)) + var/escape_fail_prey_message = span_vnotice(belly_format_string(escape_fail_messages_prey, R)) + to_chat(R, escape_attempt_prey_message) + to_chat(owner, escape_attempt_owner_message) + if(do_after(R, escapetime, target = src)) + if(escapable && C) + var/escape_item_owner_message = span_vwarning(belly_format_string(escape_item_messages_owner, R, item = C)) + var/escape_item_prey_message = span_vwarning(belly_format_string(escape_item_messages_prey, R, item = C)) + var/escape_item_outside_message = span_vwarning(belly_format_string(escape_item_messages_outside, R, item = C)) + + release_specific_contents(C) + to_chat(R, escape_item_prey_message) + to_chat(owner, escape_item_owner_message) + if(!private_struggle) + for(var/mob/M in hearers(4, owner)) + M.show_message(escape_item_outside_message, 2) + return TRUE + + if(escapable && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled? + var/escape_owner_message = span_vwarning(belly_format_string(escape_messages_owner, R)) + var/escape_prey_message = span_vwarning(belly_format_string(escape_messages_prey, R)) + var/escape_outside_message = span_vwarning(belly_format_string(escape_messages_outside, R)) + + release_specific_contents(R) + to_chat(R, escape_prey_message) + to_chat(owner, escape_owner_message) + if(!private_struggle) + for(var/mob/M in hearers(4, owner)) + M.show_message(escape_outside_message, 2) + return TRUE + + if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. + return TRUE + + //Belly became inescapable. + to_chat(R, escape_fail_prey_message) + to_chat(owner, escape_fail_owner_message) + return TRUE + +/obj/belly/proc/resist_check_transferchance(mob/living/R, obj/item/C) + if(!prob(transferchance) || !transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started. + return FALSE + + var/obj/belly/dest_belly + for(var/obj/belly/B as anything in owner.vore_organs) + if(B.name == transferlocation) + dest_belly = B + break + + if(!dest_belly) + to_chat(owner, span_vwarning("Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")) + transferchance = 0 + transferlocation = null + return TRUE + + var/primary_transfer_owner_message = span_vwarning(belly_format_string(primary_transfer_messages_owner, R, dest = transferlocation)) + var/primary_transfer_prey_message = span_vwarning(belly_format_string(primary_transfer_messages_prey, R, dest = transferlocation)) + + to_chat(R, primary_transfer_prey_message) + to_chat(owner, primary_transfer_owner_message) + if(C) + transfer_contents(C, dest_belly) + return TRUE + + transfer_contents(R, dest_belly) + return TRUE + +/obj/belly/proc/resist_check_secondary_transferchance(mob/living/R, obj/item/C) + if(!prob(transferchance_secondary) || !transferlocation_secondary) //After the first potential mess getting into, run the secondary one which might be even bigger of a mess. + return FALSE + + var/obj/belly/dest_belly + for(var/obj/belly/B as anything in owner.vore_organs) + if(B.name == transferlocation_secondary) + dest_belly = B + break + + if(!dest_belly) + to_chat(owner, span_vwarning("Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")) + transferchance_secondary = 0 + transferlocation_secondary = null + return TRUE + + var/secondary_transfer_owner_message = span_vwarning(belly_format_string(secondary_transfer_messages_owner, R, dest = transferlocation_secondary)) + var/secondary_transfer_prey_message = span_vwarning(belly_format_string(secondary_transfer_messages_prey, R, dest = transferlocation_secondary)) + + to_chat(R, secondary_transfer_prey_message) + to_chat(owner, secondary_transfer_owner_message) + if(C) + transfer_contents(C, dest_belly) + return TRUE + + transfer_contents(R, dest_belly) + return TRUE + +/obj/belly/proc/resist_check_absorbchance(mob/living/R) + if(!prob(absorbchance) || digest_mode == DM_ABSORB) //After that, let's have it run the absorb chance. + return FALSE + var/absorb_chance_owner_message = span_vwarning(belly_format_string(absorb_chance_messages_owner, R)) + var/absorb_chance_prey_message = span_vwarning(belly_format_string(absorb_chance_messages_prey, R)) + + to_chat(R, absorb_chance_prey_message) + to_chat(owner, absorb_chance_owner_message) + digest_mode = DM_ABSORB + return TRUE + +/obj/belly/proc/resist_check_digestchance(mob/living/R) + if(!prob(digestchance) || digest_mode == DM_DIGEST) //Then, let's see if it should run the digest chance. + return FALSE + var/digest_chance_owner_message = span_vwarning(belly_format_string(digest_chance_messages_owner, R)) + var/digest_chance_prey_message = span_vwarning(belly_format_string(digest_chance_messages_prey, R)) + + to_chat(R, digest_chance_prey_message) + to_chat(owner, digest_chance_owner_message) + digest_mode = DM_DIGEST + return TRUE + +/obj/belly/proc/resist_check_selectchance(mob/living/R) + if(!prob(selectchance) || digest_mode == DM_SELECT) //Finally, let's see if it should run the selective mode chance. + return FALSE + var/select_chance_owner_message = span_vwarning(belly_format_string(select_chance_messages_owner, R)) + var/select_chance_prey_message = span_vwarning(belly_format_string(select_chance_messages_prey, R)) + + to_chat(R, select_chance_prey_message) + to_chat(owner, select_chance_owner_message) + digest_mode = DM_SELECT + return TRUE + +// Absorbed resist handling +/obj/belly/proc/relay_absorbed_resist(mob/living/R) + if (!(R in contents) || !R.absorbed) + return // User is not in this belly or isn't actually absorbed + + R.setClickCooldown(50) + + if(displayed_message_flags & MS_FLAG_STRUGGLE_ABSORBED_OUTSIDE) + absorbed_resist_struggle_outside(R) + + if(!private_struggle) + resist_play_sound() + + //absorb resists + if(escapable || owner.stat) //If the stomach has escapable enabled or the owner is dead/unconscious + if(absorbed_resist_check_escapechance(R)) + return + + var/struggle_user_message = span_valert(belly_format_string(absorbed_struggle_messages_inside, R, use_absorbed_count = TRUE)) + to_chat(R, struggle_user_message) + +/obj/belly/proc/absorbed_resist_struggle_outside(mob/living/R) + var/struggle_outer_message = span_valert(belly_format_string(absorbed_struggle_messages_outside, R, use_absorbed_count = TRUE)) + if(private_struggle) + to_chat(owner, struggle_outer_message) + return + + for(var/mob/M in hearers(4, owner)) + M.show_message(struggle_outer_message, 2) // hearable + +/obj/belly/proc/absorbed_resist_check_escapechance(mob/living/R) + if(!(prob(escapechance_absorbed) || owner.stat)) //Let's have it check to see if the prey's escape attempt starts. + return FALSE + var/escape_attempt_absorbed_owner_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_owner, R)) + var/escape_attempt_absorbed_prey_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_prey, R)) + + to_chat(R, escape_attempt_absorbed_prey_message) + to_chat(owner, escape_attempt_absorbed_owner_message) + if(do_after(R, escapetime, target = src)) + if((escapable || owner.stat) && (R.loc == src) && prob(escapechance_absorbed)) //Does the escape attempt succeed? + var/escape_absorbed_owner_message = span_vwarning(belly_format_string(escape_absorbed_messages_owner, R)) + var/escape_absorbed_prey_message = span_vwarning(belly_format_string(escape_absorbed_messages_prey, R)) + var/escape_absorbed_outside_message = span_vwarning(belly_format_string(escape_absorbed_messages_outside, R)) + + release_specific_contents(R) + to_chat(R, escape_absorbed_prey_message) + to_chat(owner, escape_absorbed_owner_message) + if(!private_struggle) + for(var/mob/M in hearers(4, owner)) + M.show_message(escape_absorbed_outside_message, 2) + return TRUE + + if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. + return TRUE + + //Belly became inescapable or you failed your roll. + var/escape_fail_absorbed_owner_message = span_vwarning(belly_format_string(escape_fail_absorbed_messages_owner, R)) + var/escape_fail_absorbed_prey_message = span_vnotice(belly_format_string(escape_fail_absorbed_messages_prey, R)) + + to_chat(R, escape_fail_absorbed_prey_message) + to_chat(owner, escape_fail_absorbed_owner_message) + return TRUE diff --git a/code/modules/vore/eating/belly_obj_vfx.dm b/code/modules/vore/eating/belly_obj_vfx.dm new file mode 100644 index 0000000000..5e42d283b5 --- /dev/null +++ b/code/modules/vore/eating/belly_obj_vfx.dm @@ -0,0 +1,165 @@ +// SEND_SIGNAL(COMSIG_BELLY_UPDATE_VORE_FX) is sometimes used when calling vore_fx() to send belly visuals +// to certain non-belly atoms. Not called here as vore_fx() is usually only called if a mob is in the belly. +// Don't forget it if you need to rework vore_fx(). +/obj/belly/proc/vore_fx(mob/living/L, var/severity = 0) + if(!istype(L)) + return + if(!L.client) + return + if(L.previewing_belly && L.previewing_belly != src) + return + if(L.previewing_belly == src && L.vore_selected != src) + L.previewing_belly = null + return + if(!L.show_vore_fx) + L.clear_fullscreen("belly") + L.previewing_belly = null + return + if(!belly_fullscreen) + L.clear_fullscreen("belly") + check_hud_disable(L) + return + + if(colorization_enabled) + var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly, severity) // preserving save data + var/datum/belly_overlays/lookup_belly_path = text2path("/datum/belly_overlays/[lowertext(belly_fullscreen)]") + if(!lookup_belly_path) + var/used_fullscreen = belly_fullscreen + to_chat(owner, span_warning("The belly overlay ([used_fullscreen]) you've selected for [src] no longer exists. Please reselect your overlay.")) + belly_fullscreen = null + log_runtime("Icon datum was not defined for [used_fullscreen]") + + var/alpha = min(belly_fullscreen_alpha, L.max_voreoverlay_alpha) + F.icon = initial(lookup_belly_path.belly_icon) + F.cut_overlays() + var/image/I = image(F.icon, belly_fullscreen) //Would be cool if I could just include color and alpha in the image define so we don't have to copy paste + I.color = belly_fullscreen_color + I.alpha = alpha + F.add_overlay(I) + I = image(F.icon, belly_fullscreen+"-2") + I.color = belly_fullscreen_color2 + I.alpha = alpha + F.add_overlay(I) + I = image(F.icon, belly_fullscreen+"-3") + I.color = belly_fullscreen_color3 + I.alpha = alpha + F.add_overlay(I) + I = image(F.icon, belly_fullscreen+"-4") + I.color = belly_fullscreen_color4 + I.alpha = alpha + F.add_overlay(I) + var/extra_mush = 0 + var/extra_mush_color = mush_color + if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0) + var/mob/living/carbon/human/H = owner + var/datum/reagents/metabolism/ingested = H.ingested + if(ingested && ingested.total_volume > 0) + if(custom_ingested_color) + extra_mush_color = custom_ingested_color + else + extra_mush_color = ingested.get_color() + extra_mush = ingested.total_volume * metabolism_mush_ratio + if(!mush_overlay) + I = get_mush_overlay(extra_mush_color, min(custom_ingested_alpha, L.max_voreoverlay_alpha), max_ingested, ingested.total_volume) + F.add_overlay(I) + if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0)) + I = get_mush_overlay(mush_color, min(mush_alpha, L.max_voreoverlay_alpha), max_mush, owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush) + var/stored_y = I.pixel_y + F.add_overlay(I) + if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0) + var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush + I = get_mush_extra_overlay(extra_mush_color, min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha), stored_y) + F.add_overlay(I) + if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume) + I = get_liquid_overlay() + I.alpha = min(I.alpha, L.max_voreoverlay_alpha) + F.add_overlay(I) + F.update_for_view(L.client.view) + return + + var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly/fixed, severity) //preserving save data + F.icon = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi' + F.cut_overlays() + F.add_overlay(image(F.icon, belly_fullscreen)) + F.add_overlay(image(F.icon, belly_fullscreen+"-2")) + F.add_overlay(image(F.icon, belly_fullscreen+"-3")) + F.add_overlay(image(F.icon, belly_fullscreen+"-4")) + var/image/I + var/extra_mush = 0 + var/extra_mush_color = mush_color + if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0) + var/mob/living/carbon/human/H = owner + var/datum/reagents/metabolism/ingested = H.ingested + if(ingested && ingested.total_volume > 0) + if(custom_ingested_color) + extra_mush_color = custom_ingested_color + else + extra_mush_color = ingested.get_color() + extra_mush = ingested.total_volume * metabolism_mush_ratio + if(!mush_overlay) + I = get_mush_overlay(extra_mush_color, custom_ingested_alpha, max_ingested, ingested.total_volume) + F.add_overlay(I) + if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0)) + I = get_mush_overlay(mush_color, mush_alpha, max_mush, owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush) + I.alpha = mush_alpha + var/stored_y = I.pixel_y + F.add_overlay(I) + if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0) + var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush + I = get_mush_extra_overlay(extra_mush_color, min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha), stored_y) + F.add_overlay(I) + if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume) + I = get_liquid_overlay() + F.add_overlay(I) + F.update_for_view(L.client.view) + check_hud_disable(L) + +/obj/belly/proc/check_hud_disable(var/mob/living/living_prey) + if(disable_hud && living_prey != owner) + if(living_prey?.hud_used?.hud_shown) + to_chat(living_prey, span_vnotice("((Your pred has disabled huds in their belly. Turn off vore FX and hit F12 to get it back; or relax, and enjoy the serenity.))")) + living_prey.toggle_hud_vis(TRUE) + +/obj/belly/proc/get_mush_overlay(color, alpha, limit, content) + var/image/I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") + I.color = color + I.pixel_y = -450 + (450 / max(limit, 1) * max(min(limit, content), 1)) + if(I.pixel_y < -450 + (450 / 100 * min_mush)) + I.pixel_y = -450 + (450 / 100 * min_mush) + I.alpha = alpha + return I + +/obj/belly/proc/get_mush_extra_overlay(color, alpha, stored_y) + var/image/I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") + I.color = color + I.pixel_y = stored_y + I.alpha = alpha + return I + +/obj/belly/proc/get_liquid_overlay() + var/image/I + if(digest_mode == DM_HOLD && item_digest_mode == IM_HOLD) + I = image('icons/mob/vore_fullscreens/bubbles.dmi', "calm") + else + I = image('icons/mob/vore_fullscreens/bubbles.dmi', "bubbles") + if(custom_reagentcolor) + I.color = custom_reagentcolor + else + I.color = reagentcolor + if(custom_reagentalpha) + I.alpha = custom_reagentalpha + else + I.alpha = max(150, min(custom_max_volume, 255)) - (255 - belly_fullscreen_alpha) + I.pixel_y = -450 + min((450 / custom_max_volume * reagents.total_volume), 450 / 100 * max_liquid_level) + return I + +/obj/belly/proc/vore_preview(mob/living/L) + if(!istype(L) || !L.client) + L.previewing_belly = null + return + L.previewing_belly = src + vore_fx(L) + +/obj/belly/proc/clear_preview(mob/living/L) + L.previewing_belly = null + L.clear_fullscreen("belly") diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index fe091d19c8..626e89230c 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -664,181 +664,6 @@ // Note, this should be refactored to drop priority overlays I.add_overlay(I.d_stage_overlay, TRUE) -// SEND_SIGNAL(COMSIG_BELLY_UPDATE_VORE_FX) is sometimes used when calling vore_fx() to send belly visuals -// to certain non-belly atoms. Not called here as vore_fx() is usually only called if a mob is in the belly. -// Don't forget it if you need to rework vore_fx(). -/obj/belly/proc/vore_fx(mob/living/L, var/severity = 0) - if(!istype(L)) - return - if(!L.client) - return - if(L.previewing_belly && L.previewing_belly != src) - return - if(L.previewing_belly == src && L.vore_selected != src) - L.previewing_belly = null - return - if(!L.show_vore_fx) - L.clear_fullscreen("belly") - L.previewing_belly = null - return - if(belly_fullscreen) - if(colorization_enabled) - var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly, severity) // preserving save data - var/datum/belly_overlays/lookup_belly_path = text2path("/datum/belly_overlays/[lowertext(belly_fullscreen)]") - if(!lookup_belly_path) - var/used_fullscreen = belly_fullscreen - to_chat(owner, span_warning("The belly overlay ([used_fullscreen]) you've selected for [src] no longer exists. Please reselect your overlay.")) - belly_fullscreen = null - log_runtime("Icon datum was not defined for [used_fullscreen]") - - var/alpha = min(belly_fullscreen_alpha, L.max_voreoverlay_alpha) - F.icon = initial(lookup_belly_path.belly_icon) - F.cut_overlays() - var/image/I = image(F.icon, belly_fullscreen) //Would be cool if I could just include color and alpha in the image define so we don't have to copy paste - I.color = belly_fullscreen_color - I.alpha = alpha - F.add_overlay(I) - I = image(F.icon, belly_fullscreen+"-2") - I.color = belly_fullscreen_color2 - I.alpha = alpha - F.add_overlay(I) - I = image(F.icon, belly_fullscreen+"-3") - I.color = belly_fullscreen_color3 - I.alpha = alpha - F.add_overlay(I) - I = image(F.icon, belly_fullscreen+"-4") - I.color = belly_fullscreen_color4 - I.alpha = alpha - F.add_overlay(I) - var/extra_mush = 0 - var/extra_mush_color = mush_color - if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0) - var/mob/living/carbon/human/H = owner - var/datum/reagents/metabolism/ingested = H.ingested - if(ingested && ingested.total_volume > 0) - if(custom_ingested_color) - extra_mush_color = custom_ingested_color - else - extra_mush_color = ingested.get_color() - extra_mush = ingested.total_volume * metabolism_mush_ratio - if(!mush_overlay) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = extra_mush_color - I.alpha = min(custom_ingested_alpha, L.max_voreoverlay_alpha) - I.pixel_y = -450 + ((450 / max(max_ingested, 1)) * min(max_ingested, ingested.total_volume)) - F.add_overlay(I) - if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0)) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = mush_color - I.alpha = min(mush_alpha, L.max_voreoverlay_alpha) - var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush - I.pixel_y = -450 + (450 / max(max_mush, 1) * max(min(max_mush, total_mush_content), 1)) - if(I.pixel_y < -450 + (450 / 100 * min_mush)) - I.pixel_y = -450 + (450 / 100 * min_mush) - var/stored_y = I.pixel_y - F.add_overlay(I) - if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = extra_mush_color - I.alpha = min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha) - I.pixel_y = stored_y - F.add_overlay(I) - if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume) - if(digest_mode == DM_HOLD && item_digest_mode == IM_HOLD) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "calm") - else - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "bubbles") - if(custom_reagentcolor) - I.color = custom_reagentcolor - else - I.color = reagentcolor - if(custom_reagentalpha) - I.alpha = custom_reagentalpha - else - I.alpha = max(150, min(custom_max_volume, 255)) - (255 - belly_fullscreen_alpha) - I.pixel_y = -450 + min((450 / custom_max_volume * reagents.total_volume), 450 / 100 * max_liquid_level) - I.alpha = min(I.alpha, L.max_voreoverlay_alpha) - F.add_overlay(I) - F.update_for_view(L.client.view) - else - var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly/fixed, severity) //preserving save data - F.icon = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi' - F.cut_overlays() - F.add_overlay(image(F.icon, belly_fullscreen)) - F.add_overlay(image(F.icon, belly_fullscreen+"-2")) - F.add_overlay(image(F.icon, belly_fullscreen+"-3")) - F.add_overlay(image(F.icon, belly_fullscreen+"-4")) - var/image/I - var/extra_mush = 0 - var/extra_mush_color = mush_color - if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0) - var/mob/living/carbon/human/H = owner - var/datum/reagents/metabolism/ingested = H.ingested - if(ingested && ingested.total_volume > 0) - if(custom_ingested_color) - extra_mush_color = custom_ingested_color - else - extra_mush_color = ingested.get_color() - extra_mush = ingested.total_volume * metabolism_mush_ratio - if(!mush_overlay) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = extra_mush_color - I.alpha = custom_ingested_alpha - I.pixel_y = -450 + (450 / max(max_ingested, 1) * max(min(max_ingested, ingested.total_volume), 1)) - F.add_overlay(I) - if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0)) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = mush_color - I.alpha = mush_alpha - var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush - I.pixel_y = -450 + (450 / max(max_mush, 1) * max(min(max_mush, total_mush_content), 1)) - if(I.pixel_y < -450 + (450 / 100 * min_mush)) - I.pixel_y = -450 + (450 / 100 * min_mush) - var/stored_y = I.pixel_y - F.add_overlay(I) - if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush") - I.color = extra_mush_color - I.alpha = min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha) - I.pixel_y = stored_y - F.add_overlay(I) - if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume) - if(digest_mode == DM_HOLD && item_digest_mode == IM_HOLD) - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "calm") - else - I = image('icons/mob/vore_fullscreens/bubbles.dmi', "bubbles") - if(custom_reagentcolor) - I.color = custom_reagentcolor - else - I.color = reagentcolor - if(custom_reagentalpha) - I.alpha = custom_reagentalpha - else - I.alpha = max(150, min(custom_max_volume, 255)) - (255 - belly_fullscreen_alpha) - I.pixel_y = -450 + min((450 / custom_max_volume * reagents.total_volume), 450 / 100 * max_liquid_level) - F.add_overlay(I) - F.update_for_view(L.client.view) - else - L.clear_fullscreen("belly") - - if(disable_hud && L != owner) - if(L?.hud_used?.hud_shown) - to_chat(L, span_vnotice("((Your pred has disabled huds in their belly. Turn off vore FX and hit F12 to get it back; or relax, and enjoy the serenity.))")) - L.toggle_hud_vis(TRUE) - -/obj/belly/proc/vore_preview(mob/living/L) - if(!istype(L) || !L.client) - L.previewing_belly = null - return - L.previewing_belly = src - vore_fx(L) - -/obj/belly/proc/clear_preview(mob/living/L) - L.previewing_belly = null - L.clear_fullscreen("belly") - - - // Release all contents of this belly into the owning mob's location. // If that location is another mob, contents are transferred into whichever of its bellies the owning mob is in. // Returns the number of mobs so released. @@ -1270,243 +1095,6 @@ /obj/belly/onDropInto(atom/movable/AM) return null -//Handle a mob struggling -// Called from /mob/living/carbon/relaymove() -/obj/belly/proc/relay_resist(mob/living/R, obj/item/C) - if (!(R in contents)) - if(!C) - return // User is not in this belly - - R.setClickCooldown(50) - - var/escape_attempt_owner_message = span_vwarning(belly_format_string(escape_attempt_messages_owner, R)) - var/escape_attempt_prey_message = span_vwarning(belly_format_string(escape_attempt_messages_prey, R)) - var/escape_fail_owner_message = span_vwarning(belly_format_string(escape_fail_messages_owner, R)) - var/escape_fail_prey_message = span_vnotice(belly_format_string(escape_fail_messages_prey, R)) - - if(owner.stat) //If owner is stat (dead, KO) we can actually escape - escape_attempt_prey_message = span_vwarning("[escape_attempt_prey_message] (will take around [escapetime/10] seconds.)") - to_chat(R, escape_attempt_prey_message) - to_chat(owner, escape_attempt_owner_message) - - if(do_after(R, escapetime, owner, target = src, timed_action_flags = IGNORE_INCAPACITATED)) - if((owner.stat || escapable)) //Can still escape? - if(C) - release_specific_contents(C) - return - if(R.loc == src) - release_specific_contents(R) - return - else if(R.loc != src) //Aren't even in the belly. Quietly fail. - return - else //Belly became inescapable or mob revived - to_chat(R, escape_fail_prey_message) - to_chat(owner, escape_fail_owner_message) - return - return - - var/struggle_user_message = span_valert(belly_format_string(struggle_messages_inside, R)) - - if(displayed_message_flags & MS_FLAG_STRUGGLE_OUTSIDE) - var/struggle_outer_message = span_valert(belly_format_string(struggle_messages_outside, R)) - if(private_struggle) - to_chat(owner, struggle_outer_message) - else - for(var/mob/M in hearers(4, owner)) - M.show_message(struggle_outer_message, 2) // hearable - - var/sound/struggle_snuggle - var/sound/struggle_rustle = sound(get_sfx("rustle")) - - if((vore_sprite_flags & DM_FLAG_VORESPRITE_BELLY) && (owner.vore_capacity_ex[belly_sprite_to_affect] >= 1) && !private_struggle && resist_triggers_animation && affects_vore_sprites) - owner.vs_animate(belly_sprite_to_affect) - - if(!private_struggle) - if(is_wet) - if(!fancy_vore) - struggle_snuggle = sound(get_sfx("classic_struggle_sounds")) - else - struggle_snuggle = sound(get_sfx("fancy_prey_struggle")) - playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) - else - playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) - if(prob(belchchance))//Unsure if this should go in escapable or not, leaving it here for now. - owner.emote("belch") - if(escapable) //If the stomach has escapable enabled. - if(prob(escapechance)) //Let's have it check to see if the prey escapes first. - to_chat(R, escape_attempt_prey_message) - to_chat(owner, escape_attempt_owner_message) - if(do_after(R, escapetime, target = src)) - if(escapable && C) - var/escape_item_owner_message = span_vwarning(belly_format_string(escape_item_messages_owner, R, item = C)) - var/escape_item_prey_message = span_vwarning(belly_format_string(escape_item_messages_prey, R, item = C)) - var/escape_item_outside_message = span_vwarning(belly_format_string(escape_item_messages_outside, R, item = C)) - - release_specific_contents(C) - to_chat(R, escape_item_prey_message) - to_chat(owner, escape_item_owner_message) - if(!private_struggle) - for(var/mob/M in hearers(4, owner)) - M.show_message(escape_item_outside_message, 2) - return - if(escapable && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled? - var/escape_owner_message = span_vwarning(belly_format_string(escape_messages_owner, R)) - var/escape_prey_message = span_vwarning(belly_format_string(escape_messages_prey, R)) - var/escape_outside_message = span_vwarning(belly_format_string(escape_messages_outside, R)) - - release_specific_contents(R) - to_chat(R, escape_prey_message) - to_chat(owner, escape_owner_message) - if(!private_struggle) - for(var/mob/M in hearers(4, owner)) - M.show_message(escape_outside_message, 2) - return - else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. - return - else //Belly became inescapable. - to_chat(R, escape_fail_prey_message) - to_chat(owner, escape_fail_owner_message) - return - - else if(prob(transferchance) && transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started. - var/obj/belly/dest_belly - for(var/obj/belly/B as anything in owner.vore_organs) - if(B.name == transferlocation) - dest_belly = B - break - - if(!dest_belly) - to_chat(owner, span_vwarning("Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")) - transferchance = 0 - transferlocation = null - return - var/primary_transfer_owner_message = span_vwarning(belly_format_string(primary_transfer_messages_owner, R, dest = transferlocation)) - var/primary_transfer_prey_message = span_vwarning(belly_format_string(primary_transfer_messages_prey, R, dest = transferlocation)) - - to_chat(R, primary_transfer_prey_message) - to_chat(owner, primary_transfer_owner_message) - if(C) - transfer_contents(C, dest_belly) - return - transfer_contents(R, dest_belly) - return - - else if(prob(transferchance_secondary) && transferlocation_secondary) //After the first potential mess getting into, run the secondary one which might be even bigger of a mess. - var/obj/belly/dest_belly - for(var/obj/belly/B as anything in owner.vore_organs) - if(B.name == transferlocation_secondary) - dest_belly = B - break - - if(!dest_belly) - to_chat(owner, span_vwarning("Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")) - transferchance_secondary = 0 - transferlocation_secondary = null - return - - var/secondary_transfer_owner_message = span_vwarning(belly_format_string(secondary_transfer_messages_owner, R, dest = transferlocation_secondary)) - var/secondary_transfer_prey_message = span_vwarning(belly_format_string(secondary_transfer_messages_prey, R, dest = transferlocation_secondary)) - - to_chat(R, secondary_transfer_prey_message) - to_chat(owner, secondary_transfer_owner_message) - if(C) - transfer_contents(C, dest_belly) - return - transfer_contents(R, dest_belly) - return - - else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance. - var/absorb_chance_owner_message = span_vwarning(belly_format_string(absorb_chance_messages_owner, R)) - var/absorb_chance_prey_message = span_vwarning(belly_format_string(absorb_chance_messages_prey, R)) - - to_chat(R, absorb_chance_prey_message) - to_chat(owner, absorb_chance_owner_message) - digest_mode = DM_ABSORB - return - - else if(prob(digestchance) && digest_mode != DM_DIGEST) //Then, let's see if it should run the digest chance. - var/digest_chance_owner_message = span_vwarning(belly_format_string(digest_chance_messages_owner, R)) - var/digest_chance_prey_message = span_vwarning(belly_format_string(digest_chance_messages_prey, R)) - - to_chat(R, digest_chance_prey_message) - to_chat(owner, digest_chance_owner_message) - digest_mode = DM_DIGEST - return - else if(prob(selectchance) && digest_mode != DM_SELECT) //Finally, let's see if it should run the selective mode chance. - var/select_chance_owner_message = span_vwarning(belly_format_string(select_chance_messages_owner, R)) - var/select_chance_prey_message = span_vwarning(belly_format_string(select_chance_messages_prey, R)) - - to_chat(R, select_chance_prey_message) - to_chat(owner, select_chance_owner_message) - digest_mode = DM_SELECT - - else //Nothing interesting happened. - to_chat(R, struggle_user_message) - to_chat(owner, span_vwarning("Your prey appears to be unable to make any progress in escaping your [lowertext(name)].")) - return - to_chat(R, struggle_user_message) - -/obj/belly/proc/relay_absorbed_resist(mob/living/R) - if (!(R in contents) || !R.absorbed) - return // User is not in this belly or isn't actually absorbed - - R.setClickCooldown(50) - - var/struggle_user_message = span_valert(belly_format_string(absorbed_struggle_messages_inside, R, use_absorbed_count = TRUE)) - - if(displayed_message_flags & MS_FLAG_STRUGGLE_ABSORBED_OUTSIDE) - var/struggle_outer_message = span_valert(belly_format_string(absorbed_struggle_messages_outside, R, use_absorbed_count = TRUE)) - if(private_struggle) - to_chat(owner, struggle_outer_message) - else - for(var/mob/M in hearers(4, owner)) - M.show_message(struggle_outer_message, 2) // hearable - - var/sound/struggle_snuggle - var/sound/struggle_rustle = sound(get_sfx("rustle")) - - if(!private_struggle) - if(is_wet) - if(!fancy_vore) - struggle_snuggle = sound(get_sfx("classic_struggle_sounds")) - else - struggle_snuggle = sound(get_sfx("fancy_prey_struggle")) - playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) - else - playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE) - - //absorb resists - if(escapable || owner.stat) //If the stomach has escapable enabled or the owner is dead/unconscious - if(prob(escapechance) || owner.stat) //Let's have it check to see if the prey's escape attempt starts. - var/escape_attempt_absorbed_owner_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_owner, R)) - var/escape_attempt_absorbed_prey_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_prey, R)) - - to_chat(R, escape_attempt_absorbed_prey_message) - to_chat(owner, escape_attempt_absorbed_owner_message) - if(do_after(R, escapetime, target = src)) - if((escapable || owner.stat) && (R.loc == src) && prob(escapechance_absorbed)) //Does the escape attempt succeed? - var/escape_absorbed_owner_message = span_vwarning(belly_format_string(escape_absorbed_messages_owner, R)) - var/escape_absorbed_prey_message = span_vwarning(belly_format_string(escape_absorbed_messages_prey, R)) - var/escape_absorbed_outside_message = span_vwarning(belly_format_string(escape_absorbed_messages_outside, R)) - - release_specific_contents(R) - to_chat(R, escape_absorbed_prey_message) - to_chat(owner, escape_absorbed_owner_message) - if(!private_struggle) - for(var/mob/M in hearers(4, owner)) - M.show_message(escape_absorbed_outside_message, 2) - return - else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. - return - else //Belly became inescapable or you failed your roll. - var/escape_fail_absorbed_owner_message = span_vwarning(belly_format_string(escape_fail_absorbed_messages_owner, R)) - var/escape_fail_absorbed_prey_message = span_vnotice(belly_format_string(escape_fail_absorbed_messages_prey, R)) - - to_chat(R, escape_fail_absorbed_prey_message) - to_chat(owner, escape_fail_absorbed_owner_message) - return - to_chat(R, struggle_user_message) - /obj/belly/proc/get_mobs_and_objs_in_belly() var/list/see = list() var/list/belly_mobs = list() diff --git a/vorestation.dme b/vorestation.dme index d4170ca9bb..708c3f5f93 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -5002,6 +5002,8 @@ #include "code\modules\vore\eating\belly_import.dm" #include "code\modules\vore\eating\belly_messages.dm" #include "code\modules\vore\eating\belly_obj_liquids.dm" +#include "code\modules\vore\eating\belly_obj_resist.dm" +#include "code\modules\vore\eating\belly_obj_vfx.dm" #include "code\modules\vore\eating\belly_obj_vr.dm" #include "code\modules\vore\eating\bellymodes_datum_vr.dm" #include "code\modules\vore\eating\bellymodes_vr.dm"