diff --git a/code/__defines/belly_modes_ch.dm b/code/__defines/belly_modes_ch.dm
new file mode 100644
index 0000000000..e4b04aa87a
--- /dev/null
+++ b/code/__defines/belly_modes_ch.dm
@@ -0,0 +1,9 @@
+//CHOMP belly modes
+
+
+
+//Belly Reagents mode flags
+#define DM_FLAG_REAGENTSNUTRI 0x1
+#define DM_FLAG_REAGENTSDIGEST 0x2
+#define DM_FLAG_REAGENTSABSORB 0x4
+#define DM_FLAG_REAGENTSDRAIN 0x8
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 0976ed5ea3..c87391562b 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -5,6 +5,7 @@
#define CHEM_TOUCH 1
#define CHEM_INGEST 2
#define CHEM_BLOOD 3
+#define CHEM_VORE 4 //CHOMP vore belly interactions
#define MINIMUM_CHEMICAL_VOLUME 0.01
diff --git a/code/controllers/subsystems/bellies_vr.dm b/code/controllers/subsystems/bellies_vr.dm
index faaa297ca3..64fec98568 100644
--- a/code/controllers/subsystems/bellies_vr.dm
+++ b/code/controllers/subsystems/bellies_vr.dm
@@ -34,6 +34,7 @@ SUBSYSTEM_DEF(bellies)
if(QDELETED(B))
belly_list -= B
else
+ B.HandleBellyReagents() //CHOMP reagent belly stuff, here to jam it into subsystems and avoid too much cpu usage
if(B.process_belly(times_fired,wait) == SSBELLIES_IGNORED)
ignored_bellies++
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index dad9e0f41d..719be69838 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -291,6 +291,7 @@
msg += attempt_vr(src,"examine_weight",args) //VOREStation Code
msg += attempt_vr(src,"examine_nutrition",args) //VOREStation Code
+ msg += attempt_vr(src,"examine_reagent_bellies",args) //CHOMP reagent bellies
msg += attempt_vr(src,"examine_bellies",args) //VOREStation Code
msg += attempt_vr(src,"examine_pickup_size",args) //VOREStation Code
msg += attempt_vr(src,"examine_step_size",args) //VOREStation Code
diff --git a/code/modules/mob/living/silicon/pai/examine.dm b/code/modules/mob/living/silicon/pai/examine.dm
index 11a970cfe8..db0f0d618a 100644
--- a/code/modules/mob/living/silicon/pai/examine.dm
+++ b/code/modules/mob/living/silicon/pai/examine.dm
@@ -7,6 +7,7 @@
if(!src.client) msg += "\nIt appears to be in stand-by mode.\n" //afk
if(UNCONSCIOUS) msg += "\nIt doesn't seem to be responding.\n"
if(DEAD) msg += "\nIt looks completely unsalvageable.\n"
+ msg += attempt_vr(src,"examine_reagent_bellies",args) //CHOMP reagent bellies
msg += attempt_vr(src,"examine_bellies",args) //VOREStation Edit
// VOREStation Edit: Start
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index 33ec3183be..fddae555dd 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -32,6 +32,7 @@
msg += "It appears to be in stand-by mode.\n" //afk
if(UNCONSCIOUS) msg += "It doesn't seem to be responding.\n"
if(DEAD) msg += "It looks completely unsalvageable.\n"
+ msg += attempt_vr(src,"examine_reagent_bellies",args) //CHOMP reagent bellies
msg += attempt_vr(src,"examine_bellies_borg",args) //VOREStation Edit
// VOREStation Edit: Start
diff --git a/code/modules/reagents/Chemistry-Holder_ch.dm b/code/modules/reagents/Chemistry-Holder_ch.dm
new file mode 100644
index 0000000000..2a532da0d9
--- /dev/null
+++ b/code/modules/reagents/Chemistry-Holder_ch.dm
@@ -0,0 +1,25 @@
+//CHOMP code for transfer specifically into vore bellies
+
+/datum/reagents/proc/vore_trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_VORE, var/multiplier = 1, var/copy = 0, var/obj/belly/target_belly = null) // Transfer after checking into which holder...
+ if(!target || !istype(target))
+ return
+
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ if(type == CHEM_VORE)
+ var/datum/reagents/R = target_belly.reagents
+ return trans_to_holder(R, amount, multiplier, copy)
+ if(type == CHEM_INGEST)
+ var/datum/reagents/R = C.ingested
+ return C.ingest(src, R, amount, multiplier, copy)
+
+ else //Retaining this code as a backup
+ var/datum/reagents/R = new /datum/reagents(amount)
+ . = trans_to_holder(R, amount, multiplier, copy)
+ R.touch_mob(target)
+
+/datum/reagents/proc/vore_trans_to_con(var/obj/item/weapon/reagent_containers/T, var/amount = 1, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder...
+ if(!T || !istype(T))
+ return
+
+ return trans_to_holder(T.reagents, amount, multiplier, copy)
diff --git a/code/modules/vore/eating/belly_obj_ch.dm b/code/modules/vore/eating/belly_obj_ch.dm
new file mode 100644
index 0000000000..792310a023
--- /dev/null
+++ b/code/modules/vore/eating/belly_obj_ch.dm
@@ -0,0 +1,265 @@
+#define VORE_SOUND_FALLOFF 0.1
+#define VORE_SOUND_RANGE 3
+
+//CHOMP vore additions, currently only consists of reagent stuff - Jack
+
+/obj/belly
+ //CHOMP - liquid bellies
+ var/reagentbellymode = FALSE // Belly has abilities to make liquids from digested/absorbed/drained prey and/or nutrition
+ var/reagent_mode_flags = 0
+
+ var/tmp/static/list/reagent_mode_flag_list= list(
+ "Produce Liquids" = DM_FLAG_REAGENTSNUTRI,
+ "Digestion Liquids" = DM_FLAG_REAGENTSDIGEST,
+ "Absorption Liquids" = DM_FLAG_REAGENTSABSORB,
+ "Draining Liquids" = DM_FLAG_REAGENTSDRAIN
+ )
+
+ var/nutri_reagent_gen = FALSE //if belly produces reagent over time using nutrition, needs to be optimized to use subsystem - Jack
+ var/list/generated_reagents = list("water" = 1) //Any number of reagents, the associated value is how many units are generated per process()
+ var/reagent_name = "water" //What is shown when reagents are removed, doesn't need to be an actual reagent
+ var/gen_cost = 1 //amount of nutrient taken from the host everytime nutrition is used to make reagents
+ var/gen_amount = 1 //Does not actually influence amount produced, but is used as a way to tell the system how much total reagent it has to take into account when filling a belly
+
+ var/gen_interval = 0 //Interval in seconds for generating fluids, once it reaches the value of gen_time one cycle of reagents generation will occur
+ var/gen_time = 30 //Time it takes in seconds to produce one cycle of reagents
+
+ var/digest_nutri_gain = 0 //variable to store temporary nutrition gain from digestion and allow a seperate proc to ease up on the wall of code
+
+ var/liquid_fullness1_messages = FALSE
+ var/liquid_fullness2_messages = FALSE
+ var/liquid_fullness3_messages = FALSE
+ var/liquid_fullness4_messages = FALSE
+ var/liquid_fullness5_messages = FALSE
+
+ var/list/fullness1_messages = list(
+ "%pred's %belly looks empty"
+ )
+ var/list/fullness2_messages = list(
+ "%pred's %belly looks filled"
+ )
+ var/list/fullness3_messages = list(
+ "%pred's %belly looks like it's full of liquid"
+ )
+ var/list/fullness4_messages = list(
+ "%pred's %belly is quite full!"
+ )
+ var/list/fullness5_messages = list(
+ "%pred's %belly is completely filled to it's limit!"
+ )
+
+ // Stuff to add in future!
+ /*
+ var/list/empty_message = list("You feel as though your internal reagent implant is almost empty.")
+ var/list/full_message = "You feel as though your internal reagent implant is full."
+
+ var/list/emote_descriptor = list("tranfers something") //In format of [x] [emote_descriptor] into [container]
+ var/list/self_emote_descriptor = list("transfer") //In format of You [self_emote_descriptor] some [generated_reagent] into [container]
+ var/list/random_emote = list() //An emote the person with the implant may be forced to perform after a prob check, such as [X] meows. //Potential future settings to have custom messages set by player when someone extracts fluids from them - Jack
+ */
+
+ var/tmp/reagent_chosen = "Water" // variable for switch to figure out what to set variables when a certain reagent is selected
+ var/tmp/static/list/reagent_choices = list( // List of reagents people can chose, maybe one day expand so it covers criterias like dogborgs who can make meds, booze, etc - Jack
+ "Water",
+ "Milk",
+ "Cream",
+ "Honey"
+ )
+
+
+
+///////////////////// NUTRITION REAGENT PRODUCTION /////////////////
+
+/obj/belly/proc/HandleBellyReagents()
+ if(reagent_mode_flags & DM_FLAG_REAGENTSNUTRI && reagents.total_volume < reagents.maximum_volume)
+ if(owner.nutrition >= gen_cost && gen_interval >= gen_time)
+ GenerateBellyReagents()
+ gen_interval = 0
+ else
+ gen_interval++
+
+/obj/belly/proc/GenerateBellyReagents()
+ owner.nutrition -= gen_cost
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent])
+
+//////////////////////////// REAGENT_DIGEST ////////////////////////
+
+/obj/belly/proc/GenerateBellyReagents_digesting() //The rate isnt based on selected reagent, due to the fact that the price of the reagent is already paid by nutrient not gained.
+ if(reagents.total_volume + (digest_nutri_gain * gen_amount) <= reagents.maximum_volume) //By default a reagent with an amount of 1 should result in pred getting 100 units from a full health prey
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] * digest_nutri_gain)
+ else
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] / gen_amount * (reagents.maximum_volume - reagents.total_volume))
+
+/obj/belly/proc/GenerateBellyReagents_digested()
+ if(reagents.total_volume <= reagents.maximum_volume - 25 * gen_amount)
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] * 25)
+ else
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] / gen_amount * (reagents.maximum_volume - reagents.total_volume))
+
+//////////////////////////// REAGENT_ABSORB ////////////////////////
+
+/obj/belly/proc/GenerateBellyReagents_absorbing()
+ if(reagents.total_volume <= reagents.maximum_volume - 1.5 * gen_amount) //Going for 1.5 amount of reagent per cycle, can be adjusted in future if need adjustments
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] * 1.5)
+ else
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] / gen_amount * (reagents.maximum_volume - reagents.total_volume))
+
+/obj/belly/proc/GenerateBellyReagents_absorbed()
+ if(reagents.total_volume <= reagents.maximum_volume - 25 * gen_amount) //Going for 25 amount of reagent for absorbing the prey, can be adjusted in future if need adjustments
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] * 10)
+ else
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent] / gen_amount * (reagents.maximum_volume - reagents.total_volume))
+
+//////////////////////////// REAGENT_DRAIN ///////////////////////// //Currently not needed, maybe later a specific proc for drain needs to be made - Jack
+
+
+
+//////////////////////////// REAGENT SELECTION /////////////////////
+
+//This is gonna end up a long proc, but its gonna have to make do for now
+
+/obj/belly/proc/ReagentSwitch()
+ switch(reagent_chosen)
+ if("Water")
+ generated_reagents = list("water" = 1)
+ reagent_name = "water"
+ gen_amount = 1
+ gen_cost = 1
+ if("Milk")
+ generated_reagents = list("milk" = 1)
+ reagent_name = "milk"
+ gen_amount = 1
+ gen_cost = 1.5
+ if("Cream")
+ generated_reagents = list("cream" = 1)
+ reagent_name = "cream"
+ gen_amount = 1
+ gen_cost = 1.5
+ if("Honey")
+ generated_reagents = list("honey" = 1)
+ reagent_name = "honey"
+ gen_amount = 1
+ gen_cost = 1.5
+
+/////////////////////// FULLNESS MESSAGES //////////////////////
+
+// Get the line that should show up in Examine message if the owner of this belly is examined.
+// Returns a string which shoul be appended to the Examine output.
+// Yes I know it doesnt look great with 5 almost identical procs in a row, I didnt have a better idea at the time - Jack
+/obj/belly/proc/get_reagent_examine_msg1()
+ if(fullness1_messages.len)
+ var/formatted_message
+ var/raw_message = pick(fullness1_messages)
+
+ formatted_message = replacetext(raw_message,"%belly",lowertext(name))
+ formatted_message = replacetext(formatted_message,"%pred",owner)
+
+ return("[formatted_message]
")
+
+/obj/belly/proc/get_reagent_examine_msg2()
+ if(fullness1_messages.len)
+ var/formatted_message
+ var/raw_message = pick(fullness2_messages)
+
+ formatted_message = replacetext(raw_message,"%belly",lowertext(name))
+ formatted_message = replacetext(formatted_message,"%pred",owner)
+
+ return("[formatted_message]
")
+
+/obj/belly/proc/get_reagent_examine_msg3()
+ if(fullness1_messages.len)
+ var/formatted_message
+ var/raw_message = pick(fullness3_messages)
+
+ formatted_message = replacetext(raw_message,"%belly",lowertext(name))
+ formatted_message = replacetext(formatted_message,"%pred",owner)
+
+ return("[formatted_message]
")
+
+/obj/belly/proc/get_reagent_examine_msg4()
+ if(fullness1_messages.len)
+ var/formatted_message
+ var/raw_message = pick(fullness4_messages)
+
+ formatted_message = replacetext(raw_message,"%belly",lowertext(name))
+ formatted_message = replacetext(formatted_message,"%pred",owner)
+
+ return("[formatted_message]
")
+
+/obj/belly/proc/get_reagent_examine_msg5()
+ if(fullness1_messages.len)
+ var/formatted_message
+ var/raw_message = pick(fullness5_messages)
+
+ formatted_message = replacetext(raw_message,"%belly",lowertext(name))
+ formatted_message = replacetext(formatted_message,"%pred",owner)
+
+ return("[formatted_message]
")
+
+
+// The next function gets the messages set on the belly, in human-readable format.
+// This is useful in customization boxes and such. The delimiter right now is \n\n so
+// in message boxes, this looks nice and is easily delimited.
+/obj/belly/proc/get_reagent_messages(var/type, var/delim = "\n\n")
+ ASSERT(type == "full1" || type == "full2" || type == "full3" || type == "full4" || type == "full5")
+ var/list/raw_messages
+
+ switch(type)
+ if("full1")
+ raw_messages = fullness1_messages
+ if("full2")
+ raw_messages = fullness2_messages
+ if("full3")
+ raw_messages = fullness3_messages
+ if("full4")
+ raw_messages = fullness4_messages
+ if("full5")
+ raw_messages = fullness5_messages
+
+ var/messages = list2text(raw_messages,delim)
+ return messages
+
+// The next function sets the messages on the belly, from human-readable var
+// replacement strings and linebreaks as delimiters (two \n\n by default).
+// They also sanitize the messages.
+/obj/belly/proc/set_reagent_messages(var/raw_text, var/type, var/delim = "\n\n")
+ ASSERT(type == "full1" || type == "full2" || type == "full3" || type == "full4" || type == "full5")
+
+ var/list/raw_list = text2list(html_encode(raw_text),delim)
+ if(raw_list.len > 10)
+ raw_list.Cut(11)
+ log_debug("[owner] tried to set [lowertext(name)] with 11+ messages")
+
+ for(var/i = 1, i <= raw_list.len, i++)
+ if(length(raw_list[i]) > 160 || length(raw_list[i]) < 10) //160 is fudged value due to htmlencoding increasing the size
+ raw_list.Cut(i,i)
+ log_debug("[owner] tried to set [lowertext(name)] with >121 or <10 char message")
+ else
+ raw_list[i] = readd_quotes(raw_list[i])
+ //Also fix % sign for var replacement
+ raw_list[i] = replacetext(raw_list[i],"%","%")
+
+ ASSERT(raw_list.len <= 10) //Sanity
+
+ switch(type)
+ if("full1")
+ fullness1_messages = raw_list
+ if("full2")
+ fullness2_messages = raw_list
+ if("full3")
+ fullness3_messages = raw_list
+ if("full4")
+ fullness4_messages = raw_list
+ if("full5")
+ fullness5_messages = raw_list
+
+ return
\ No newline at end of file
diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm
index 2edab6a30b..90db1dccd4 100644
--- a/code/modules/vore/eating/belly_obj_vr.dm
+++ b/code/modules/vore/eating/belly_obj_vr.dm
@@ -158,7 +158,24 @@
"release_sound",
"fancy_vore",
"is_wet",
- "wet_loop"
+ "wet_loop",
+ "reagent_mode_flags", //CHOMP start of variables from CHOMP
+ "liquid_fullness1_messages",
+ "liquid_fullness2_messages",
+ "liquid_fullness3_messages",
+ "liquid_fullness4_messages",
+ "liquid_fullness5_messages",
+ "reagent_name",
+ "reagent_chosen",
+ "gen_cost",
+ "gen_amount",
+ "gen_time",
+ "generated_reagents",
+ "fullness1_messages",
+ "fullness2_messages",
+ "fullness3_messages",
+ "fullness4_messages",
+ "fullness5_messages" //CHOMP end of variables from CHOMP
)
/obj/belly/New(var/newloc)
@@ -168,6 +185,8 @@
owner = loc
owner.vore_organs |= src
SSbellies.belly_list += src
+ create_reagents(100) //CHOMP So we can have some liquids in bellies
+ flags |= NOREACT // We dont want bellies to start bubling nonstop due to people mixing when transfering and making different reagents
/obj/belly/Destroy()
SSbellies.belly_list -= src
@@ -690,6 +709,18 @@
dupe.fancy_vore = fancy_vore
dupe.is_wet = is_wet
dupe.wet_loop = wet_loop
+ dupe.reagent_mode_flags = reagent_mode_flags //CHOMP start of variables from CHOMP
+ dupe.liquid_fullness1_messages = liquid_fullness1_messages
+ dupe.liquid_fullness2_messages = liquid_fullness2_messages
+ dupe.liquid_fullness3_messages = liquid_fullness3_messages
+ dupe.liquid_fullness4_messages = liquid_fullness4_messages
+ dupe.liquid_fullness5_messages = liquid_fullness5_messages
+ dupe.reagent_name = reagent_name
+ dupe.reagent_chosen = reagent_chosen
+ dupe.gen_cost = gen_cost
+ dupe.gen_amount = gen_amount
+ dupe.gen_time = gen_time //CHOMP end of variables from CHOMP
+
//// Object-holding variables
//struggle_messages_outside - strings
@@ -717,6 +748,43 @@
for(var/I in examine_messages)
dupe.examine_messages += I
+ // CHOMP reagent belly
+ //generated_reagents - strings
+ dupe.generated_reagents.Cut()
+ for(var/I in generated_reagents)
+ dupe.generated_reagents += I
+
+ // CHOMP fullness messages stage 1
+ //fullness1_messages - strings
+ dupe.fullness1_messages.Cut()
+ for(var/I in fullness1_messages)
+ dupe.fullness1_messages += I
+
+ // CHOMP fullness messages stage 2
+ //fullness2_messages - strings
+ dupe.fullness2_messages.Cut()
+ for(var/I in fullness2_messages)
+ dupe.fullness2_messages += I
+
+ // CHOMP fullness messages stage 3
+ //fullness3_messages - strings
+ dupe.fullness3_messages.Cut()
+ for(var/I in fullness3_messages)
+ dupe.fullness3_messages += I
+
+ // CHOMP fullness messages stage 4
+ //fullness4_messages - strings
+ dupe.fullness4_messages.Cut()
+ for(var/I in fullness4_messages)
+ dupe.fullness4_messages += I
+
+ // CHOMP fullness messages stage 5
+ //generated_reagents - strings
+ dupe.fullness5_messages.Cut()
+ for(var/I in fullness5_messages)
+ dupe.fullness5_messages += I
+
+
//emote_lists - index: digest mode, key: list of strings
dupe.emote_lists.Cut()
for(var/K in emote_lists)
diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm
index 605fea6cd9..d1175656e4 100644
--- a/code/modules/vore/eating/bellymodes_vr.dm
+++ b/code/modules/vore/eating/bellymodes_vr.dm
@@ -191,9 +191,17 @@
if(compensation > 0)
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
- R.cell.charge += 25*compensation
+ if(reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && reagents.total_volume < reagents.maximum_volume) //CHOMP digestion producing reagents
+ R.cell.charge += 15*compensation
+ GenerateBellyReagents_digested()
+ else
+ R.cell.charge += 25*compensation
else
- owner.nutrition += (nutrition_percent / 100)*4.5*compensation
+ if(reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && reagents.total_volume < reagents.maximum_volume) //CHOMP digestion producing reagents
+ owner.nutrition += (nutrition_percent / 100)*3.0*compensation
+ GenerateBellyReagents_digested()
+ else
+ owner.nutrition += (nutrition_percent / 100)*4.5*compensation
to_update = TRUE
continue
@@ -210,10 +218,20 @@
var/offset = (1 + ((M.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02
var/difference = owner.size_multiplier / M.size_multiplier
if(isrobot(owner))
- var/mob/living/silicon/robot/R = owner
- R.cell.charge += 25*damage_gain
+ if(reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && reagents.total_volume < reagents.maximum_volume) //CHOMP digestion producing reagents
+ var/mob/living/silicon/robot/R = owner
+ R.cell.charge += 20*damage_gain
+ GenerateBellyReagents_digesting()
+ else
+ var/mob/living/silicon/robot/R = owner
+ R.cell.charge += 25*damage_gain
if(offset) // If any different than default weight, multiply the % of offset.
- owner.nutrition += offset*((nutrition_percent / 100)*4.5*(damage_gain)/difference) //4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
+ if(reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && reagents.total_volume < reagents.maximum_volume) //CHOMP digestion producing reagents
+ owner.nutrition += offset*((nutrition_percent / 100)*4.5/(gen_cost*1.25)*(damage_gain)/difference)//Uncertain if balanced fairly, can adjust by multiplier for the cost of reagent, dont go below 1 or else it will result in more nutrition than normal - Jack
+ digest_nutri_gain = offset*((nutrition_percent / 100)*0.5/(gen_cost*1.25)*(damage_gain)/difference) //for transfering nutrition value over to GenerateBellyReagents_digesting()
+ GenerateBellyReagents_digesting()
+ else
+ owner.nutrition += offset*((nutrition_percent / 100)*4.5*(damage_gain)/difference)//4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
else
owner.nutrition += (nutrition_percent / 100)*4.5*(damage_gain)/difference
@@ -237,9 +255,15 @@
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
- owner.nutrition += oldnutrition
+ if(reagent_mode_flags & DM_FLAG_REAGENTSABSORB && reagents.total_volume < reagents.maximum_volume) //CHOMP absorption reagent production
+ owner.nutrition += oldnutrition * 0.75 //keeping the price static, due to how much nutrition can flunctuate
+ GenerateBellyReagents_absorbing()
+ else
+ owner.nutrition += oldnutrition
else if(M.nutrition < 100) //When they're finally drained.
absorb_living(M)
+ if(reagent_mode_flags & DM_FLAG_REAGENTSABSORB && reagents.total_volume < reagents.maximum_volume) //CHOMP absorption reagent production
+ GenerateBellyReagents_absorbed() //A bonus for pred, I know for a fact prey is usually at zero nutrition when absorption finally happens
to_update = TRUE
//////////////////////////// DM_UNABSORB ////////////////////////////
@@ -269,7 +293,11 @@
if(M.nutrition >= 100) //Drain them until there's no nutrients left.
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
- owner.nutrition += oldnutrition
+ if(reagent_mode_flags & DM_FLAG_REAGENTSDRAIN && reagents.total_volume < reagents.maximum_volume) //CHOMP draining reagent production
+ owner.nutrition += oldnutrition * 0.75 //keeping the price static, due to how much nutrition can flunctuate
+ GenerateBellyReagents_absorbing() //Dont need unique proc so far
+ else
+ owner.nutrition += oldnutrition
//////////////////////////// DM_SHRINK ////////////////////////////
else if(digest_mode == DM_SHRINK)
@@ -372,6 +400,7 @@
else
M.playsound_local(owner.loc, play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
//these are all external sound triggers now, so it's ok.
+
if(to_update)
for(var/mob/living/M in contents)
if(M.client)
diff --git a/code/modules/vore/eating/living_ch.dm b/code/modules/vore/eating/living_ch.dm
new file mode 100644
index 0000000000..7ef5b23e11
--- /dev/null
+++ b/code/modules/vore/eating/living_ch.dm
@@ -0,0 +1,138 @@
+///////////////////// Mob Living /////////////////////
+/mob/living
+ var/receive_reagents = FALSE //Pref for people to avoid others transfering reagents into them.
+ var/give_reagents = FALSE //Pref for people to avoid others taking reagents from them.
+
+//
+// Returns examine messages for how much reagents are in bellies
+//
+/mob/living/proc/examine_reagent_bellies()
+ if(!show_pudge()) //Some clothing or equipment can hide this. Reagent inflation is not very different in this aspect.
+ return ""
+
+ var/message = ""
+ for (var/belly in vore_organs)
+ var/obj/belly/B = belly
+
+ if(0 <= B.reagents.total_volume && B.reagents.total_volume <= 20 && B.liquid_fullness1_messages)
+ message += B.get_reagent_examine_msg1()
+ if(20 < B.reagents.total_volume && B.reagents.total_volume <= 40 && B.liquid_fullness2_messages)
+ message += B.get_reagent_examine_msg2()
+ if(40 < B.reagents.total_volume && B.reagents.total_volume <= 60 && B.liquid_fullness3_messages)
+ message += B.get_reagent_examine_msg3()
+ if(60 < B.reagents.total_volume && B.reagents.total_volume <= 80 && B.liquid_fullness4_messages)
+ message += B.get_reagent_examine_msg4()
+ if(80 < B.reagents.total_volume && B.reagents.total_volume <= 100 && B.liquid_fullness5_messages)
+ message += B.get_reagent_examine_msg5()
+
+ return message
+
+
+/mob/living/proc/vore_transfer_reagents()
+ set name = "Transfer Liquid (Vore)"
+ set category = "Abilities"
+ set desc = "Transfer liquid from an organ to another or stomach, or into another person or container."
+ set popup_menu = FALSE
+
+ if(!canClick() || incapacitated(INCAPACITATION_ALL))
+ return FALSE
+
+ var/mob/living/user = usr
+
+ var/mob/living/TG = input("Choose who is transfered from") as null| mob in view(user.loc,1)
+ if(!TG)
+ return FALSE
+
+
+ var/obj/belly/RTB = input("Choose which organ to transfer from") as null|anything in TG.vore_organs //First they choose the belly to transfer from.
+ if(!RTB)
+ return FALSE
+ if(TG.give_reagents == FALSE && user != TG) //User isnt forced to allow giving in prefs if they are the one doing it
+ to_chat(user, "This person's prefs dont allow that!")
+ return FALSE
+
+ var/transfer_amount = input("How much to transfer?") in list(5,10,25,50,100)
+ if(!transfer_amount)
+ return FALSE
+
+ switch(input(user,"Choose what to transfer to","Select Target") in list("Organs", "Stomachs", "Containers", "Cancel"))
+ if("Cancel")
+ return FALSE
+ if("Organs")
+ var/mob/living/TR = input(user,"Choose who to transfer to","Select Target") as null|mob in view(user.loc,1)
+ if(!TR) return FALSE
+
+ if(TR == user) //Proceed, we dont need to have prefs enabled for transfer within user
+ var/obj/belly/TB = input("Choose which organ to transfer to") as null|anything in user.vore_organs
+ if(!TB)
+ return FALSE
+
+ if(!TR.reagents.get_free_space())
+ to_chat(user, "[TB] is full!")
+ return FALSE
+
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_VORE, 1, 0, TB)
+
+ if(TG != user)
+ user.visible_message("[user] fills their [TB] with [RTB.reagent_name] from [TG]'s [RTB].")
+ else
+ user.visible_message("[user] fills their [TB] with [RTB.reagent_name] from their [RTB].")
+
+ else if(TR.receive_reagents == FALSE)
+ to_chat(user, "This person's prefs dont allow that!")
+ return FALSE
+
+ else
+ var/obj/belly/TB = input("Choose which organ to transfer to") as null|anything in TR.vore_organs
+ if(!TB)
+ return FALSE
+
+ if(!TR.reagents.get_free_space())
+ to_chat(user, "[TR]'s [TB] is full!")
+ return FALSE
+
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_VORE, 1, 0, TB)
+
+ if(TG == user)
+ user.visible_message("[user] fills [TR]'s [TB] with [RTB.reagent_name] from their [RTB].")
+ else
+ user.visible_message("[user] fills [TR]'s [TB] with [RTB.reagent_name] from [TG]'s [RTB].")
+
+ add_attack_logs(user,TR,"Transfered reagents from [TG]'s [RTB] to [TR]'s [TB]") //Bonus for staff so they can see if people have abused transfer and done pref breaks
+
+
+ if("Stomachs")
+ var/mob/living/TR = input(user,"Choose who to transfer to","Select Target") as null|mob in view(user.loc,1)
+ if(!TR) return
+
+ if(TR == user) //Proceed, we dont need to have prefs enabled for transfer within user
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_INGEST, 1, 0, null)
+ if(TG != user)
+ user.visible_message("[user] fills their stomach with [RTB.reagent_name] from [TG]'s [RTB].")
+ else
+ user.visible_message("[user] fills their stomach with [RTB.reagent_name] from their [RTB].")
+
+ else if(TR.receive_reagents == FALSE)
+ to_chat(user, "This person's prefs dont allow that!")
+ return FALSE
+
+ else
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_INGEST, 1, 0, null)
+ if(TG == user)
+ user.visible_message("[user] fills [TR]'s stomach with [RTB.reagent_name] from their [RTB].")
+ else
+ user.visible_message("[user] fills [TR]'s stomach with [RTB.reagent_name] from [TG]'s [RTB].")
+
+ add_attack_logs(user,TR,"Transfered reagents from [TG]'s [RTB] to [TR]'s Stomach") //Bonus for staff so they can see if people have abused transfer and done pref breaks
+
+ if("Containers")
+ var/list/choices = list()
+ for(var/obj/item/weapon/reagent_containers/rc in view(user.loc,1))
+ choices += rc
+ var/obj/item/weapon/reagent_containers/T = input(user,"Choose what to transfer to","Select Target") as null|anything in choices
+ RTB.reagents.vore_trans_to_con(T, transfer_amount, 1, 0)
+
+ if(TG == user)
+ user.visible_message("[user] fills the [T] with [RTB.reagent_name] from their [RTB].")
+ else
+ user.visible_message("[user] fills the [T] with [RTB.reagent_name] from [TG]'s [RTB].")
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index 6582a840c4..4b51924572 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -42,6 +42,7 @@
if(M.no_vore) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
return TRUE
M.verbs += /mob/living/proc/insidePanel
+ M.verbs += /mob/living/proc/vore_transfer_reagents //CHOMP If mob doesnt have bellies it cant use this verb for anything
//Tries to load prefs if a client is present otherwise gives freebie stomach
spawn(2 SECONDS)
@@ -229,6 +230,12 @@
P.can_be_drop_prey = src.can_be_drop_prey
P.can_be_drop_pred = src.can_be_drop_pred
+
+ //CHOMP reagent belly
+ P.receive_reagents = src.receive_reagents
+ P.give_reagents = src.give_reagents
+
+
var/list/serialized = list()
for(var/belly in src.vore_organs)
var/obj/belly/B = belly
@@ -259,6 +266,12 @@
can_be_drop_prey = P.can_be_drop_prey
can_be_drop_pred = P.can_be_drop_pred
+
+ //CHOMP reagents belly
+ receive_reagents = P.receive_reagents
+ give_reagents = P.give_reagents
+
+
release_vore_contents(silent = TRUE)
vore_organs.Cut()
for(var/entry in P.belly_prefs)
diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm
index 919cec84e8..62f5046bca 100644
--- a/code/modules/vore/eating/vore_vr.dm
+++ b/code/modules/vore/eating/vore_vr.dm
@@ -55,6 +55,12 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
var/can_be_drop_prey = FALSE
var/can_be_drop_pred = FALSE
+
+ //CHOMP reagent belly
+ var/receive_reagents = FALSE
+ var/give_reagents = FALSE
+
+
//Mechanically required
var/path
var/slot
@@ -126,6 +132,12 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
can_be_drop_pred = json_from_file["can_be_drop_pred"]
belly_prefs = json_from_file["belly_prefs"]
+
+ //CHOMP reagent belly
+ receive_reagents = json_from_file["receive_reagents"]
+ give_reagents = json_from_file["give_reagents"]
+
+
//Quick sanitize
if(isnull(digestable))
digestable = TRUE
@@ -148,6 +160,12 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
if(isnull(belly_prefs))
belly_prefs = list()
+ //CHOMP reagent belly
+ if(isnull(receive_reagents))
+ receive_reagents = FALSE
+ if(isnull(give_reagents))
+ give_reagents = FALSE
+
return TRUE
/datum/vore_preferences/proc/save_vore()
diff --git a/code/modules/vore/eating/vorepanel_ch.dm b/code/modules/vore/eating/vorepanel_ch.dm
new file mode 100644
index 0000000000..72fdc48d90
--- /dev/null
+++ b/code/modules/vore/eating/vorepanel_ch.dm
@@ -0,0 +1,6 @@
+//CHOMP - liquid bellies
+
+
+/datum/vore_look
+ var/show_liquids = FALSE
+ var/show_fullness_messages = FALSE
diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm
index b22db19e98..5fae5f96a0 100644
--- a/code/modules/vore/eating/vorepanel_vr.dm
+++ b/code/modules/vore/eating/vorepanel_vr.dm
@@ -306,6 +306,78 @@
dat += " [selected.digestchance]%"
dat += "