From a0e66075a6549d0bd4dbd4aece186166e53da495 Mon Sep 17 00:00:00 2001 From: Cameron Lennox Date: Fri, 15 Aug 2025 20:54:27 -0400 Subject: [PATCH] Refactors vore code to allow for instant-vore that does not sleep (#18219) Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> --- code/game/objects/buckling.dm | 2 +- .../structures/crates_lockers/__closets.dm | 3 +- .../species/station/protean/protean_powers.dm | 2 +- .../animal/alien animals/space_mouse.dm | 4 + .../subtypes/animal/alien animals/stardog.dm | 4 + .../subtypes/animal/alien animals/teppi.dm | 34 +++- .../living/simple_mob/subtypes/vore/plants.dm | 2 +- code/modules/vore/eating/living_vr.dm | 114 +---------- code/modules/vore/eating/simple_animal_vr.dm | 5 + code/modules/vore/eating/slipvore_vr.dm | 4 +- code/modules/vore/eating/stumblevore_vr.dm | 4 +- code/modules/vore/eating/vore_procs.dm | 189 ++++++++++++++++++ vorestation.dme | 1 + 13 files changed, 237 insertions(+), 131 deletions(-) create mode 100644 code/modules/vore/eating/vore_procs.dm diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 9320b64701..9ba15be0e4 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -135,7 +135,7 @@ M.visible_message(span_warning("[M.name] sits down on [L.name]!")) else M.visible_message(span_warning("[M.name] is forced to sit down on [L.name] by [user.name]!")) - M.perform_the_nom(user, L, M, M.vore_selected, -1) + M.begin_instant_nom(user, L, M, M.vore_selected) add_fingerprint(user) // unbuckle_mob() diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm index f59e872dd5..835081581a 100644 --- a/code/game/objects/structures/crates_lockers/__closets.dm +++ b/code/game/objects/structures/crates_lockers/__closets.dm @@ -587,4 +587,5 @@ playsound(src, vore_sound, 25) var/mob/living/M = usr - M.perform_the_nom(usr,target,usr,usr.vore_selected,-1) + if(isliving(M)) + M.begin_instant_nom(M,target,M,M.vore_selected) diff --git a/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm b/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm index 2b6c3534f7..0d6fb24013 100644 --- a/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm @@ -343,7 +343,7 @@ m.drop_from_inventory(S.OurRig) if(wearer && devour) //We're being worn. Engulf em', if prefs align.. otherwise just drop off. if(P.can_be_drop_pred && wearer.devourable && wearer.can_be_drop_prey && P.vore_selected) - perform_the_nom(P,wearer,P,P.vore_selected,-1) + begin_instant_nom(P,wearer,P,P.vore_selected) else to_chat(P, span_vwarning("You can't assimilate your current host.")) P.forceMove(get_turf(S.OurRig)) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm index 85140c8c89..129999c3f0 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm @@ -84,6 +84,10 @@ . = ..() movement_cooldown = 10 +/mob/living/simple_mob/vore/alienanimals/dustjumper/begin_instant_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + . = ..() + movement_cooldown = 10 + /datum/ai_holder/simple_mob/melee/evasive/dustjumper hostile = FALSE retaliate = TRUE diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm index b5eab2ac09..cf4c23a292 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm @@ -152,6 +152,10 @@ return //If it can do normal vore mechanics, it can carry players to the OM, //and release them there. I think that's probably a bad idea. +/mob/living/simple_mob/vore/overmap/stardog/begin_instant_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + to_chat(src, span_warning("You can't do that.")) + return + /mob/living/simple_mob/vore/overmap/stardog/Initialize(mapload) . = ..() child_om_marker.set_light(5, 1, "#ff8df5") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm index f5caa00f4f..7acfe1e220 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm @@ -813,24 +813,38 @@ GLOBAL_VAR_INIT(teppi_count, 0) // How mant teppi DO we have? /mob/living/simple_mob/vore/alienanimals/teppi/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay_time) + if(!client) + var/teppi_checks = teppi_checks(user, prey, pred, belly) + if(teppi_checks) + belly = teppi_checks + ai_holder.set_busy(TRUE) + prey.stop_pulling() + ..() + if(!client) + ai_holder.set_busy(FALSE) + +/mob/living/simple_mob/vore/alienanimals/teppi/begin_instant_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + if(!client) + var/teppi_checks = teppi_checks(user, prey, pred, belly) + if(teppi_checks) + belly = teppi_checks + ai_holder.set_busy(TRUE) + prey.stop_pulling() + ..() + if(!client) + ai_holder.set_busy(FALSE) + +///Retrns the belly we'll be using if we are friends. +/mob/living/simple_mob/vore/alienanimals/teppi/proc/teppi_checks(mob/living/user, mob/living/prey, mob/living/pred) if(!pred) pred = user - if(client) - return ..() var/current_affinity = affinity[prey.real_name] - ai_holder.set_busy(TRUE) - prey.stop_pulling() if(current_affinity >= 50) - belly = friend_zone - ..() - ai_holder.set_busy(FALSE) - return + return friend_zone if(current_affinity <= -50) vore_selected.digest_mode = DM_DIGEST else vore_selected.digest_mode = DM_DRAIN - ..() - ai_holder.set_busy(FALSE) //Instead of copying this everywhere let's just make a proc /mob/living/simple_mob/vore/alienanimals/teppi/proc/lets_eat(person) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm b/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm index 4c8682a3b2..543f07868d 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm @@ -77,7 +77,7 @@ if(L in eaten_mobs) return if(L.devourable && L.allowmobvore && (src.vore_fullness < src.vore_capacity)) - perform_the_nom(src,L,src,src.vore_selected,-1) + begin_instant_nom(src,L,src,src.vore_selected) eaten_mobs += L diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 4def73d252..a52cb6e0e9 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -678,118 +678,6 @@ var/belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.feedable_bellies()) return perform_the_nom(user, prey, pred, belly) -// -// Master vore proc that actually does vore procedures -// -/mob/living/proc/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay_time) - //Sanity - if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs)) - log_debug("[user] attempted to feed [prey] to [pred], via [belly ? lowertext(belly.name) : "*null*"] but it went wrong.") - return FALSE - if(pred == prey) - return FALSE - - // The belly selected at the time of noms - var/attempt_msg = "ERROR: Vore message couldn't be created. Notify a dev. (at)" - var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)" - - //Final distance check. Time has passed, menus have come and gone. Can't use do_after adjacent because doesn't behave for held micros - var/user_to_pred = get_dist(get_turf(user),get_turf(pred)) - var/user_to_prey = get_dist(get_turf(user),get_turf(prey)) - - if(user == pred && isAI(user)) - var/mob/living/silicon/ai/AI = user - if(AI.holo && AI.holo.masters[AI]) - user_to_prey = get_dist(get_turf(AI.holo.masters[AI]), get_turf(prey)) - - if(user_to_pred > 1 || user_to_prey > 1) - return FALSE - - if(!prey.devourable) - to_chat(user, span_vnotice("They aren't able to be devoured.")) - log_and_message_admins("attempted to devour [key_name_admin(prey)] against their prefs ([prey ? ADMIN_JMP(prey) : "null"])", src) - return FALSE - if(prey.absorbed || pred.absorbed) - to_chat(user, span_vwarning("They aren't aren't in a state to be devoured.")) - return FALSE - - //Determining vore attempt privacy - var/message_range = world.view - if(!pred.is_slipping && !prey.is_slipping) //We only care about privacy preference if it's NOT a spontaneous vore. - switch(belly.eating_privacy_local) //if("loud") case not added, as it would not modify message_range - if("default") - if(pred.eating_privacy_global) - message_range = 1 - if("subtle") - message_range = 1 - - // Prepare messages - if(prey.is_slipping) - attempt_msg = span_vwarning("It seems like [prey] is about to slide into [pred]'s [lowertext(belly.name)]!") - success_msg = span_vwarning("[prey] suddenly slides into [pred]'s [lowertext(belly.name)]!") - else if(pred.is_slipping) - attempt_msg = span_vwarning("It seems like [prey] is gonna end up inside [pred]'s [lowertext(belly.name)] as [pred] comes sliding over!") - success_msg = span_vwarning("[prey] suddenly slips inside of [pred]'s [lowertext(belly.name)] as [pred] slides into them!") - else if(user == pred) //Feeding someone to yourself - attempt_msg = span_vwarning("[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") - success_msg = span_vwarning("[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") - else //Feeding someone to another person - attempt_msg = span_vwarning("[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") - success_msg = span_vwarning("[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") - - // Announce that we start the attempt! - - user.visible_message(attempt_msg, range = message_range) - - // Now give the prey time to escape... return if they did - var/swallow_time - if(delay_time < 0) - swallow_time = 0 //No delay! - else if(delay_time) - swallow_time = delay_time - else - swallow_time = ishuman(prey) ? belly.human_prey_swallow_time : belly.nonhuman_prey_swallow_time - - // Their AI should get notified so they can stab us - prey.ai_holder?.react_to_attack(user) - - //Timer and progress bar - if(!user.client && prey.weakened > 0) // stop crwaling instantly break swallow attempt for mobvore - prey.Stun(min(prey.weakened, 2)) // stop crwaling instantly break swallow attempt for mobvore - if(!do_after(user, swallow_time, prey, exclusive = TASK_USER_EXCLUSIVE)) - return FALSE // Prey escaped (or user disabled) before timer expired. - - // If we got this far, nom successful! Announce it! - user.visible_message(success_msg, range = message_range) - - // Actually shove prey into the belly. - if(istype(prey.loc, /obj/item/holder)) - var/obj/item/holder/H = prey.loc - for(var/mob/living/M in H.contents) - belly.nom_mob(M, user) - if(M.loc == H) // In case nom_mob failed somehow. - M.forceMove(get_turf(src)) - H.held_mob = null - qdel(H) - else - belly.nom_mob(prey, user) - - user.update_icon() - - var/mob/living/carbon/victim = prey // Check for afk vore - if(istype(victim) && !victim.client && !victim.ai_holder && victim.ckey) - log_and_message_admins("ate [key_name_admin(prey)] whilst the prey was AFK ([pred ? ADMIN_JMP(pred) : "null"])", pred) - var/mob/living/carbon/victim_pred = pred // Check for afk vore - if(istype(victim_pred) && !victim_pred.client && !victim_pred.ai_holder && victim_pred.ckey) - log_and_message_admins("ate [key_name_admin(prey)] whilst the pred was AFK ([pred ? ADMIN_JMP(pred) : "null"])", pred) - - // Inform Admins - if(pred == user) - add_attack_logs(pred, prey, "Eaten via [belly.name]") - else - add_attack_logs(user, pred, "Forced to eat [key_name(prey)]") - return TRUE - // // Magical pred-air breathing for inside preds // overrides a proc defined on atom called by breathe.dm @@ -869,7 +757,7 @@ if(user.is_incorporeal()) return FALSE var/belly = user.vore_selected - return perform_the_nom(user, prey, user, belly, -1) + return begin_instant_nom(user, prey, user, belly) /mob/living/proc/glow_toggle() set name = "Glow (Toggle)" diff --git a/code/modules/vore/eating/simple_animal_vr.dm b/code/modules/vore/eating/simple_animal_vr.dm index 578401ffdb..8f37288e05 100644 --- a/code/modules/vore/eating/simple_animal_vr.dm +++ b/code/modules/vore/eating/simple_animal_vr.dm @@ -37,6 +37,11 @@ belly = vore_selected return ..() +/mob/living/simple_mob/begin_instant_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + if(vore_active && !voremob_loaded && pred == src) //Only init your own bellies. + init_vore(TRUE) + belly = vore_selected + return ..() // // Simple proc for animals to have their digestion toggled on/off externally // Added as a verb in /mob/living/simple_mob/init_vore() if vore is enabled for this mob. diff --git a/code/modules/vore/eating/slipvore_vr.dm b/code/modules/vore/eating/slipvore_vr.dm index 73e3c31480..26557862d6 100644 --- a/code/modules/vore/eating/slipvore_vr.dm +++ b/code/modules/vore/eating/slipvore_vr.dm @@ -48,12 +48,12 @@ var/mob/living/target = AM if(istype(target) && !target.is_incorporeal() && !src.is_incorporeal()) //The slip vore begins if(can_slip_vore(target) && !src.slip_vore_in_progress && !target.slip_vore_in_progress) //If we can vore them go for it - perform_the_nom(src,target,src,src.vore_selected,-1) + begin_instant_nom(src,target,src,src.vore_selected) target.slip_vore_in_progress = FALSE target.is_slipping = FALSE return else if(can_be_slip_vored_by(target) && !src.slip_vore_in_progress && !target.slip_vore_in_progress) //Otherwise, if they can vore us, make it happen. - perform_the_nom(target,src,target,target.vore_selected,-1) + begin_instant_nom(target,src,target,target.vore_selected) slip_vore_in_progress = FALSE is_slipping = FALSE return diff --git a/code/modules/vore/eating/stumblevore_vr.dm b/code/modules/vore/eating/stumblevore_vr.dm index dcc65c2e39..1ebdf226d9 100644 --- a/code/modules/vore/eating/stumblevore_vr.dm +++ b/code/modules/vore/eating/stumblevore_vr.dm @@ -38,13 +38,13 @@ if(CanStumbleVore(M)) //This is if the person stumbling into us is able to eat us! visible_message(span_vwarning("[M] flops carelessly into [src]!")) M.forceMove(get_turf(src)) - perform_the_nom(src,M,src,src.vore_selected,-1) + begin_instant_nom(src,M,src,src.vore_selected) return if(M.CanStumbleVore(src)) //This is if the person stumbling into us is able to be eaten by us! BROKEN! visible_message(span_vwarning("[M] flops carelessly into [src]!")) M.forceMove(get_turf(src)) - perform_the_nom(M,src,M,M.vore_selected,-1) + begin_instant_nom(M,src,M,M.vore_selected) return if(istype(S) && S.species.lightweight == 1) diff --git a/code/modules/vore/eating/vore_procs.dm b/code/modules/vore/eating/vore_procs.dm new file mode 100644 index 0000000000..bf6fdab893 --- /dev/null +++ b/code/modules/vore/eating/vore_procs.dm @@ -0,0 +1,189 @@ +//Vore procs! Can be delayed or instant. +//If delayed, the chain is: perform_the_nom -> begin_delayed_nom -> vore_sanity_checks -> attempt_to_devour_prey -> devour_and_move_prey +//If instant, the chain is: perform_the_nom -> begin_instant_nom -> vore_sanity_checks -> devour_and_move_prey + + + +/** + * Vore proc that actually does the main part of eating + * Written to be compatible with instant or delayed noms. Alternatively, call begin_instant_nom if the vore is going to be instant. + * Params: user, prey, pred, belly, delay_time + */ +/mob/living/proc/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay_time) + if(!delay_time || delay_time > 0) + return begin_delayed_nom(user, prey, pred, belly, delay_time) + else //This is here to catch when delay_time is set to a negative number, aka, 'we want this to be instant.' Any uses of this should be replaced by begin_instant_nom + return begin_instant_nom(user, prey, pred, belly) + +/** + * Vore proc that actually does the main part of eating + * Params: user, prey, pred, belly, delay_time + */ +/proc/begin_delayed_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay_time) + if(vore_sanity_checks(user, prey, pred, belly)) + return attempt_to_devour_prey(user, prey, pred, belly, delay_time) + else + return FALSE + +/** + * Vore proc that actually tries to instantly eat the preey + * Params: user, prey, pred, belly + * NOTE: THIS MUST NOT SLEEP, THIS IS CALLED BY THINGS THAT USE SIGNAL_HANDLER + */ +/mob/living/proc/begin_instant_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + SHOULD_NOT_SLEEP(TRUE) + if(vore_sanity_checks(user, prey, pred, belly)) + return devour_and_move_prey(user, prey, pred, belly) + else + return FALSE //We failed + +/proc/attempt_to_devour_prey(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay_time) + var/message_range = get_vore_message_range(user, pred, prey, belly) + var/attempt_msg = generate_vore_attempt_message(user, prey, pred, belly) + // Announce that we start the attempt! + user.visible_message(attempt_msg, range = message_range) + // Now give the prey time to escape... return if they did + var/swallow_time + if(delay_time < 0) //Shouldn't happen, but let's just be sane.. + swallow_time = 0 + else if(delay_time) + swallow_time = delay_time + else + swallow_time = ishuman(prey) ? belly.human_prey_swallow_time : belly.nonhuman_prey_swallow_time + + // Their AI should get notified so they can stab us + prey.ai_holder?.react_to_attack(user) + + //Timer and progress bar + if(!user.client && prey.weakened > 0) // stop crwaling instantly break swallow attempt for mobvore + prey.Stun(min(prey.weakened, 2)) // stop crawling instantly break swallow attempt for mobvore + if(!do_after(user, swallow_time, prey, exclusive = TASK_USER_EXCLUSIVE)) + return FALSE // Prey escaped (or user disabled) before timer expired. + + // If we got this far, nom successful! Announce it and move the prey! + return devour_and_move_prey(user, prey, pred, belly, message_range) + +/proc/devour_and_move_prey(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, message_range) + var/success_msg = generate_vore_success_message(user, prey, pred, belly) + if(!message_range) + message_range = get_vore_message_range(user, pred, prey, belly) + user.visible_message(success_msg, range = message_range) + // Actually shove prey into the belly. + if(istype(prey.loc, /obj/item/holder)) + var/obj/item/holder/H = prey.loc + for(var/mob/living/M in H.contents) + belly.nom_mob(M, user) + if(M.loc == H) // In case nom_mob failed somehow. + M.forceMove(get_turf(user)) + H.held_mob = null + qdel(H) + else + belly.nom_mob(prey, user) + + user.update_icon() + + var/mob/living/carbon/victim = prey // Check for afk vore + if(istype(victim) && !victim.client && !victim.ai_holder && victim.ckey) + log_and_message_admins("ate [key_name_admin(prey)] whilst the prey was AFK ([pred ? ADMIN_JMP(pred) : "null"])", pred) + var/mob/living/carbon/victim_pred = pred // Check for afk vore + if(istype(victim_pred) && !victim_pred.client && !victim_pred.ai_holder && victim_pred.ckey) + log_and_message_admins("ate [key_name_admin(prey)] whilst the pred was AFK ([pred ? ADMIN_JMP(pred) : "null"])", pred) + + // Inform Admins + if(pred == user) + add_attack_logs(pred, prey, "Eaten via [belly.name]") + else + add_attack_logs(user, pred, "Forced to eat [key_name(prey)]") + return TRUE + +///VORE HELPER PROCS UNDER HERE + +/** + * Vore helper proc that creates the vore success message we'll be using + * Params: user, prey, pred, belly, delay_time + * Returns: success_msg + */ +/proc/generate_vore_success_message(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + //Determining vore attempt privacy + var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)" + + if(prey.is_slipping) + success_msg = span_vwarning("[prey] suddenly slides into [pred]'s [lowertext(belly.name)]!") + else if(pred.is_slipping) + success_msg = span_vwarning("[prey] suddenly slips inside of [pred]'s [lowertext(belly.name)] as [pred] slides into them!") + else if(user == pred) //Feeding someone to yourself + success_msg = span_vwarning("[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") + else //Feeding someone to another person + success_msg = span_vwarning("[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") + return success_msg + +/** + * Vore proc helper that creates the vore attempt message we'll be using + * Params: user, prey, pred, belly, delay_time + * Returns: attempt_msg + */ +/proc/generate_vore_attempt_message(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + //Determining vore attempt privacy + var/attempt_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)" + + if(prey.is_slipping) + attempt_msg = span_vwarning("It seems like [prey] is about to slide into [pred]'s [lowertext(belly.name)]!") + else if(pred.is_slipping) + attempt_msg = span_vwarning("It seems like [prey] is gonna end up inside [pred]'s [lowertext(belly.name)] as [pred] comes sliding over!") + else if(user == pred) //Feeding someone to yourself + attempt_msg = span_vwarning("[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") + else //Feeding someone to another person + attempt_msg = span_vwarning("[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!") + return attempt_msg + +/** + * Vore proc helper that finds what range our message should be + * Params: user, prey, pred, belly, delay_time + * Returns: attempt_msg + */ +/proc/get_vore_message_range(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + var/message_range = world.view + if(!pred.is_slipping && !prey.is_slipping) //We only care about privacy preference if it's NOT a spontaneous vore. + switch(belly.eating_privacy_local) //if("loud") case not added, as it would not modify message_range + if("default") + if(pred.eating_privacy_global) + message_range = 1 + if("subtle") + message_range = 1 + return message_range + +/** + * Vore proc helper that sees if we can actually do the vore attempt + * Params: user, prey, pred, belly + * Returns: TRUE/FALSE + * FALSE: Can not eat. + * TRUE: Can eat. + */ +/proc/vore_sanity_checks(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly) + //Sanity + if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs)) + log_debug("[user] attempted to feed [prey] to [pred], via [belly ? lowertext(belly.name) : "*null*"] but it went wrong.") + return FALSE + if(pred == prey) + return FALSE + + //Final distance check. Time has passed, menus have come and gone. Can't use do_after adjacent because doesn't behave for held micros + var/user_to_pred = get_dist(get_turf(user),get_turf(pred)) + var/user_to_prey = get_dist(get_turf(user),get_turf(prey)) + + if(user == pred && isAI(user)) + var/mob/living/silicon/ai/AI = user + if(AI.holo && AI.holo.masters[AI]) + user_to_prey = get_dist(get_turf(AI.holo.masters[AI]), get_turf(prey)) + + if(user_to_pred > 1 || user_to_prey > 1) + return FALSE + + if(!prey.devourable) + to_chat(user, span_vnotice("They aren't able to be devoured.")) + log_and_message_admins("attempted to devour [key_name_admin(prey)] against their prefs ([prey ? ADMIN_JMP(prey) : "null"])", user) + return FALSE + if(prey.absorbed || pred.absorbed) + to_chat(user, span_vwarning("They aren't aren't in a state to be devoured.")) + return FALSE + return TRUE diff --git a/vorestation.dme b/vorestation.dme index f7824d1fae..49b9388e0c 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -4546,6 +4546,7 @@ #include "code\modules\vore\eating\stumblevore_vr.dm" #include "code\modules\vore\eating\transforming_vr.dm" #include "code\modules\vore\eating\vertical_nom_vr.dm" +#include "code\modules\vore\eating\vore_procs.dm" #include "code\modules\vore\eating\vore_vr.dm" #include "code\modules\vore\eating\vorepanel_vr.dm" #include "code\modules\vore\eating\panel_databackend\vorepanel_pref_data.dm"