From 5f520271bea442703de880d14ce51da66a52dfd8 Mon Sep 17 00:00:00 2001 From: SatinIsle <98125273+SatinIsle@users.noreply.github.com> Date: Sun, 31 Mar 2024 10:03:47 +0100 Subject: [PATCH] Added Post-Drain belly modes (#15876) * Added Post-Drain belly modes Added "Drain Finishing Modes" that kick into effect once a drain belly has extracted all of the nutrition that it can out of a prey character. These modes are currently: Normal: Current behaviour, just stops when it runs out of nutrition to extract. Sleep: Slowly increases the prey's tiredness until the fall asleep. Be warned that they won't be able to post or see posts when they fall asleep. False Sleep: Slowly increases the prey's tiredness until just before they fall asleep, darkening their screen but NOT preventing them from posting and reading posts. Weight Drain: You're done draining their nutrition? Well, time to start taking their weight directly and adding it to your own body. Is dependent on the prey's weight loss % chosen in character setup. * Added a knockout process option * I forgot eject all on the previous commit * Update tgui.bundle.js --- code/__defines/belly_modes_vr.dm | 6 ++++++ code/modules/mob/living/carbon/human/life.dm | 20 +++++++++++++++++++ code/modules/mob/living/living_defines.dm | 1 + code/modules/vore/eating/belly_obj_vr.dm | 12 +++++++++++ code/modules/vore/eating/bellymodes_vr.dm | 14 +++++++++++++ code/modules/vore/eating/living_vr.dm | 1 + code/modules/vore/eating/vorepanel_vr.dm | 21 ++++++++++++++++++++ tgui/packages/tgui/interfaces/VorePanel.jsx | 7 +++++++ tgui/public/tgui.bundle.css | 4 ++-- tgui/public/tgui.bundle.js | 14 ++++++------- 10 files changed, 91 insertions(+), 9 deletions(-) diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm index c86e66f1c0..35c8425640 100644 --- a/code/__defines/belly_modes_vr.dm +++ b/code/__defines/belly_modes_vr.dm @@ -36,3 +36,9 @@ #define MIN_NUTRITION_TO_GAIN 450 // Above this amount you will gain weight #define MAX_NUTRITION_TO_LOSE 50 // Below this amount you will lose weight // #define WEIGHT_PER_NUTRITION 0.0285 // Tuned so 1050 (nutrition for average mob) = 30 lbs + +// Drain modes +#define DR_NORMAL "Normal" +#define DR_SLEEP "Sleep" +#define DR_FAKE "False Sleep" +#define DR_WEIGHT "Weight Drain" diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index a5c9448032..5697f004e0 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1245,6 +1245,11 @@ Paralyse(10) setHalLoss(species.total_health - 1) + if(tiredness) //tiredness for vore drain + tiredness = (tiredness - 1) + if(tiredness >= 100) + Sleeping(5) + if(paralysis || sleeping) blinded = 1 set_stat(UNCONSCIOUS) @@ -1429,6 +1434,21 @@ else clear_fullscreen("brute") + //tiredness for drain vore + if(tiredness) + var/severity = 0 + switch(tiredness) + if(10 to 20) severity = 1 + if(20 to 30) severity = 2 + if(30 to 45) severity = 3 + if(45 to 60) severity = 4 + if(60 to 75) severity = 5 + if(75 to 90) severity = 6 + if(90 to INFINITY) severity = 7 + overlay_fullscreen("tired", /obj/screen/fullscreen/oxy, severity) + else + clear_fullscreen("tired") + if(healths) if (chem_effects[CE_PAINKILLER] > 100) healths.icon_state = "health_numb" diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 7bdb20349d..6635200baa 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -82,3 +82,4 @@ var/inventory_panel_type = /datum/inventory_panel var/datum/inventory_panel/inventory_panel var/last_resist_time = 0 // world.time of the most recent resist that wasn't on cooldown. + var/tiredness = 0 //For vore draining diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index b147915454..690f03c08a 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -71,6 +71,8 @@ var/tmp/static/list/mode_flag_list = list("Numbing" = DM_FLAG_NUMBING, "Stripping" = DM_FLAG_STRIPPING, "Leave Remains" = DM_FLAG_LEAVEREMAINS, "Muffles" = DM_FLAG_THICKBELLY, "Affect Worn Items" = DM_FLAG_AFFECTWORN, "Jams Sensors" = DM_FLAG_JAMSENSORS, "Complete Absorb" = DM_FLAG_FORCEPSAY) //Item related modes var/tmp/static/list/item_digest_modes = list(IM_HOLD,IM_DIGEST_FOOD,IM_DIGEST) + //drain modes + var/tmp/static/list/drainmodes = list(DR_NORMAL,DR_SLEEP,DR_FAKE,DR_WEIGHT) //List of slots that stripping handles strips var/tmp/static/list/slots = list(slot_back,slot_handcuffed,slot_l_store,slot_r_store,slot_wear_mask,slot_l_hand,slot_r_hand,slot_wear_id,slot_glasses,slot_gloves,slot_head,slot_shoes,slot_belt,slot_wear_suit,slot_w_uniform,slot_s_store,slot_l_ear,slot_r_ear) @@ -79,6 +81,7 @@ var/tmp/digest_mode = DM_HOLD // Current mode the belly is set to from digest_modes (+transform_modes if human) var/tmp/list/items_preserved = list() // Stuff that wont digest so we shouldn't process it again. var/tmp/recent_sound = FALSE // Prevent audio spam + var/tmp/drainmode = DR_NORMAL // Simply drains the prey then does nothing. // Don't forget to watch your commas at the end of each line if you change these. var/list/struggle_messages_outside = list( @@ -339,6 +342,7 @@ "belly_mob_mult", "belly_item_mult", "belly_overall_mult", + "drainmode", ) if (save_digest_mode == 1) @@ -525,6 +529,8 @@ for(var/atom/movable/AM as anything in contents) if(isliving(AM)) var/mob/living/L = AM + if(L.stat) + L.SetSleeping(min(L.sleeping,20)) if(L.absorbed && !include_absorbed) continue count += release_specific_contents(AM, silent = TRUE) @@ -610,6 +616,12 @@ absorbed_count++ Pred.bloodstr.trans_to(Prey, Pred.reagents.total_volume / absorbed_count) + //Makes it so that if prey are heavily asleep, they will wake up shortly after release + if(isliving(M)) + var/mob/living/ML = M + if(ML.stat) + ML.SetSleeping(min(ML.sleeping,20)) + //Clean up our own business if(!ishuman(owner)) owner.update_icons() diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index e7548f6b89..20300924a2 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -301,6 +301,20 @@ owner.adjust_nutrition((nutrition_percent / 100) * compensation * 4.5 * personal_nutrition_modifier * pred_digestion_efficiency) /obj/belly/proc/steal_nutrition(mob/living/L) + if(L.nutrition <= 110) + if(drainmode == DR_SLEEP && istype(L,/mob/living/carbon/human)) //Slowly put prey to sleep + if(L.tiredness <= 105) + L.tiredness = (L.tiredness + 6) + if(L.tiredness <= 90 && L.tiredness >= 75) + to_chat(L, "You are about to fall unconscious!") + to_chat(owner, "[L] is about to fall unconscious!") + if(drainmode == DR_FAKE && istype(L,/mob/living/carbon/human)) //Slowly bring prey to the edge of sleep without crossing it + if(L.tiredness <= 93) + L.tiredness = (L.tiredness + 6) + if(drainmode == DR_WEIGHT && istype(L,/mob/living/carbon/human)) //Slowly drain your prey's weight and add it to your own + if(L.weight > 70) + L.weight -= (0.01 * L.weight_loss) + owner.weight += (0.01 * L.weight_loss) //intentionally dependant on the prey's weight loss ratio rather than the preds weight gain to keep them in pace with one another. if(L.nutrition >= 100) var/oldnutrition = (L.nutrition * 0.05) L.nutrition = (L.nutrition * 0.95) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index d8272c486f..34b87cbb58 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -447,6 +447,7 @@ absorbed = FALSE //Make sure we're not absorbed muffled = FALSE //Removes Muffling forceMove(get_turf(src)) //Just move me up to the turf, let's not cascade through bellies, there's been a problem, let's just leave. + SetSleeping(0) //Wake up instantly if asleep for(var/mob/living/simple_mob/SA in range(10)) LAZYSET(SA.prey_excludes, src, world.time) log_and_message_admins("[key_name(src)] used the OOC escape button to get out of [key_name(B.owner)] ([B.owner ? "JMP" : "null"])") diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 634072c453..9703b537e3 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -225,6 +225,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", "belly_mob_mult" = selected.belly_mob_mult, "belly_item_mult" = selected.belly_item_mult, "belly_overall_mult" = selected.belly_overall_mult, + "drainmode" = selected.drainmode, ) @@ -823,6 +824,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", if(ourtarget.absorbable) process_options += "Absorb" + process_options += "Knockout" //Can't think of any mechanical prefs that would restrict this. Even if they are already asleep, you may want to make it permanent. + if(process_options.len) process_options += "Cancel" else @@ -878,6 +881,16 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", var/n = 0 - ourtarget.nutrition ourtarget.adjust_nutrition(n) b.absorb_living(ourtarget) + if("Knockout") + if(tgui_alert(ourtarget, "\The [usr] is attempting to instantly make you unconscious, you will be unable until ejected from the pred. Is this something you are okay with happening to you?","Instant Knockout", list("No", "Yes")) != "Yes") + to_chat(usr, "\The [ourtarget] declined your knockout attempt.") + to_chat(ourtarget, "You declined the knockout attempt.") + return + if(ourtarget.loc != b) + to_chat(usr, "\The [ourtarget] is no longer in \the [b].") + return + ourtarget.AdjustSleeping(500000) + to_chat(ourtarget, "\The [usr] has put you to sleep, you will remain unconscious until ejected from the belly.") if("Cancel") return if("Health Check") @@ -1502,6 +1515,14 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", var/new_new_damage = CLAMP(new_damage, 0, 6) host.vore_selected.digest_clone = new_new_damage . = TRUE + if("b_drainmode") + var/list/menu_list = host.vore_selected.drainmodes.Copy() + var/new_drainmode = tgui_input_list(usr, "Choose Mode (currently [host.vore_selected.digest_mode])", "Mode Choice", menu_list) + if(!new_drainmode) + return FALSE + + host.vore_selected.drainmode = new_drainmode + host.vore_selected.updateVRPanels() if("b_emoteactive") host.vore_selected.emote_active = !host.vore_selected.emote_active . = TRUE diff --git a/tgui/packages/tgui/interfaces/VorePanel.jsx b/tgui/packages/tgui/interfaces/VorePanel.jsx index b80b57fa02..7a415b55a8 100644 --- a/tgui/packages/tgui/interfaces/VorePanel.jsx +++ b/tgui/packages/tgui/interfaces/VorePanel.jsx @@ -723,6 +723,7 @@ const VoreSelectedBellyOptions = (props) => { belly_mob_mult, belly_item_mult, belly_overall_mult, + drainmode, } = belly; return ( @@ -870,6 +871,12 @@ const VoreSelectedBellyOptions = (props) => { content={digest_clone} /> + + ",ae+='
',ae+='
',ae+="Addons:
"+x(_)+"

",ae+="== Descriptions ==
",ae+="Vore Verb:
"+b+"

",ae+="Release Verb:
"+I+"

",ae+='Description:
"'+C+'"

',ae+='Absorbed Description:
"'+j+'"

',ae+="
",ae+="== Messages ==
",ae+='
',ae+='
",ae+='
',ae+='
',ae+='
',ve==null||ve.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',be==null||be.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',we==null||we.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Je==null||Je.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ze==null||ze.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Ke==null||Ke.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Be==null||Be.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ct==null||ct.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',xt==null||xt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',st==null||st.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ot==null||ot.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Ae==null||Ae.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Le==null||Le.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Pe==null||Pe.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ke==null||ke.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Me==null||Me.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Fe==null||Fe.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',We==null||We.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',He==null||He.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',jt==null||jt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Mt==null||Mt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',bt==null||bt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Dt==null||Dt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',lt==null||lt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Ge==null||Ge.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ue==null||ue.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',ce==null||ce.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',me==null||me.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',xe==null||xe.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',je==null||je.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Qe==null||Qe.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',mt==null||mt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Pt==null||Pt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',zt==null||zt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',en==null||en.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',Wt==null||Wt.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+='
',dn==null||dn.forEach(function(Se){ae+=Se+"
"}),ae+="
",ae+="
",ae+="
",ae+="
",ae+="
= Idle Messages =

",ae+="

Idle Messages (Hold):

",Gn==null||Gn.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Hold Absorbed):

",Hn==null||Hn.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Digest):

",Bn==null||Bn.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Absorb):

",Eo==null||Eo.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Unabsorb):

",In==null||In.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Drain):

",Oo==null||Oo.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Heal):

",bo==null||bo.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Size Steal):

",Vr==null||Vr.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Shrink):

",Gr==null||Gr.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Grow):

",oa==null||oa.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="
Idle Messages (Encase In Egg):

",Xr==null||Xr.forEach(function(Se){ae+=Se+"
"}),ae+="


",ae+="


",ae+="
",ae+='
',ae+='
',ae+='

',ae+='

",ae+='
',ae+='
',ae+='
    ',ae+='
  • Can Taste: '+(k?'Yes':'No')+"
  • ",ae+='
  • Contaminates: '+(V?'Yes':'No')+"
  • ",ae+='
  • Contamination Flavor: '+F+"
  • ",ae+='
  • Contamination Color: '+J+"
  • ",ae+='
  • Nutritional Gain: '+H+"%
  • ",ae+='
  • Required Examine Size: '+Y*100+"%
  • ",ae+='
  • Display Absorbed Examines: '+(Z?'True':'False')+"
  • ",ae+='
  • Save Digest Mode: '+(X?'True':'False')+"
  • ",ae+='
  • Idle Emotes: '+(z?'Active':'Inactive')+"
  • ",ae+='
  • Idle Emote Delay: '+Q+" seconds
  • ",ae+='
  • Shrink/Grow Size: '+ee*100+"%
  • ",ae+='
  • Egg Type: '+oe+"
  • ",ae+='
  • Selective Mode Preference: '+ne+"
  • ",ae+="
",ae+="
",ae+='
',ae+='

',ae+='

",ae+='
',ae+='
',ae+='
    ',ae+='
  • Fleshy Belly: '+(Io?'Yes':'No')+"
  • ",ae+='
  • Internal Loop: '+(Cr?'Yes':'No')+"
  • ",ae+='
  • Use Fancy Sounds: '+(xn?'Yes':'No')+"
  • ",ae+='
  • Vore Sound: '+pn+"
  • ",ae+='
  • Release Sound: '+ir+"
  • ",ae+="
",ae+="
",ae+='
',ae+='

',ae+='

",ae+='
",ae+='
',ae+="Vore FX",ae+='
    ',ae+='
  • Disable Prey HUD: '+(Er?'Yes':'No')+"
  • ",ae+="
",ae+="
",ae+='
',ae+='

',ae+='

",ae+='
',ae+='
',ae+="Belly Interactions ("+(_o?'Enabled':'Disabled')+")",ae+='
    ',ae+='
  • Escape Chance: '+ei+"%
  • ",ae+='
  • Escape Chance: '+ti+"%
  • ",ae+='
  • Escape Time: '+ni/10+"s
  • ",ae+='
  • Transfer Chance: '+Kn+"%
  • ",ae+='
  • Transfer Location: '+aa+"
  • ",ae+='
  • Secondary Transfer Chance: '+ia+"%
  • ",ae+='
  • Secondary Transfer Location: '+ri+"
  • ",ae+='
  • Absorb Chance: '+sa+"%
  • ",ae+='
  • Digest Chance: '+la+"%
  • ",ae+="
",ae+="
",ae+="
",ae},m=function(){var c=new Date,d=String(c.getHours());d.length<2&&(d="0"+d);var p=String(c.getMinutes());p.length<2&&(p="0"+p);var C=String(c.getDate());C.length<2&&(C="0"+C);var j=String(c.getMonth()+1);j.length<2&&(j="0"+j);var b=String(c.getFullYear());return" "+b+"-"+j+"-"+C+" ("+d+" "+p+")"},v=function(c){var d=(0,s.Oc)(),p=d.act,C=d.data,j=C.db_version,b=C.db_repo,I=C.mob_name,O=C.bellies,_=m(),D=I+_+c,M;if(c===".html"){var A="";M=new Blob([''+O.length+" Exported Bellies (DB_VER: "+b+"-"+j+')'+A+'

Bellies of '+I+'

Generated on: '+_+'

'],{type:"text/html;charset=utf8"}),O.forEach(function(R,K){M=new Blob([M,f(R,K)],{type:"text/html;charset=utf8"})}),M=new Blob([M,"
",'