From 6514aab82893fa0a1a8aac2cbeee99b31b62a8bf Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 24 Jun 2026 22:50:49 -0400 Subject: [PATCH 01/16] Changed the turf-targetting for attacks to ignore mobs in Bellies and any dead mobs that are 'first' in the list. Fixed being in a belly causes you to still drown. Fixed Slosh sounds and Reagent Gen from Absorb and Digest. --- code/_onclick/click.dm | 2 +- code/modules/mob/living/carbon/life.dm | 13 ++++++------- .../code/modules/vore/eating/bellymodes_vr.dm | 2 +- modular_causticcove/code/modules/vore/slosh.dm | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index e40f47da6f5..6d4f5ccbd79 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -339,7 +339,7 @@ if(T) var/mob/target for(var/mob/M in T) - if(M.invisibility || M == src) + if(M.invisibility || M == src || M.stat == DEAD || isbelly(M.loc)) //Caustic Edit - Lets not target dead mobs, nor mobs that are in a belly! This must be how that's been happening? continue target = M break diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 3b118ebeb23..b956eb2d8ec 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -778,14 +778,13 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put /mob/living/proc/handle_swimming() var/turf/T = get_turf(src) var/area/A = get_area(src) - - - var/is_on_water = istype(T, /turf/open/water) - var/is_on_new_water = istype(T, /turf/open/water/transparent) - - var/is_true_swimming = is_swimming || is_underwater || istype(A, /area/underwater) || is_on_new_water - var/is_area_underwater = istype(A, /area/underwater) + //Caustic Edit - If the mob is in a Belly, we are not swimming! + var/is_on_water = (istype(T, /turf/open/water) && !isbelly(loc)) + var/is_on_new_water = (istype(T, /turf/open/water/transparent) && !isbelly(loc)) + var/is_area_underwater = (istype(A, /area/underwater) && !isbelly(loc)) + var/is_true_swimming = is_swimming || is_underwater || is_area_underwater || is_on_new_water + //Caustic Edit End var/sw_skill = get_skill_level(/datum/skill/misc/swimming) var/new_max_breath = (STACON * 5) + (sw_skill * 5) diff --git a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm index 3a587f77732..7a14965f03e 100644 --- a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm @@ -354,7 +354,7 @@ if(L.nutrition >= 100) var/oldnutrition = (L.nutrition * 0.05) L.nutrition = (L.nutrition * 0.95) - if(show_liquids && reagent_mode_flags & DM_FLAG_REAGENTSDRAIN && reagents.total_volume < reagents.maximum_volume) // draining reagent production //Added to this proc now since it's used for draining + if(reagent_mode_flags & DM_FLAG_REAGENTSDRAIN && reagents.total_volume < reagents.maximum_volume) // draining reagent production //Added to this proc now since it's used for draining //Check previously had show_liquids && at the start owner_adjust_nutrition(oldnutrition * 0.75) //keeping the price static, due to how much nutrition can flunctuate GenerateBellyReagents_absorbing() //Dont need unique proc so far else diff --git a/modular_causticcove/code/modules/vore/slosh.dm b/modular_causticcove/code/modules/vore/slosh.dm index 4c8fee2b898..986e305df01 100644 --- a/modular_causticcove/code/modules/vore/slosh.dm +++ b/modular_causticcove/code/modules/vore/slosh.dm @@ -45,7 +45,7 @@ var/total_volume = B.reagents.total_volume vore_organs_reagents += total_volume - if(B.show_liquids && B.vorefootsteps_sounds && highest_vol < total_volume) + if(B.vorefootsteps_sounds && highest_vol < total_volume) //Whyyyy did this have B.show_liquids && at the start??? highest_vol = total_volume if(highest_vol < 20) From 99eca040c65c1d6af7942c99a9bf28f8156261d7 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 25 Jun 2026 04:22:00 -0400 Subject: [PATCH 02/16] Trying out using Poppymilk for the numbing replacement! Trying to add in Muffled support and Psay for Absorbed players. --- code/__DEFINES/say.dm | 4 ++ code/datums/emotes.dm | 6 ++- code/game/atoms_movable.dm | 1 + code/game/sound.dm | 2 +- code/modules/mob/living/say.dm | 37 +++++++++++++++++++ code/modules/mob/say.dm | 6 ++- .../code/__DEFINES/vore_liquid_defines.dm | 2 + .../vore/eating/bellymodes_datum_vr.dm | 4 +- .../code/modules/vore/eating/bellymodes_vr.dm | 6 +-- 9 files changed, 59 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 43ec1a16539..30df240005d 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -23,6 +23,10 @@ #define MODE_WHISPER "whisper" #define MODE_WHISPER_CRIT "whispercrit" +//Caustic Edit - Add Absorbed Psay mode +#define MODE_PSAY "absorbed" +//Caustic Edit End + #define MODE_SING "%" #define MODE_DEPARTMENT "department" diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 5bba5cfc8db..add0fabf349 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -260,7 +260,7 @@ . = message if(message_muffled && iscarbon(user)) var/mob/living/carbon/C = user - if(C.silent) + if(C.silent || C.muffled) //Caustic Edit - Account for Belly Muffling emotes! . = message_muffled if(!muzzle_ignore && HAS_TRAIT(C, TRAIT_MUTE) && emote_type == EMOTE_AUDIBLE) . = message_muffled @@ -327,6 +327,10 @@ return target /datum/emote/proc/is_emote_muffled(mob/living/carbon/H) //ONLY for audible emote use + //Caustic Edit - Account for Belly Muffling + if(H.muffled) + return FALSE + //Caustic Edit End if(H.mouth?.muteinmouth) return FALSE for(var/obj/item/grabbing/grab in H.grabbedby) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 1d91d4540cb..41913f4cb2c 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -18,6 +18,7 @@ var/verb_ask = "asks" var/verb_exclaim = "exclaims" var/verb_whisper = "whispers" + var/verb_thinks = "thinks" //Caustic Edit - Added to account for Psay and absorbed players! var/verb_sing = "sings" var/verb_yell = "yells" var/speech_span diff --git a/code/game/sound.dm b/code/game/sound.dm index 557f2c98841..bc9964d7240 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -85,7 +85,7 @@ continue - var/is_muffled = (M in muffled_listeners) + var/is_muffled = (M.muffled || (M in muffled_listeners)) //Caustic Edit - Account for belly Muffling in sound effects! Neat? if(M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, repeat, is_muffled)) . += M diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 0f317a4cd53..db6fa07e244 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -208,6 +208,14 @@ GLOBAL_LIST_INIT(department_radio_keys, list( last_words = message message_mode = MODE_WHISPER_CRIT succumbed = TRUE + //Caustic Edit - Add in an attempt at the Psay message channel? + else if(message_mode == MODE_PSAY) //For now this just gets logged as a whisper + message_range = 0 + var/whisper_log_type = npc_speech ? LOG_NPC_SAY : LOG_WHISPER + src.log_talk(message, whisper_log_type) + send_thoughts(message, message_range, src, bubble_type, spans, language, message_mode, original_message) + return + //Caustic Edit End else var/log_type = npc_speech ? LOG_NPC_SAY : LOG_SAY src.log_talk(message, log_type, forced_by=forced) @@ -263,6 +271,31 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return 1 +//Caustic Edit - Add Psay for absorbed players and their pred! +/mob/living/proc/send_thoughts(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode, original_message) + var/list/listening = list() + var/mob/living/pred + if(absorbed && isbelly(loc)) + var/obj/belly/bloc = loc + pred = bloc.owner + else + pred = src + + if(pred.client) + listening |= pred + + for(var/obj/belly/B in pred.vore_organs) + for(var/mob/living/M in B.contents) + if(M.client && M.absorbed) + listening |= M + + log_seen(src, null, listening, original_message, SEEN_LOG_SAY) + + var/rendered = compose_message(src, message_language, message, , spans, message_mode) + for(var/mob/living/thinker in listening) + thinker.show_message(rendered) +//Caustic Edit End + /mob/living/proc/send_speech_sign(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode, original_message) var/static/list/eavesdropping_modes = list(MODE_WHISPER = TRUE, MODE_WHISPER_CRIT = TRUE) var/eavesdrop_range = 0 @@ -663,6 +696,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list( /mob/living/proc/radio(message, message_mode, list/spans, language) switch(message_mode) + if(MODE_PSAY) //Caustic Edit - Add in Psay here so that it also becomes Italics like whispers + return ITALICS if(MODE_WHISPER) return ITALICS if(MODE_R_HAND) @@ -686,6 +721,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list( . = verb_whisper else if(message_mode == MODE_WHISPER_CRIT) . = "[verb_whisper] in [p_their()] last breath" + else if(message_mode == MODE_PSAY) //Caustic Edit - Add in accounting for Psay and the 'thinks' action + . = verb_thinks else if(stuttering) . = "stammers" else if(derpspeech) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index b2768c8d7e3..4a80be505d0 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -147,8 +147,10 @@ */ /mob/proc/get_message_mode(message) var/key = copytext_char(message, 1, 2) - if(key == "#") - return MODE_WHISPER + if(key == "$" || (forced_psay && absorbed)) //Caustic Edit - Account for the absorbed and muffled effects from vorestuffs. Muffled forces a whisper! Psay is limited to absorbed mobs and the pred! + return MODE_PSAY + else if(key == "#" || muffled) + return MODE_WHISPER //Caustic Edit End else if(key == ";") return MODE_HEADSET else if(key == "%") diff --git a/modular_causticcove/code/__DEFINES/vore_liquid_defines.dm b/modular_causticcove/code/__DEFINES/vore_liquid_defines.dm index db8da5cf02e..1dad76cadc9 100644 --- a/modular_causticcove/code/__DEFINES/vore_liquid_defines.dm +++ b/modular_causticcove/code/__DEFINES/vore_liquid_defines.dm @@ -140,3 +140,5 @@ #define REAGENT_NUMBENZYME "Numbing Enzyme" #define REAGENT_ID_NUMBENZYME "numbenzyme" + +#define REAGENT_ID_POPPYMILK /datum/reagent/consumable/poppy_milk diff --git a/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm b/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm index 758a24d3b7a..95f459497b3 100644 --- a/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm @@ -95,7 +95,7 @@ GLOBAL_LIST_INIT(digest_modes, list()) consider_healthbar(L, old_health, B.owner) if(offset && damage_gain > 0) // If any different than default weight, multiply the % of offset. - if(B.show_liquids && B.reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && B.reagents.total_volume < B.reagents.maximum_volume) //digestion producing reagents + if(B.reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && B.reagents.total_volume < B.reagents.maximum_volume) //digestion producing reagents //Check previously had B.show_liquids && at the start? B.owner_adjust_nutrition(offset * (3 * damage_gain / difference) * L.get_digestion_nutrition_modifier() * B.owner.get_digestion_efficiency_modifier()) //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 B.digest_nutri_gain += offset * (1.5 * damage_gain / difference) * L.get_digestion_nutrition_modifier() * B.owner.get_digestion_efficiency_modifier() //for transfering nutrition value over to GenerateBellyReagents_digesting() B.GenerateBellyReagents_digesting() @@ -118,7 +118,7 @@ GLOBAL_LIST_INIT(digest_modes, list()) B.steal_nutrition(L) if(L.nutrition < 100) B.absorb_living(L) - if(B.show_liquids && B.reagent_mode_flags & DM_FLAG_REAGENTSABSORB && B.reagents.total_volume < B.reagents.maximum_volume) //absorption reagent production + if(B.reagent_mode_flags & DM_FLAG_REAGENTSABSORB && B.reagents.total_volume < B.reagents.maximum_volume) //absorption reagent production //Check previously had B.show_liquids && at the start? B.GenerateBellyReagents_absorbed() //A bonus for pred, I know for a fact prey is usually at zero nutrition when absorption finally happens consider_healthbar(L, old_nutrition, B.owner) return list("to_update" = TRUE) diff --git a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm index 7a14965f03e..05bd3ad92a3 100644 --- a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm @@ -210,9 +210,9 @@ var/mob/living/carbon/human/H = L //Numbing flag - if(mode_flags & DM_FLAG_NUMBING) //Caustic - I don't think we have this in actually. Might need to make a reagent with an effect? - if(H.reagents.get_reagent_amount(REAGENT_ID_NUMBENZYME) < 2) - H.reagents.add_reagent(REAGENT_ID_NUMBENZYME,4) + if(mode_flags & DM_FLAG_NUMBING) //Caustic - Attempting to use Poppymilk as a numbing substitution. + if(H.reagents.get_reagent_amount(REAGENT_ID_POPPYMILK) < 2) + H.reagents.add_reagent(REAGENT_ID_POPPYMILK, 4) //Worn items flag if(mode_flags & DM_FLAG_AFFECTWORN && H.contaminate_pref) From 61015968a33c803b471fdffb82727c3b8dd7f47d Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 25 Jun 2026 04:38:44 -0400 Subject: [PATCH 03/16] Tweak the Psay to only look for the first character! --- code/modules/mob/living/say.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index db6fa07e244..85fcf953404 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -86,7 +86,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE) var/talk_key = get_key(message) - var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE, MODE_SING = TRUE) + var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE, MODE_PSAY = TRUE, MODE_SING = TRUE) //Caustic Edit - Add Psay here so it doesn't trim the first character of your message! var/ic_blocked = FALSE if(client && !forced && CHAT_FILTER_CHECK(message)) From 080d46b9752c527903dca3897fb0371549f08433 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 25 Jun 2026 05:28:55 -0400 Subject: [PATCH 04/16] Cleaned up older comments left from the port-update work! --- modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm index 05bd3ad92a3..79bc6803a38 100644 --- a/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/bellymodes_vr.dm @@ -188,14 +188,14 @@ L.Stun(5) //Thickbelly flag - if((mode_flags & DM_FLAG_THICKBELLY) && !L.muffled) //Caustic - This likely should function like a gag? + if((mode_flags & DM_FLAG_THICKBELLY) && !L.muffled) //Caustic - Now forces whispers on say! L.muffled = TRUE //Fix muffled sometimes being sticky. else if(!(mode_flags & DM_FLAG_THICKBELLY) && L.muffled) L.muffled = FALSE //Force psay - if((mode_flags & DM_FLAG_FORCEPSAY) && !L.forced_psay && L.absorbed) //Caustic - This might be 'private say' in any case of PSAY, so subtle 'says' + if((mode_flags & DM_FLAG_FORCEPSAY) && !L.forced_psay && L.absorbed) //Caustic - Now has it's own private "thinking" chat between all prey and the pred who absorbed them! L.forced_psay = TRUE //Fix forcepsay sometimes being sticky. else if(!(mode_flags & DM_FLAG_FORCEPSAY) && L.forced_psay) From 0b9f96398ac2f43d0f5b30c28fd00219e2f6baf1 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 28 Jun 2026 05:18:28 -0400 Subject: [PATCH 05/16] I got inspired to add in the ability for someone to feed a noble for a buff to the food! Like the grapes, but bumps the quality of the food up by 1 level! --- code/modules/food_and_drinks/food/snacks.dm | 28 ++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index 5b9d7442853..ed7cf1c9063 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -383,19 +383,41 @@ All foods are distributed among various categories. Use common sense. eater.add_stress(/datum/stressevent/noble_desperate) if(eat_effect != /datum/status_effect/debuff/rotfood && eat_effect != /datum/status_effect/debuff/burnedfood && eat_effect != /datum/status_effect/debuff/uncookedfood) apply_effect = FALSE - if (FARE_POOR to FARE_NEUTRAL) + //Caustic Edit - If a noble is being fed, it will act as if it's 1 tier better! ... The worst case though is always bad. + if (FARE_POOR) eater.add_stress(/datum/stressevent/noble_bland_food) if (prob(25)) to_chat(eater, span_red("This is rather bland. I deserve better food than this...")) if(eat_effect != /datum/status_effect/debuff/rotfood && eat_effect != /datum/status_effect/debuff/burnedfood && eat_effect != /datum/status_effect/debuff/uncookedfood) apply_effect = FALSE + if (FARE_NEUTRAL) + if (isliving(src.loc)) + eater.remove_stress(/datum/stressevent/noble_bland_food) + if (prob(25)) + to_chat(eater, span_red("This food is plain, but to be fed... That makes up for it.")) + else + eater.add_stress(/datum/stressevent/noble_bland_food) + if (prob(25)) + to_chat(eater, span_red("This is rather bland. I deserve better food than this...")) + if(eat_effect != /datum/status_effect/debuff/rotfood && eat_effect != /datum/status_effect/debuff/burnedfood && eat_effect != /datum/status_effect/debuff/uncookedfood) + apply_effect = FALSE if (FARE_FINE) - eater.remove_stress(/datum/stressevent/noble_bland_food) + if (isliving(src.loc)) + eater.remove_stress(/datum/stressevent/noble_bland_food) + eater.add_stress(/datum/stressevent/noble_lavish_food) + if (prob(25)) + to_chat(eater, span_green("Ah, a fine meal, and doted on like this? Exquisite.")) + else + eater.remove_stress(/datum/stressevent/noble_bland_food) if (FARE_LAVISH) eater.remove_stress(/datum/stressevent/noble_bland_food) eater.add_stress(/datum/stressevent/noble_lavish_food) if (prob(25)) - to_chat(eater, span_green("Ah, food fit for my title.")) + if (isliving(src.loc)) + to_chat(eater, span_green("Oh! This is exellent! To be fed the most lavish of meals...")) + else + to_chat(eater, span_green("Ah, food fit for my title.")) + //Caustic Edit End // yeomen and courtiers are also used to a better quality of life but are way less picky if (human_eater.is_burgher() || human_eater.is_courtier()) From aa86cfa0996128d364db68976b575144f13f13cb Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 29 Jun 2026 21:14:18 -0400 Subject: [PATCH 06/16] Plug-in the In-Belly spawn hopefully! Update the Character Directory and the Examine Menu to make the RP Guidnace and RP Ads much more apparent they are there! Also the Directory now just shows you someone's examine closer panel instead! Ported that bit from OV. --- .../mob/living/carbon/human/examine_tgui.dm | 34 +++ interface/interface.dm | 22 +- modular_causticcove/code/datums/loadout.dm | 6 + .../character_directory.dm | 84 +++++- .../code/modules/vore/eating/inbelly_spawn.dm | 22 +- .../CharacterDirectoryList.tsx | 162 +++++++---- .../CharacterDirectoryViewCharacter.tsx | 1 + .../interfaces/CharacterDirectory/index.tsx | 267 ++++++++++++------ .../interfaces/CharacterDirectory/types.ts | 2 + .../packages/tgui/interfaces/ExaminePanel.tsx | 129 +++++++-- .../tgui/interfaces/ExaminePanelData.ts | 1 + .../tgui/interfaces/ExaminePanelPages.tsx | 4 +- 12 files changed, 536 insertions(+), 198 deletions(-) diff --git a/code/modules/mob/living/carbon/human/examine_tgui.dm b/code/modules/mob/living/carbon/human/examine_tgui.dm index aa4df94d908..b013491c340 100644 --- a/code/modules/mob/living/carbon/human/examine_tgui.dm +++ b/code/modules/mob/living/carbon/human/examine_tgui.dm @@ -34,6 +34,38 @@ ui = new(user, src, "ExaminePanel") ui.open() +//Caustic Edit - Grabbing the OV Character Ad addition to the Examine Panel! +/datum/examine_panel/proc/get_character_ad() + if(ishuman(holder)) + var/raw_character_ad = holder.client?.prefs?.directory_ad + if(isnull(raw_character_ad)) + raw_character_ad = holder.mind?.directory_ad + if(raw_character_ad) + return parsemarkdown_basic(html_encode(raw_character_ad), hyperlink = TRUE) + else if(pref?.directory_ad) + return parsemarkdown_basic(html_encode(pref.directory_ad), hyperlink = TRUE) + + return "" + +/proc/refresh_character_ad_examine_panels(mob/living/carbon/human/holder_mob, datum/preferences/holder_prefs, datum/mind/holder_mind) + for(var/datum/tgui/ui as anything in SStgui.all_uis) + if(!istype(ui?.src_object, /datum/examine_panel)) + continue + + var/datum/examine_panel/panel = ui.src_object + var/panel_matches_character = FALSE + + if(holder_mob && panel.holder == holder_mob) + panel_matches_character = TRUE + else if(holder_prefs && (panel.pref == holder_prefs || panel.holder?.client?.prefs == holder_prefs)) + panel_matches_character = TRUE + else if(holder_mind && panel.holder?.mind == holder_mind) + panel_matches_character = TRUE + + if(panel_matches_character) + ui.send_update() +//Caustic Edit End + /datum/examine_panel/familiar/ui_static_data(mob/user) //altered and condensed version used for familiars. sorry var/flavor_text @@ -92,6 +124,7 @@ /datum/examine_panel/familiar/ui_data(mob/user) var/list/data = list( + "character_ad" = "", //Casutic Edit - Adding in the Character Ad addition to the Examine Panel from OV "is_playing" = is_playing, ) return data @@ -202,6 +235,7 @@ /datum/examine_panel/ui_data(mob/user) var/list/data = list( + "character_ad" = get_character_ad(), //Casutic Edit - Adding in the Character Ad addition to the Examine Panel from OV "is_playing" = is_playing, ) return data diff --git a/interface/interface.dm b/interface/interface.dm index ce8f00f4fc7..7d1a76ad29c 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -228,22 +228,20 @@ Hotkey-Mode: (hotkey-mode must be on) if(!ishuman(mob)) return var/mob/living/carbon/human/C = mob - var/has_old_ad = FALSE - if(LAZYACCESS(GLOB.roleplay_ads,C.mobid)) - to_chat(C, span_info(LAZYACCESS(GLOB.roleplay_ads,C.mobid))) - has_old_ad = TRUE - var/msg = input("Set an advertisement for what kind of roleplay you are looking to engage in. Others will be able to see it with the Roleplay Ad (View) command. Do not abuse this. Leave empty and press OK to remove your roleplay ad.", "I LOVE TO ROLEPLAY") as message|null + //Caustic Edit - Grabbing the OV edit to move the RP ads into the Examine Panel and Character Directory! + var/current_ad = get_character_ad_value(C, C.client?.prefs, C.mind) + if(current_ad) + to_chat(C, span_info(current_ad)) + var/msg = input("Set an advertisement for what kind of roleplay you are looking to engage in. Others will be able to see it with the Roleplay Ad (View) command. Do not abuse this. Leave empty and press OK to remove your roleplay ad.", "I LOVE TO ROLEPLAY", current_ad) as message|null + if(isnull(msg)) + return + set_character_ad_value(C, C.client?.prefs, C.mind, msg, TRUE) if(msg) - LAZYSET(GLOB.roleplay_ads,C.mobid,"[C.real_name] - [msg]
") to_chat(C, span_info("Roleplay ad set.")) log_game("[C] has set their Roleplay Ad to '[msg]'.") - for(var/client/advertisee in (GLOB.clients - src)) - if(!(advertisee.prefs.toggles & ROLEPLAY_ADS)) - continue - to_chat(advertisee, span_info("[C.real_name] has set a roleplay ad.")) - else if(has_old_ad) - LAZYREMOVE(GLOB.roleplay_ads,C.mobid) + else to_chat(C, span_info("Roleplay ad removed.")) + //Caustic Edit End /client/verb/changefps() set category = "OPTIONS" diff --git a/modular_causticcove/code/datums/loadout.dm b/modular_causticcove/code/datums/loadout.dm index cd6c07e0484..d33fd63f6a5 100644 --- a/modular_causticcove/code/datums/loadout.dm +++ b/modular_causticcove/code/datums/loadout.dm @@ -116,3 +116,9 @@ name = "Artificer's cap" path = /obj/item/clothing/head/roguetown/articap +//Reform Gem option in the Loadout! + +/datum/loadout_item/reform_gem + name = "Reform Gem" + path = /obj/item/reformation_gem + cost = 0 //Make it free to grab! It's a scene tool after all. diff --git a/modular_causticcove/code/modules/character_directory/character_directory.dm b/modular_causticcove/code/modules/character_directory/character_directory.dm index 9010b6da571..a20265acaab 100644 --- a/modular_causticcove/code/modules/character_directory/character_directory.dm +++ b/modular_causticcove/code/modules/character_directory/character_directory.dm @@ -1,5 +1,37 @@ GLOBAL_DATUM(character_directory, /datum/character_directory) +/proc/get_character_ad_value(mob/living/carbon/human/character, datum/preferences/prefs, datum/mind/mind) + var/current_ad = prefs?.directory_ad + if(isnull(current_ad)) + current_ad = mind?.directory_ad + if(isnull(current_ad)) + current_ad = character?.client?.prefs?.directory_ad + if(isnull(current_ad)) + current_ad = character?.mind?.directory_ad + return current_ad + +/proc/set_character_ad_value(mob/living/carbon/human/character, datum/preferences/prefs, datum/mind/mind, new_value, notify_roleplay_viewers = FALSE) + if(prefs) + prefs.directory_ad = new_value + prefs.save_character() + if(mind) + mind.directory_ad = new_value + + if(character) + if(new_value) + var/formatted_ad = parsemarkdown_basic(html_encode(new_value), hyperlink = TRUE) + LAZYSET(GLOB.roleplay_ads, character.mobid, "[html_encode(character.real_name)] - [formatted_ad]
") + + if(notify_roleplay_viewers) + for(var/client/advertisee in (GLOB.clients - character.client)) + if(!(advertisee.prefs.toggles & ROLEPLAY_ADS)) + continue + to_chat(advertisee, span_info("[character.real_name] has set a roleplay ad.")) + else + LAZYREMOVE(GLOB.roleplay_ads, character.mobid) + + refresh_character_ad_examine_panels(character, prefs || character?.client?.prefs, mind || character?.mind) + /client/verb/show_character_directory() set name = "Character Directory" set category = "OOC" @@ -96,6 +128,16 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) var/ooc_notes_style = null*/ var/gendertag = null var/sexualitytag = null + var/rpguidance = null + switch(C.prefs.rp_guidance) + if(0) //Discourages Conflict + rpguidance = "Alternatives Preferred" + if(1) //Encourages Conflict + rpguidance = "Mechanics Willing" + if(2) //Same as normal. This can be changed in the future however if people wish. Encourages Conflict + Hunted. + rpguidance = "Mechanics Willing" + if(3) + rpguidance = "Unset" //var/eventtag = GLOB.vantag_choices_list[VANTAG_NONE] var/flavor_text = null var/custom_link = null @@ -106,14 +148,14 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) if (C.mob?.mind) //could use ternary for all three but this is more efficient tag = C.mob.mind.directory_tag || "Unset" erptag = C.mob.mind.directory_erptag || "Unset" - character_ad = C.mob.mind.directory_ad + character_ad = get_character_ad_value(C.mob, C.prefs, C.mob.mind) gendertag = C.mob.mind.directory_gendertag || "Unset" sexualitytag = C.mob.mind.directory_sexualitytag || "Unset" //eventtag = GLOB.vantag_choices_list[C.mob.mind.vantag_preference] else tag = C.prefs.directory_tag || "Unset" erptag = C.prefs.directory_erptag || "Unset" - character_ad = C.prefs.directory_ad + character_ad = get_character_ad_value(null, C.prefs, null) gendertag = C.prefs.directory_gendertag || "Unset" sexualitytag = C.prefs.directory_sexualitytag || "Unset" //eventtag = GLOB.vantag_choices_list[C.prefs.vantag_preference] @@ -180,8 +222,11 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) // But if we can't find the name, they must be using a non-compatible mob type currently. if(!name) continue + if(character_ad) + character_ad = parsemarkdown_basic(html_encode(character_ad), hyperlink = TRUE) directory_mobs.Add(list(list( + "ckey" = C.ckey, "name" = name, "species" = species, /*"ooc_notes_favs" = ooc_notes_favs, @@ -191,6 +236,7 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) "ooc_notes_style" = ooc_notes_style,*/ "gendertag" = gendertag, "sexualitytag" = sexualitytag, + "rpguidance" = rpguidance, //"eventtag" = eventtag, "ooc_notes" = ooc_notes, "tag" = tag, @@ -219,9 +265,35 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) ui.user.setClickCooldown(10) update_static_data(ui.user, ui) return TRUE + else if(action == "openExamine") + return open_character_examine(ui.user, params["ckey"], params["open_ad"]) else return check_for_mind_or_prefs(ui.user, action, params["overwrite_prefs"]) +/datum/character_directory/proc/open_character_examine(mob/user, target_ckey, open_ad = FALSE) + if(!user || !target_ckey) + return FALSE + + var/client/target_client = GLOB.directory[target_ckey] + if(!target_client) + to_chat(user, span_warning("That character is no longer available. Try refreshing the directory.")) + return FALSE + + var/datum/examine_panel/character_examine_panel + if(ishuman(target_client.mob)) + character_examine_panel = new(target_client.mob) + character_examine_panel.holder = target_client.mob + else if(target_client.prefs) + character_examine_panel = new + character_examine_panel.pref = target_client.prefs + else + to_chat(user, span_warning("That character does not currently have profile data available.")) + return FALSE + + character_examine_panel.viewing = user + character_examine_panel.ui_interact(user) + return TRUE + /datum/character_directory/proc/check_for_mind_or_prefs(mob/user, action, overwrite_prefs) if (!user.client) return @@ -251,7 +323,7 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) to_chat(user, span_notice("You are now [!visible ? "shown" : "not shown"] in the directory.")) return set_for_mind_or_prefs(user, action, !visible, can_set_prefs, can_set_mind) if ("editAd") - var/current_ad = (can_set_mind ? user.mind.directory_ad : null) || (can_set_prefs ? user.client.prefs.directory_ad : null) + var/current_ad = get_character_ad_value(user, can_set_prefs ? user.client.prefs : null, can_set_mind ? user.mind : null) var/new_ad = tgui_input_text(user, "Change your character ad", "Character Ad", current_ad, MAX_MESSAGE_LEN, TRUE, prevent_enter = TRUE) if(isnull(new_ad)) return @@ -304,11 +376,7 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) user.mind.show_in_directory = new_value return TRUE if ("editAd") - if (can_set_prefs) - user.client.prefs.directory_ad = new_value - user.client.prefs.save_character() - if (can_set_mind) - user.mind.directory_ad = new_value + set_character_ad_value(user, can_set_prefs ? user.client.prefs : null, can_set_mind ? user.mind : null, new_value) return TRUE /*if ("setEventTag") if (can_set_prefs) diff --git a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm index 878d1a6a23b..be0678b5728 100644 --- a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm +++ b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm @@ -95,11 +95,29 @@ if(absorbed) target_belly.absorb_living(new_character) // Glorp. - log_admin("[prey] (as [new_character.real_name] has spawned inside one of [pred]'s bellies.") // Log it. Avoid abuse. - message_admins("[prey] (as [new_character.real_name] has spawned inside one of [pred]'s bellies.", 1) + log_admin("[prey] (as [new_character.real_name]) has spawned inside one of [pred]'s bellies.") // Log it. Avoid abuse. + message_admins("[prey] (as [new_character.real_name]) has spawned inside one of [pred]'s bellies.", 1) return new_character // incase its ever needed +/mob/dead/observer + var/enable_inbelly_spawn_attempts = FALSE + +/mob/dead/observer/verb/ToggleInBellySpawnAttempts() + set name = "Toggle In-Belly Spawn" + set desc = "Toggles the ability to attempt to In-Belly spawn on someone on Middle Mouse Click. Defaults to off to not cause any accidents!" + set category = "VORE" + + enable_inbelly_spawn_attempts = !enable_inbelly_spawn_attempts + to_chat(src, span_notice("In-Belly spawn attempts [enable_inbelly_spawn_attempts ? "enabled! Middle-Mouse click on your pred to request a spawn (if they have it set up!)" : "disabled! Middle-Mouse clicks will revert to their usual actions."]")) + +/mob/dead/observer/MiddleClickOn(atom/A, params) + if(enable_inbelly_spawn_attempts && isliving(A)) + var/mob/living/alive = A + alive.inbelly_spawn_prompt(src) + else + . = ..() + /*/mob/living/proc/soulcatcher_spawn_prompt(mob/observer/dead/prey, req_time) //We don't have soulcatchers or NIFs if(tgui_alert(src, "[prey.name] wants to join into your Soulcatcher.","Soulcatcher Request",list("Deny", "Allow"), timeout=1 MINUTES) != "Allow") to_chat(prey, span_warning("[src] has denied your request.")) diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx index 6b7ca45fb5d..b6bdb154c19 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx @@ -8,14 +8,15 @@ import type { mobEntry } from './types'; export const CharacterDirectoryList = (props: { directory: mobEntry[]; - onOverlay: React.Dispatch>; + onOpenAd: (name: string, ad: string) => void; }) => { const { act } = useBackend(); - const { onOverlay, directory } = props; + const { directory, onOpenAd } = props; const [sortId, setSortId] = useState('name'); const [sortOrder, setSortOrder] = useState(true); + const [hoveredAction, setHoveredAction] = useState(null); return (
- Photo + + Photo + ERP Tag + + RP Guidance + + + RP Ad + View @@ -92,55 +107,98 @@ export const CharacterDirectoryList = (props: { const i = sortOrder ? 1 : -1; return a[sortId].localeCompare(b[sortId]) * i; }) - .map((character, i) => ( - - - {character.photo ? ( - - - - - - ) : null} - - - {character.name} - - - {character.species} - - {character.tag} - - {character.gendertag} - - - {character.sexualitytag} - - {character.erptag} - - - - - ))} + .map((character, i) => { + const hasCharacterAd = !!character.character_ad?.trim(); + const adActionId = `${character.ckey}-ad`; + const viewActionId = `${character.ckey}-view`; + + return ( + + + {character.photo ? ( + + + + + + ) : null} + + + {character.name} + + + {character.species} + + + {character.tag} + + + {character.gendertag} + + + {character.sexualitytag} + + + {character.erptag} + + + {character.rpguidance} + + +
); diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx index 09b1663df21..614c9d10875 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryViewCharacter.tsx @@ -1,3 +1,4 @@ +// Old/redundant in-directory description renderer retained for reference. import { Box, Button, Section, Table } from 'tgui-core/components'; import { MarkdownSpoilerText } from '../common/SpoilerText'; import { getTagColor } from './constants'; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx index a4524e6078c..bb25162f894 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/index.tsx @@ -1,11 +1,13 @@ -import { useState } from 'react'; +import { useMemo, useState } from 'react'; import { useBackend } from 'tgui/backend'; import { Window } from 'tgui/layouts'; import { Box, Button, LabeledList, Section, Stack } from 'tgui-core/components'; import { CharacterDirectoryList } from './CharacterDirectoryList'; -import { ViewCharacter } from './CharacterDirectoryViewCharacter'; -import type { Data, mobEntry } from './types'; +import type { Data } from './types'; + +const CHARACTER_DIRECTORY_WINDOW_WIDTH = Math.round(816 * 1.15); +const CHARACTER_DIRECTORY_WINDOW_HEIGHT = Math.round(722 * 1.15); export const CharacterDirectory = (props) => { const { act, data } = useBackend(); @@ -19,109 +21,186 @@ export const CharacterDirectory = (props) => { directory, } = data; - const [overlay, setOverlay] = useState(null); const [overwritePrefs, setOverwritePrefs] = useState(true); + const [directoryAd, setDirectoryAd] = useState(null); + const [directoryAdName, setDirectoryAdName] = useState(''); + const directoryAdHTML = useMemo(() => ({ + __html: directoryAd || '', + }), [directoryAd]); + const closeDirectoryAd = () => { + setDirectoryAd(null); + setDirectoryAdName(''); + }; return ( - + + {/* + Old/redundant in-directory description overlay retained for reference. + We now open the shared Examine Panel instead so directory views match + in-person "Examine closer" rendering. + {(overlay && ( )) || ( - <> -
- - - Save to current preferences slot:  - - - - - - - } - > - - - - - + */} + +
+ + + Save to current preferences slot:  + + + - - - - - - - - - - - - - - -
- - + + + } + > + + + + + + + + + + + + + + + + + + + + +
+ { + setDirectoryAdName(name); + setDirectoryAd(ad); + }} + /> + + {/* )} + */}
+ {!!directoryAd?.trim() && ( + +
+ Close + + } + > + + + +
+
+ )}
); }; diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts b/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts index 58bd11778c8..57a828c3b6c 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/types.ts @@ -11,6 +11,7 @@ export type Data = { }; export type mobEntry = { + ckey: string; name: string; species: string; ooc_notes_favs: string; @@ -20,6 +21,7 @@ export type mobEntry = { ooc_notes_style: BooleanLike; gendertag: string; sexualitytag: string; + rpguidance: string; eventtag: string; ooc_notes: string; tag: string; diff --git a/tgui/packages/tgui/interfaces/ExaminePanel.tsx b/tgui/packages/tgui/interfaces/ExaminePanel.tsx index ff4f3bc2813..cbc1c7fc2ea 100644 --- a/tgui/packages/tgui/interfaces/ExaminePanel.tsx +++ b/tgui/packages/tgui/interfaces/ExaminePanel.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react'; -import { Button, Stack } from 'tgui-core/components'; +import { useEffect, useMemo, useState } from 'react'; +import { Box, Button, Section, Stack } from 'tgui-core/components'; import { useBackend } from '../backend'; import { PageButton } from '../components/PageButton'; @@ -14,9 +14,20 @@ enum Page { export const ExaminePanel = (props) => { const { act, data } = useBackend(); - const { is_vet, is_donator, character_name, is_playing, has_song, img_gallery, nsfw_img_gallery, examine_theme } = data; + const { is_donator, is_vet, character_name, is_playing, has_song, img_gallery, nsfw_img_gallery, examine_theme, character_ad } = data; const [currentPage, setCurrentPage] = useState(Page.FlavorText); + const [showCharacterAd, setShowCharacterAd] = useState(false); const hasAnyGalleryImages = img_gallery.length > 0 || nsfw_img_gallery.length > 0; + const hasCharacterAd = !!character_ad?.trim(); + const characterAdHTML = useMemo(() => ({ + __html: `${character_ad || ''}`, + }), [character_ad]); + + useEffect(() => { + if (showCharacterAd && !hasCharacterAd) { + setShowCharacterAd(false); + } + }, [showCharacterAd, hasCharacterAd]); let pageContents; @@ -51,6 +62,18 @@ export const ExaminePanel = (props) => { /> )} + } + > + + + )} - {hasAnyGalleryImages && ()} - - {pageContents} - - +
); diff --git a/tgui/packages/tgui/interfaces/ExaminePanelData.ts b/tgui/packages/tgui/interfaces/ExaminePanelData.ts index 34c52f53e8d..062e4b1339d 100644 --- a/tgui/packages/tgui/interfaces/ExaminePanelData.ts +++ b/tgui/packages/tgui/interfaces/ExaminePanelData.ts @@ -17,4 +17,5 @@ export type ExaminePanelData = { is_donator: boolean; // is_naked: boolean; // Caustic Edit: Removes naked requirement to view NSFW flavortext examine_theme: string | null; + character_ad: string; }; diff --git a/tgui/packages/tgui/interfaces/ExaminePanelPages.tsx b/tgui/packages/tgui/interfaces/ExaminePanelPages.tsx index bcb3ba4ff2f..44f634fb8fc 100644 --- a/tgui/packages/tgui/interfaces/ExaminePanelPages.tsx +++ b/tgui/packages/tgui/interfaces/ExaminePanelPages.tsx @@ -150,10 +150,10 @@ export const ImageGalleryPage = (props) => { const { img_gallery, nsfw_img_gallery, - is_naked, + //is_naked, // Caustic Edit: Removes naked requirement to view NSFW flavortext } = data; const [galleryIndex, setGalleryIndex] = useState('SFW'); - const canViewNsfwGallery = is_naked && nsfw_img_gallery.length > 0; + const canViewNsfwGallery = nsfw_img_gallery.length > 0; //is_naked && nsfw_img_gallery.length > 0; // Caustic Edit: Removes naked requirement to view NSFW flavortext useEffect(() => { if (galleryIndex === 'NSFW' && !canViewNsfwGallery) { From 69c221be278765237fa5664209eb8d5495b34db8 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 29 Jun 2026 23:06:23 -0400 Subject: [PATCH 07/16] Healbelly and Digestion Fixes. They now should work properly, and account for the code differences. --- .../baycode_port_helpers.dm | 2 +- .../vore/eating/bellymodes_datum_vr.dm | 78 ++++++++++++------- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/modular_causticcove/code/modules/baycode_port_helpers/baycode_port_helpers.dm b/modular_causticcove/code/modules/baycode_port_helpers/baycode_port_helpers.dm index 45d10ede507..ef4e1d218ca 100644 --- a/modular_causticcove/code/modules/baycode_port_helpers/baycode_port_helpers.dm +++ b/modular_causticcove/code/modules/baycode_port_helpers/baycode_port_helpers.dm @@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(icon_state_lists) return health /mob/living/carbon/human/getActualFuckingHealth() - return health //getMaxHealth() - ((getBruteLoss() + getFireLoss() + getToxLoss() + getOxyLoss())) + return getMaxHealth() - getCloneLoss() //getMaxHealth() - ((getBruteLoss() + getFireLoss() + getToxLoss() + getOxyLoss())) /mob/living/proc/nutrition_percent() return 100 * nutrition / maxnutrition diff --git a/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm b/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm index 95f459497b3..6ca66dda0e0 100644 --- a/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/bellymodes_datum_vr.dm @@ -47,7 +47,7 @@ GLOBAL_LIST_INIT(digest_modes, list()) if(!L) return - //Parasitic digestion immunity hook, used to be a synx istype check but this is more optimized. + //Parasitic digestion immunity hook, used to be a synx istype check but this is more optimized. if(L.parasitic) if(isliving(L)) var/paratox = B.digest_brute+B.digest_burn @@ -61,30 +61,39 @@ GLOBAL_LIST_INIT(digest_modes, list()) // Deal digestion damage (and feed the pred) var/old_health = L.getActualFuckingHealth() - var/old_brute = L.getBruteLoss() - var/old_burn = L.getFireLoss() - var/old_oxy = L.getOxyLoss() - var/old_tox = L.getToxLoss() + //var/old_brute = L.getBruteLoss() + //var/old_burn = L.getFireLoss() + //var/old_oxy = L.getOxyLoss() + //var/old_tox = L.getToxLoss() var/old_clone = L.getCloneLoss() + L.adjustBruteLoss(B.digest_brute) L.adjustFireLoss(B.digest_burn) - L.adjustOxyLoss(B.digest_oxy) - L.adjustToxLoss(B.digest_tox) - L.adjustCloneLoss(B.digest_clone) - - if(old_brute > (L.maxHealth * 4.5) || old_burn > (L.maxHealth * 4.5)) //Bandaid Patch for unkillable mobs? Potentially just set the OxyLoss to 200 for one tick, which WILL kill them. - L.adjustOxyLoss(200, forced = TRUE) + //L.adjustOxyLoss(B.digest_oxy) + //L.adjustToxLoss(B.digest_tox) + //L.adjustCloneLoss(B.digest_clone) + + //if(old_brute > (L.maxHealth * 4.5) || old_burn > (L.maxHealth * 4.5)) //Bandaid Patch for unkillable mobs? Potentially just set the OxyLoss to 200 for one tick, which WILL kill them. + // L.adjustOxyLoss(200, forced = TRUE) + if(B.digest_brute > 1 || B.digest_burn > 1) + var/clone_dam = ((B.digest_brute + B.digest_burn) / B.digest_max) * 10 //At Max Digest, it will kill in 200/10 process ticks + L.adjustCloneLoss(clone_dam) + if(L.getCloneLoss() >= (L.maxHealth * 2) && !HAS_TRAIT(src, TRAIT_NODEATH)) + L.death() + L.cure_blind(UNCONSCIOUS_BLIND) //L.attempt_multishock(SHOCKFLAG_DIGESTION) //I don't believe this is in this codebase? // Send a message when a prey-thing enters hard crit. if(iscarbon(L) && old_health > 0 && L.getActualFuckingHealth() <= 0) to_chat(B.owner, span_notice("You feel [L] go still within your [lowertext(B.name)].")) - var/actual_brute = L.getBruteLoss() - old_brute - var/actual_burn = L.getFireLoss() - old_burn - var/actual_oxy = L.getOxyLoss() - old_oxy - var/actual_tox = L.getToxLoss() - old_tox + + //var/actual_brute = L.getBruteLoss() - old_brute + //var/actual_burn = L.getFireLoss() - old_burn + //var/actual_oxy = L.getOxyLoss() - old_oxy + //var/actual_tox = L.getToxLoss() - old_tox var/actual_clone = L.getCloneLoss() - old_clone - var/damage_gain = (actual_brute + actual_burn + actual_oxy/2 + actual_tox + actual_clone*2)*(B.nutrition_percent / 100) + //var/damage_gain = (actual_brute + actual_burn + actual_oxy/2 + actual_tox + actual_clone*2)*(B.nutrition_percent / 100) + var/damage_gain = (actual_clone*2)*(B.nutrition_percent / 100) if(B.slow_digestion) damage_gain = damage_gain * 0.5 var/offset = (1 + ((L.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02 @@ -188,21 +197,34 @@ GLOBAL_LIST_INIT(digest_modes, list()) var/oldstat = L.stat if(L.stat == DEAD || !L.permit_healbelly) //healpref check return null // Can't heal the dead with healbelly + //var/mob/living/carbon/human/H = L - if(B.owner.nutrition > 90 && (L.getActualFuckingHealth() < L.getMaxHealth())) - L.adjustBruteLoss(-2.5) - L.adjustFireLoss(-2.5) - L.adjustToxLoss(-5) - L.adjustOxyLoss(-5) - L.adjustCloneLoss(-1.25) - B.owner.adjust_nutrition(-2) - if(B.health_impacts_size) - B.owner.handle_belly_update() + if(B.owner.nutrition > 90) + var/heal_actions = 0 + if(L.health < L.getMaxHealth()) + L.adjustBruteLoss(-2.5) + L.adjustFireLoss(-2.5) + L.adjustToxLoss(-5) + L.adjustOxyLoss(-5) + L.adjustCloneLoss(-1.25) + heal_actions += 1 if(L.nutrition <= 400) L.adjust_nutrition(1) - else if(B.owner.nutrition > 90 && (L.nutrition <= 400)) - B.owner.adjust_nutrition(-1) - L.adjust_nutrition(1) + heal_actions += 1 + if(L.blood_volume < BLOOD_VOLUME_NORMAL) + L.blood_volume = min(L.blood_volume+2.5, BLOOD_VOLUME_NORMAL) + heal_actions += 1 + var/list/wCount = L.get_wounds() + if(length(wCount)) + L.heal_wounds(2.5) + L.update_damage_overlays() + heal_actions += 1 + + if(heal_actions > 0) + B.owner.adjust_nutrition(-heal_actions) + if(B.health_impacts_size) + B.owner.handle_belly_update() + if(L.stat != oldstat) return list("to_update" = TRUE) From 4d9c651e0986c5de7b933edfcf4b5aaab9a392a4 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 29 Jun 2026 23:33:44 -0400 Subject: [PATCH 08/16] Add in a quick button to access the Character Directory on any examine! As long as you get the Examine Closer option :P --- code/modules/mob/living/carbon/human/examine.dm | 2 +- code/modules/mob/living/carbon/human/human_topic.dm | 6 ++++++ code/modules/mob/living/simple_animal/friendly/familiars.dm | 2 +- .../modules/mob/living/simple_animal/simple_animal_topic.dm | 6 ++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 9d71f818814..d3864dcd2e6 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -1044,7 +1044,7 @@ showassess = TRUE if((!obscure_name || client?.prefs.masked_examine) && (flavortext || headshot_link || ooc_notes)) - . += "Examine closer [showassess ? " | Assess" : ""]" + . += "Examine closer [showassess ? "| Assess " : ""]| Character Directory" /// Rumours & Gossip if(length(rumour) || length(noble_gossip)) diff --git a/code/modules/mob/living/carbon/human/human_topic.dm b/code/modules/mob/living/carbon/human/human_topic.dm index 969eee26421..e8da9195168 100644 --- a/code/modules/mob/living/carbon/human/human_topic.dm +++ b/code/modules/mob/living/carbon/human/human_topic.dm @@ -16,6 +16,12 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013??? mob_examine_panel.viewing = usr mob_examine_panel.ui_interact(usr) return + + if(href_list["task"] == "open_directory") + if(!ismob(usr) || !client) + return + client.show_character_directory() + return if(href_list["inspect_limb"] && (observer_privilege || usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY))) var/list/msg = list() diff --git a/code/modules/mob/living/simple_animal/friendly/familiars.dm b/code/modules/mob/living/simple_animal/friendly/familiars.dm index a81bbbf15a4..bd2056c8bab 100644 --- a/code/modules/mob/living/simple_animal/friendly/familiars.dm +++ b/code/modules/mob/living/simple_animal/friendly/familiars.dm @@ -174,7 +174,7 @@ if((valid_headshot_link(src, prefs.familiar_headshot_link[planar_origin], TRUE)) && (user.client?.prefs.chatheadshot)) ret.Insert(2, "") if(prefs.familiar_flavortext_display[planar_origin] || prefs.familiar_headshot_link[planar_origin] || prefs.familiar_ooc_notes_display[planar_origin]) - ret.Insert(ret.len-1, "Examine closer") + ret.Insert(ret.len-1, "Examine closer | Character Directory") return ret // mobility/utility focused. innocuous. can fly, and brew potions, but not much else diff --git a/code/modules/mob/living/simple_animal/simple_animal_topic.dm b/code/modules/mob/living/simple_animal/simple_animal_topic.dm index c53b4b777ce..9b739918ca9 100644 --- a/code/modules/mob/living/simple_animal/simple_animal_topic.dm +++ b/code/modules/mob/living/simple_animal/simple_animal_topic.dm @@ -36,4 +36,10 @@ mob_examine_panel.viewing = usr mob_examine_panel.ui_interact(usr) return + + if(href_list["task"] == "open_directory") + if(!ismob(usr) || !client) + return + client.show_character_directory() + return From 92ee20b0c8a310ebf6b95f8907a217ab0a9e487c Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 30 Jun 2026 04:52:01 -0400 Subject: [PATCH 09/16] Trying to clean it up a bit, get the Inbelly fully mimicking the latejoin minus actually having a job/role assigned. Trying to disable hoblingoblin the map from spawning cause it's being WEIRD and constantly erroring now and again... Attempt to add a backup to init the rp_guidance since somehow some people have it null? --- .../dungeon_templates/rooms/common.dm | 4 ++-- code/modules/client/preferences_savefile.dm | 3 +++ .../character_directory/character_directory.dm | 4 ++-- .../code/modules/vore/eating/inbelly_spawn.dm | 12 ++++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/code/datums/dungeon_generator/dungeon_templates/rooms/common.dm b/code/datums/dungeon_generator/dungeon_templates/rooms/common.dm index 01541893138..43aa9a41bea 100644 --- a/code/datums/dungeon_generator/dungeon_templates/rooms/common.dm +++ b/code/datums/dungeon_generator/dungeon_templates/rooms/common.dm @@ -426,7 +426,7 @@ east_offset = 18 south_offset = 26 -/datum/map_template/dungeon/room/hoblingoblin +/*/datum/map_template/dungeon/room/hoblingoblin //Caustic Edit - Lets try commenting this out and seeing if it stops the errors... mappath = "_maps/dungeon_generator/room/hoblingoblin.dmm" id = "hoblin_goblin" width = 24 @@ -435,7 +435,7 @@ north_offset = 11 south_offset = 11 east_offset = 11 - west_offset = 11 + west_offset = 11*/ /datum/map_template/dungeon/room/bathhouse_custom width = 20 diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 312b6bd349f..ee1199f0f75 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -227,6 +227,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["audio_preload"] >> audio_preload S["rp_guidance"] >> rp_guidance + + if(!rp_guidance) + rp_guidance = 3 //Reset it to default if it's somehow null. ///Caustic edit end // Custom hotkeys S["key_bindings"] >> key_bindings diff --git a/modular_causticcove/code/modules/character_directory/character_directory.dm b/modular_causticcove/code/modules/character_directory/character_directory.dm index a20265acaab..4acb4fbed69 100644 --- a/modular_causticcove/code/modules/character_directory/character_directory.dm +++ b/modular_causticcove/code/modules/character_directory/character_directory.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) var/ooc_notes_style = null*/ var/gendertag = null var/sexualitytag = null - var/rpguidance = null + var/rpguidance = "Unset" switch(C.prefs.rp_guidance) if(0) //Discourages Conflict rpguidance = "Alternatives Preferred" @@ -137,7 +137,7 @@ GLOBAL_LIST_EMPTY(chardirectory_photos) if(2) //Same as normal. This can be changed in the future however if people wish. Encourages Conflict + Hunted. rpguidance = "Mechanics Willing" if(3) - rpguidance = "Unset" + rpguidance = "Neutral" //var/eventtag = GLOB.vantag_choices_list[VANTAG_NONE] var/flavor_text = null var/custom_link = null diff --git a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm index be0678b5728..d514984c7d3 100644 --- a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm +++ b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm @@ -2,6 +2,10 @@ if(!potential_prey || !istype(potential_prey)) // Did our prey cease to exist? return + if(!potential_prey.started_as_observer) //Lets check this, just to be sure no one spawns over and over this way... You gotta at least go to the main menu and observe to in-belly spawn. + to_chat(potential_prey, span_notice("In order to In-Belly Spawn, you need to join the round as an observer. Please don't attempt to use this as a free respawn!")) + return + // Are we cool with this prey spawning in at all? var/answer = tgui_alert(src, "[potential_prey.client.prefs.real_name] wants to spawn in one of your bellies. Do you accept?", "Inbelly Spawning", list("Yes", "No")) if(answer != "Yes") @@ -86,7 +90,15 @@ joined_area.on_joining_game(new_character) new_character.update_fov_angles() + if(new_character.dna?.species) + new_character.dna.species.after_creation(new_character) + new_character.roll_stats() //This hopefully does not runtime, as it appears it properly checks for if the new player is null first. + GLOB.chosen_names += new_character.real_name + new_character.islatejoin = TRUE + SSticker.minds += new_character.mind //Is this what is needed to handle skill gain? + GLOB.joined_player_list += new_character.ckey + update_wretch_slots() new_character.regenerate_icons() new_character.update_transform() From e80c1f2bb47306b1805deb6fe3fc2ed542da0fc8 Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 30 Jun 2026 05:10:20 -0400 Subject: [PATCH 10/16] No more WOE! DIRECTORY BE UPON THEE! ... Now it actually opens it for the user, and not the examined person, oopsie :3 --- code/modules/mob/living/carbon/human/human_topic.dm | 4 ++-- code/modules/mob/living/simple_animal/simple_animal_topic.dm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_topic.dm b/code/modules/mob/living/carbon/human/human_topic.dm index e8da9195168..5723061a5d5 100644 --- a/code/modules/mob/living/carbon/human/human_topic.dm +++ b/code/modules/mob/living/carbon/human/human_topic.dm @@ -18,9 +18,9 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013??? return if(href_list["task"] == "open_directory") - if(!ismob(usr) || !client) + if(!ismob(usr) || !usr.client) return - client.show_character_directory() + usr.client.show_character_directory() return if(href_list["inspect_limb"] && (observer_privilege || usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY))) diff --git a/code/modules/mob/living/simple_animal/simple_animal_topic.dm b/code/modules/mob/living/simple_animal/simple_animal_topic.dm index 9b739918ca9..ec8f9716255 100644 --- a/code/modules/mob/living/simple_animal/simple_animal_topic.dm +++ b/code/modules/mob/living/simple_animal/simple_animal_topic.dm @@ -38,8 +38,8 @@ return if(href_list["task"] == "open_directory") - if(!ismob(usr) || !client) + if(!ismob(usr) || !usr.client) return - client.show_character_directory() + usr.client.show_character_directory() return From 8891bcfa437a441d4eae311072722adc08be1f8d Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 30 Jun 2026 21:52:07 -0400 Subject: [PATCH 11/16] Buckling can be done from adjacent tiles! Also potentially fixed the Whisper and Yell issues? --- code/game/objects/buckling.dm | 4 ++-- code/modules/mob/living/say.dm | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 68dfb585313..23c0ddc1fbc 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -46,7 +46,7 @@ if(!istype(M)) return FALSE - if(check_loc && M.loc != loc) + if(check_loc && !Adjacent(M)) //M.loc != loc //Caustic Edit - Lets see if we can't just tweak this to allow for 1-tile-away buckles? return FALSE if((!can_buckle && !force) || M.buckled || (buckled_mobs.len >= max_buckled_mobs) || (buckle_requires_restraints && !M.restrained()) || M == src) @@ -74,7 +74,7 @@ else if(isliving(M.pulledby)) M.reset_offsets("pulledby") - if(!check_loc && M.loc != loc) + if(M.loc != loc) //Caustic Edit - Removed this check !check_loc && - so it'll just always check and move the player if needed. M.forceMove(loc) M.buckling = null diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 85fcf953404..dd1e153d7e7 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -528,7 +528,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list( continue if(!(M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off continue - if(!is_in_zweb(src.z,tocheck.z)) + var/turf/tocheck_turf = get_turf(tocheck) //Caustic Edit - Change it so whispers can be sent regardless of something/someone being in a container! + if(!is_in_zweb(speaker_turf.z,tocheck_turf.z)) continue listening |= M the_dead[M] = TRUE @@ -554,7 +555,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( listener_has_ceiling = FALSE if(!hearall) if((!Zs_too && !isobserver(AM)) || message_mode == MODE_WHISPER) - if(AM.z != src.z) + if(listener_turf.z != speaker_turf.z) //Caustic Edit - This should fix whispers not comparing the actual TILES. continue if(Zs_too && listener_turf.z != speaker_turf.z && !Zs_all) if(!Zs_yell && !HAS_TRAIT(AM, TRAIT_KEENEARS) && !hearall) @@ -573,12 +574,14 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(!speaker_has_ceiling && isliving(AM)) var/mob/living/M = AM for(var/mob/living/MH in viewers(world.view, speaker_ceiling)) - if(M == MH && MH.z == speaker_ceiling?.z) + var/turf/MH_turf = get_turf(MH) + if(M == MH && MH_turf.z == speaker_ceiling?.z) //Caustic Edit - This should fix whispers not comparing the actual TILES. speaker_obstructed = FALSE if(!listener_has_ceiling) for(var/mob/living/ML in viewers(world.view, listener_ceiling)) - if(ML == src && ML.z == listener_ceiling?.z) + var/turf/ML_turf = get_turf(ML) + if(ML == src && ML_turf.z == listener_ceiling?.z) //Caustic Edit - This should fix whispers not comparing the actual TILES. listener_obstructed = FALSE if(listener_obstructed && speaker_obstructed) continue From 62b77a51af2e9c0faa01ed0d6b53e782edd1bd2e Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 30 Jun 2026 22:47:06 -0400 Subject: [PATCH 12/16] Allow for nomming (up to 6) items that are 1x2 or smaller into one belly. Can nom a smeltable item directly into a smelter belly as well! Thrown items now follow the same restrictions as long as Trash Eater is active! Can no longer combat-nom NPCs until they are in soft crit or worse. --- .../code/datums/spontaneous_vore.dm | 9 ++++---- .../code/modules/vore/eating/living_vr.dm | 22 +++++++++++++++++-- .../code/modules/vore/eating/vore_procs.dm | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/modular_causticcove/code/datums/spontaneous_vore.dm b/modular_causticcove/code/datums/spontaneous_vore.dm index 35f709c4b39..331a1ef259f 100644 --- a/modular_causticcove/code/datums/spontaneous_vore.dm +++ b/modular_causticcove/code/datums/spontaneous_vore.dm @@ -83,10 +83,11 @@ if(!destination_belly) return if(source.stat != DEAD && source.trash_catching) - if(source.adminbus_trash || /*is_type_in_list(O, GLOB.edible_trash) &&*/ O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist)) //Caustic - It's still in here if we need a check for a whitelist for stuff ate, but... technically people have been doing that with all items so far. Maybe it's fine to keep it that way? - source.visible_message(span_warning("[O] is thrown directly into [source]'s [lowertext(destination_belly.name)]!")) - destination_belly.nom_atom(O) - return COMSIG_CANCEL_HITBY + if(length(vore_selected.contents) < 6) //Lets add a limiter to how many items can be in one belly, sure someone can abuse it by making many... but that's a player issue we can deal with. + if(source.adminbus_trash || destination_belly.validate_item_size(O) ||/*is_type_in_list(O, GLOB.edible_trash) &&*/ O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist)) //Caustic - Trash Eatable was unused really, we'd otherwise have to go through and add it in to all items. + source.visible_message(span_warning("[O] is thrown directly into [source]'s [lowertext(destination_belly.name)]!")) + destination_belly.nom_atom(O) + return COMSIG_CANCEL_HITBY //Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred. if(isliving(hitby)) diff --git a/modular_causticcove/code/modules/vore/eating/living_vr.dm b/modular_causticcove/code/modules/vore/eating/living_vr.dm index ae263dcb7bf..6d86c1b1fbf 100644 --- a/modular_causticcove/code/modules/vore/eating/living_vr.dm +++ b/modular_causticcove/code/modules/vore/eating/living_vr.dm @@ -818,11 +818,15 @@ if(!I) to_chat(src, span_notice("You are not holding anything.")) return + + if(length(vore_selected.contents) >= 6) //Lets add a limiter to how many items can be in one belly, sure someone can abuse it by making many... but that's a player issue we can deal with. + to_chat(src, span_notice("Your [vore_selected.name] is already filled with objects!")) + return //if(I.) //Caustic - Potential Whitelist can go here. - if(!(I.grid_height <= world.icon_size || I.grid_height <= world.icon_size)) - to_chat(src,span_warning("You can't eat such a large thing !"))//yet <-- YET??? + if(!vore_selected.validate_item_size(I)) + to_chat(src,span_warning("You can't eat such a large thing !"))//yet //Yeah, it was 'yet' :P I just made it allow a bit bigger stuff. return if(do_after(src, 10 SECONDS)){ @@ -847,6 +851,20 @@ trash_catching = !trash_catching to_chat(src, span_warning("Trash catching [trash_catching ? "enabled" : "disabled"].")) +/obj/belly/proc/validate_item_size(var/obj/item/I) + var/can_nom = FALSE + if(I.grid_height <= world.icon_size && I.grid_width <= (world.icon_size * 2)) + can_nom = TRUE + + if(I.grid_height <= (world.icon_size * 2) && I.grid_width <= world.icon_size) + can_nom = TRUE + + if(!can_nom && I.smeltresult && item_digest_mode == IM_SMELTING) + to_chat(src.owner, span_warning("With your [name] roaring to smelt something, you start to smelt down the [I]...")) + can_nom = TRUE + + return can_nom + /* /mob/living/proc/eat_minerals() //Actual eating abstracted so the user isn't given a prompt due to an argument in this verb. set name = "Eat Minerals" diff --git a/modular_causticcove/code/modules/vore/eating/vore_procs.dm b/modular_causticcove/code/modules/vore/eating/vore_procs.dm index 684bc8cc70f..90b76bf1769 100644 --- a/modular_causticcove/code/modules/vore/eating/vore_procs.dm +++ b/modular_causticcove/code/modules/vore/eating/vore_procs.dm @@ -175,6 +175,8 @@ return FALSE if(!prey.mind) //A quick check for if the Prey has no mind datum, it likely wasn't controlled by a player ever, so we don't need to check prefs. + if(prey.cmode && prey.stat == CONSCIOUS) //If they are in combat mode, which all AI mobs are, then they have to be not actively concious to be Nom'd. Should stop combat-noms. + return FALSE return TRUE if(!prey.devourable) From d264aade413078d2d6b18df87c81754224ba5e72 Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 30 Jun 2026 22:48:49 -0400 Subject: [PATCH 13/16] Oops. Forgot to change a var name. --- modular_causticcove/code/datums/spontaneous_vore.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_causticcove/code/datums/spontaneous_vore.dm b/modular_causticcove/code/datums/spontaneous_vore.dm index 331a1ef259f..6c84e7ce232 100644 --- a/modular_causticcove/code/datums/spontaneous_vore.dm +++ b/modular_causticcove/code/datums/spontaneous_vore.dm @@ -83,7 +83,7 @@ if(!destination_belly) return if(source.stat != DEAD && source.trash_catching) - if(length(vore_selected.contents) < 6) //Lets add a limiter to how many items can be in one belly, sure someone can abuse it by making many... but that's a player issue we can deal with. + if(length(destination_belly.contents) < 6) //Lets add a limiter to how many items can be in one belly, sure someone can abuse it by making many... but that's a player issue we can deal with. if(source.adminbus_trash || destination_belly.validate_item_size(O) ||/*is_type_in_list(O, GLOB.edible_trash) &&*/ O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist)) //Caustic - Trash Eatable was unused really, we'd otherwise have to go through and add it in to all items. source.visible_message(span_warning("[O] is thrown directly into [source]'s [lowertext(destination_belly.name)]!")) destination_belly.nom_atom(O) From 5715b665dbc88692a33cd66e120ef58a681624eb Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 1 Jul 2026 00:41:18 -0400 Subject: [PATCH 14/16] Fixed the Sloshers, it now just has a default volume setting of 100, and otherwise uses the sound toggle I added earlier to quiet it! Adjusted the Inbelly spawn message because I think it's better to just do it better from the Late Join menu. --- .../code/modules/vore/eating/inbelly_spawn.dm | 6 ++---- modular_causticcove/code/modules/vore/slosh.dm | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm index d514984c7d3..8be72021ca7 100644 --- a/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm +++ b/modular_causticcove/code/modules/vore/eating/inbelly_spawn.dm @@ -90,9 +90,7 @@ joined_area.on_joining_game(new_character) new_character.update_fov_angles() - if(new_character.dna?.species) - new_character.dna.species.after_creation(new_character) - new_character.roll_stats() //This hopefully does not runtime, as it appears it properly checks for if the new player is null first. + new_character.after_creation() GLOB.chosen_names += new_character.real_name new_character.islatejoin = TRUE @@ -121,7 +119,7 @@ set category = "VORE" enable_inbelly_spawn_attempts = !enable_inbelly_spawn_attempts - to_chat(src, span_notice("In-Belly spawn attempts [enable_inbelly_spawn_attempts ? "enabled! Middle-Mouse click on your pred to request a spawn (if they have it set up!)" : "disabled! Middle-Mouse clicks will revert to their usual actions."]")) + to_chat(src, span_notice("In-Belly spawn attempts [enable_inbelly_spawn_attempts ? "enabled! Middle-Mouse click on your pred to request a spawn (if they have it set up!) This is generally for ease of continuing a scene, you will spawn without any gear or stats and skills." : "disabled! Middle-Mouse clicks will revert to their usual actions."]")) /mob/dead/observer/MiddleClickOn(atom/A, params) if(enable_inbelly_spawn_attempts && isliving(A)) diff --git a/modular_causticcove/code/modules/vore/slosh.dm b/modular_causticcove/code/modules/vore/slosh.dm index 986e305df01..0ba6787fa6d 100644 --- a/modular_causticcove/code/modules/vore/slosh.dm +++ b/modular_causticcove/code/modules/vore/slosh.dm @@ -37,7 +37,6 @@ /datum/element/slosh/proc/choose_vorefootstep(mob/living/source) if(step_count++ >= 5) - vore_organs_reagents = list() var/highest_vol = 0 @@ -64,12 +63,12 @@ handle_vorefootstep(source) /datum/element/slosh/proc/handle_vorefootstep(mob/living/source) - if(!CONFIG_GET(number/vorefootstep_volume) || !vore_footstep_volume) + if(!vore_footstep_volume) //!CONFIG_GET(number/vorefootstep_volume) || -- Commenting this out for now. Lets ... just go with the Vore Footstep Volume itself, basically? return var/S = pick(GLOB.slosh) if(!S) return - var/volume = CONFIG_GET(number/vorefootstep_volume) * (vore_footstep_volume/100) + var/volume = 100 * (vore_footstep_volume/100) //CONFIG_GET(number/vorefootstep_volume) * (vore_footstep_volume/100) /*if(ishuman(source)) var/mob/living/carbon/human/human_source = source From 2638af0dbca78da5f354f14e6bfb08793bab4d91 Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 1 Jul 2026 01:00:40 -0400 Subject: [PATCH 15/16] Few tweaks to the look of the Character Directory. The colored bars behind every player really clashed HARD with the color schemes we have, so... Lets just let the background be the color. Also re-adjusted the positioning of the various sections of the panel. We aren't solely about Vore, so that shouldn't be at the front-most. --- .../CharacterDirectoryList.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx index b6bdb154c19..9c2627f2be2 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx +++ b/tgui/packages/tgui/interfaces/CharacterDirectory/CharacterDirectoryList.tsx @@ -51,40 +51,40 @@ export const CharacterDirectoryList = (props: { Species - Vore Tag + Gender - Gender + Sexuality - Sexuality + ERP Tag - ERP Tag + Vore Tag + {character.photo ? ( setHoveredAction(adActionId)} //Why do you error? This works fine it seems? onMouseLeave={() => setHoveredAction((current) => current === adActionId ? null : current)} color="transparent" - textColor="black" + //textColor="black" icon="scroll" tooltip={hasCharacterAd ? 'View advertisement' : 'No advertisement set'} disabled={!hasCharacterAd} @@ -184,7 +184,7 @@ export const CharacterDirectoryList = (props: { onMouseEnter={() => setHoveredAction(viewActionId)} //Why do you error? This works fine it seems? onMouseLeave={() => setHoveredAction((current) => current === viewActionId ? null : current)} color="transparent" - textColor="black" + //textColor="black" icon="eye" tooltip="View character profile" style={{ From 3cec88e454129f6687a29fc3c93bca91b39a80a0 Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 1 Jul 2026 05:24:44 -0400 Subject: [PATCH 16/16] Updated the few simple mobs that were still attempting to run the old AI code --- .../controllers/subsystem/rogue/fog_event/mobs/fog_wolf.dm | 2 ++ .../living/simple_animal/hostile/retaliate/primordial.dm | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/code/controllers/subsystem/rogue/fog_event/mobs/fog_wolf.dm b/code/controllers/subsystem/rogue/fog_event/mobs/fog_wolf.dm index e341abddd47..fdf9d60d585 100644 --- a/code/controllers/subsystem/rogue/fog_event/mobs/fog_wolf.dm +++ b/code/controllers/subsystem/rogue/fog_event/mobs/fog_wolf.dm @@ -29,6 +29,8 @@ dodgetime = 30 faction = list(FACTION_REVENANTS, FACTION_WOLFS) + AIStatus = AI_OFF + can_have_ai = FALSE ai_controller = /datum/ai_controller/volf base_intents = list(/datum/intent/simple/bite/volf) melee_cooldown = WOLF_ATTACK_SPEED diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/primordial.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/primordial.dm index 5868ee8de72..0a905e03970 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/primordial.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/primordial.dm @@ -101,6 +101,9 @@ retreat_health = 0 food = 0 next_ability_use + + AIStatus = AI_OFF + can_have_ai = FALSE ai_controller = /datum/ai_controller/flame_primordial /mob/living/simple_animal/hostile/retaliate/rogue/primordial/fire/ability(turf/target_location, mob/living/user) @@ -183,6 +186,8 @@ retreat_health = 0 food = 0 + AIStatus = AI_OFF + can_have_ai = FALSE ai_controller = /datum/ai_controller/water_primordial /mob/living/simple_animal/hostile/retaliate/rogue/primordial/water/ability(turf/target_location, mob/living/user) @@ -294,6 +299,8 @@ retreat_health = 0 food = 0 + AIStatus = AI_OFF + can_have_ai = FALSE ai_controller = /datum/ai_controller/air_primordial /mob/living/simple_animal/hostile/retaliate/rogue/primordial/air/ability(turf/target_location, mob/living/user)