diff --git a/code/ATMOSPHERICS/components/shutoff.dm b/code/ATMOSPHERICS/components/shutoff.dm
index 55d11627777..ea1f9fde705 100644
--- a/code/ATMOSPHERICS/components/shutoff.dm
+++ b/code/ATMOSPHERICS/components/shutoff.dm
@@ -26,7 +26,7 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
/obj/machinery/atmospherics/valve/shutoff/Destroy()
GLOB.shutoff_valves -= src
- ..()
+ . = ..()
/obj/machinery/atmospherics/valve/shutoff/attack_ai(mob/user as mob)
return src.attack_hand(user)
diff --git a/code/__defines/_reagents.dm b/code/__defines/_reagents.dm
index bb5da52505c..7759ba3cc30 100644
--- a/code/__defines/_reagents.dm
+++ b/code/__defines/_reagents.dm
@@ -69,6 +69,8 @@
#define REAGENT_ID_POTASSIUM "potassium"
#define REAGENT_RADIUM "Radium"
#define REAGENT_ID_RADIUM "radium"
+#define REAGENT_CONCENTRATEDRADIUM "Concentrated Radium"
+#define REAGENT_ID_CONCENTRATEDRADIUM "concentrated_radium"
#define REAGENT_SILICON "Silicon"
#define REAGENT_ID_SILICON "silicon"
#define REAGENT_SODIUM "Sodium"
@@ -1302,6 +1304,8 @@
#define REAGENT_ID_SIFSAP "sifsap"
#define REAGENT_STOMACID "Digestive acid"
#define REAGENT_ID_STOMACID "stomacid"
+#define REAGENT_DIETSTOMACID "Diluted digestive acid"
+#define REAGENT_ID_DIETSTOMACID "diet_stomacid"
#define REAGENT_THERMITEV "Pyrotoxin"
#define REAGENT_ID_THERMITEV "thermite_v"
#define REAGENT_CONDENSEDCAPSAICINV "Irritant toxin"
@@ -1353,3 +1357,18 @@
#define REAGENT_ID_SLIMEBONEFIXER "slime_bone_fixer"
#define REAGENT_SLIMEORGANFIXER "Agent C"
#define REAGENT_ID_SLIMEORGANFIXER "slime_organ_fixer"
+
+// Vore Belly Options
+
+#define REAGENT_ID_WATER_BELLY "water_liquidbelly"
+#define REAGENT_ID_MILK_BELLY "milk_liquidbelly"
+#define REAGENT_ID_CREAM_BELLY "cream_liquidbelly"
+#define REAGENT_ID_HONEY_BELLY "honey_liquidbelly"
+#define REAGENT_ID_CHERRYJELLY_BELLY "cherry_liquidbelly"
+#define REAGENT_ID_STOMACID_BELLY "stomacid_liquidbelly"
+#define REAGENT_ID_DIETSTOMACID_BELLY "diet_stomacid_liquidbelly"
+#define REAGENT_ID_CLEANER_BELLY "cleaner_liquidbelly"
+#define REAGENT_ID_LUBE_BELLY "lube_liquidbelly"
+#define REAGENT_ID_BIOMASS_BELLY "biomass_liquidbelly"
+#define REAGENT_ID_CONCENTRATEDRADIUM_BELLY "cradium_liquidbelly"
+#define REAGENT_ID_TRICORDRAZINE_BELLY "tricordrazine_liquidbelly"
diff --git a/code/__defines/belly_messages.dm b/code/__defines/belly_messages.dm
new file mode 100644
index 00000000000..69eaff17d50
--- /dev/null
+++ b/code/__defines/belly_messages.dm
@@ -0,0 +1,83 @@
+// Vore belly options
+
+#define STRUGGLE_OUTSIDE "smo"
+#define STRUGGLE_INSIDE "smi"
+
+#define ABSORBED_STRUGGLE_OUSIDE "asmo"
+#define ABSORBED_STRUGGLE_INSIDE "asmi"
+
+#define ESCAPE_ATTEMPT_OWNER "escao"
+#define ESCAPE_ATTEMPT_PREY "escap"
+
+#define ESCAPE_OWNER "esco"
+#define ESCAPE_PREY "escp"
+#define ESCAPE_OUTSIDE "escout"
+
+#define ESCAPE_ITEM_OWNER "escio"
+#define ESCAPE_ITEM_PREY "escip"
+#define ESCAPE_ITEM_OUTSIDE "esciout"
+
+#define ESCAPE_FAIL_OWNER "escfo"
+#define ESCAPE_FAIL_PREY "escfp"
+
+#define ABSORBED_ESCAPE_ATTEMPT_OWNER "aescao"
+#define ABSORBED_ESCAPE_ATTEMPT_PREY "aescap"
+
+#define ABSORBED_ESCAPE_OWNER "aesco"
+#define ABSORBED_ESCAPE_PREY "aescp"
+#define ABSORBED_ESCAPE_OUTSIDE "aescout"
+
+#define FULL_ABSORBED_ESCAPE_OWNER "aescfo"
+#define FULL_ABSORBED_ESCAPE_PREY "aescfp"
+
+#define PRIMARY_TRANSFER_OWNER "trnspo"
+#define PRIMARY_TRANSFER_PREY "trnspp"
+
+#define SECONDARY_TRANSFER_OWNER "trnsso"
+#define SECONDARY_TRANSFER_PREY "trnssp"
+
+#define PRIMARY_AUTO_TRANSFER_OWNER "atrnspo"
+#define PRIMARY_AUTO_TRANSFER_PREY "atrnspp"
+
+#define SECONDARY_AUTO_TRANSFER_OWNER "atrnsso"
+#define SECONDARY_AUTO_TRANSFER_PREY "atrnssp"
+
+#define DIGEST_CHANCE_OWNER "stmodo"
+#define DIGEST_CHANCE_PREY "stmodp"
+
+#define ABSORB_CHANCE_OWNER "stmoao"
+#define ABSORB_CHANCE_PREY "stmoap"
+
+#define DIGEST_OWNER "dmo"
+#define DIGEST_PREY "dmp"
+
+#define EXAMINES "em"
+#define EXAMINES_ABSORBED "ema"
+
+#define ABSORB_OWNER "amo"
+#define ABSORB_PREY "amp"
+
+#define UNABSORBS_OWNER "uamo"
+#define UNABSORBS_PREY "uamp"
+
+#define BELLY_MODE_DIGEST "im_digest"
+#define BELLY_MODE_HOLD "im_hold"
+#define BELLY_MODE_HOLD_ABSORB "im_holdabsorbed"
+#define BELLY_MODE_ABSORB "im_absorb"
+#define BELLY_MODE_HEAL "im_heal"
+#define BELLY_MODE_DRAIN "im_drain"
+#define BELLY_MODE_STEAL "im_steal"
+#define BELLY_MODE_EGG "im_egg"
+#define BELLY_MODE_SHRINK "im_shrink"
+#define BELLY_MODE_GROW "im_grow"
+#define BELLY_MODE_UNABSORB "im_unabsorb"
+
+#define VB_MESSAGE_SANIRY(type) ASSERT(type == STRUGGLE_OUTSIDE || type == STRUGGLE_INSIDE || type == ABSORBED_STRUGGLE_OUSIDE || type == ABSORBED_STRUGGLE_INSIDE || type == ESCAPE_ATTEMPT_OWNER || type == ESCAPE_ATTEMPT_PREY ||\
+ type == ESCAPE_PREY || type == ESCAPE_OWNER || type == ESCAPE_OUTSIDE || type == ESCAPE_ITEM_PREY || type == ESCAPE_ITEM_OWNER || type == ESCAPE_ITEM_OUTSIDE || type == ESCAPE_FAIL_PREY ||\
+ type == ESCAPE_FAIL_OWNER || type == ABSORBED_ESCAPE_ATTEMPT_OWNER || type == ABSORBED_ESCAPE_ATTEMPT_PREY || type == ABSORBED_ESCAPE_PREY || type == ABSORBED_ESCAPE_OWNER ||\
+ type == ABSORBED_ESCAPE_OUTSIDE || type == FULL_ABSORBED_ESCAPE_PREY || type == FULL_ABSORBED_ESCAPE_OWNER || type == PRIMARY_TRANSFER_PREY || type == PRIMARY_TRANSFER_OWNER ||\
+ type == SECONDARY_TRANSFER_PREY || type == SECONDARY_TRANSFER_OWNER || type == PRIMARY_AUTO_TRANSFER_PREY || type == PRIMARY_AUTO_TRANSFER_OWNER || type == SECONDARY_AUTO_TRANSFER_PREY ||\
+ type == SECONDARY_AUTO_TRANSFER_OWNER || type == DIGEST_CHANCE_PREY || type == DIGEST_CHANCE_OWNER || type == ABSORB_CHANCE_PREY || type == ABSORB_CHANCE_OWNER || type == DIGEST_OWNER ||\
+ type == DIGEST_PREY || type == ABSORB_OWNER || type == ABSORB_PREY || type == UNABSORBS_OWNER || type == UNABSORBS_PREY || type == EXAMINES || type == EXAMINES_ABSORBED ||\
+ type == BELLY_MODE_DIGEST || type == BELLY_MODE_HOLD || type == BELLY_MODE_HOLD_ABSORB || type == BELLY_MODE_ABSORB || type == BELLY_MODE_HEAL || type == BELLY_MODE_DRAIN ||\
+ type == BELLY_MODE_STEAL || type == BELLY_MODE_EGG || type == BELLY_MODE_SHRINK || type == BELLY_MODE_GROW || type == BELLY_MODE_UNABSORB)
diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm
index 266d2f583af..38aefcd8703 100644
--- a/code/__defines/belly_modes_vr.dm
+++ b/code/__defines/belly_modes_vr.dm
@@ -22,11 +22,15 @@
#define DM_FLAG_JAMSENSORS 0x20
#define DM_FLAG_FORCEPSAY 0x40
#define DM_FLAG_SPARELIMB 0x80
+#define DM_FLAG_SLOWBODY 0x100
+#define DM_FLAG_MUFFLEITEMS 0x200
+#define DM_FLAG_TURBOMODE 0x400
//Item related modes
#define IM_HOLD "Hold"
#define IM_DIGEST_FOOD "Digest (Food Only)"
#define IM_DIGEST "Digest"
+#define IM_DIGEST_PARALLEL "Digest (Dispersed Damage)"
//Stance for hostile mobs to be in while devouring someone.
#define HOSTILE_STANCE_EATING 99
@@ -49,3 +53,40 @@
#define DM_FLAG_VORESPRITE_TAIL 0x2
#define DM_FLAG_VORESPRITE_MARKING 0x4
#define DM_FLAG_VORESPRITE_ARTICLE 0x8
+
+//Belly Reagents mode flags
+#define DM_FLAG_REAGENTSNUTRI 0x1
+#define DM_FLAG_REAGENTSDIGEST 0x2
+#define DM_FLAG_REAGENTSABSORB 0x4
+#define DM_FLAG_REAGENTSDRAIN 0x8
+
+//For belly fullscreen shennanigans outside of bellies, due to Life() clearing belly fullscreens outside of bellies.
+#define ATOM_BELLY_FULLSCREEN "belly_atom_vfx"
+
+//Auto-transfer mob flags
+#define AT_FLAG_CREATURES 0x1
+#define AT_FLAG_ABSORBED 0x2
+#define AT_FLAG_CARBON 0x4
+#define AT_FLAG_SILICON 0x8
+#define AT_FLAG_MOBS 0x10
+#define AT_FLAG_ANIMALS 0x20
+#define AT_FLAG_MICE 0x40
+#define AT_FLAG_DEAD 0x80
+#define AT_FLAG_CANDIGEST 0x100
+#define AT_FLAG_CANABSORB 0x200
+#define AT_FLAG_HEALTHY 0x400
+
+//Auto-transfer item flags
+#define AT_FLAG_ITEMS 0x1
+#define AT_FLAG_TRASH 0x2
+#define AT_FLAG_EGGS 0x4
+#define AT_FLAG_REMAINS 0x8
+#define AT_FLAG_INDIGESTIBLE 0x10
+#define AT_FLAG_RECYCLABLE 0x20
+#define AT_FLAG_ORES 0x40
+#define AT_FLAG_CLOTHES 0x80
+#define AT_FLAG_FOOD 0x100
+
+//Vorespawn flags
+#define VS_FLAG_ABSORB_YES 0x1
+#define VS_FLAG_ABSORB_PREY 0x2
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 8073d6a8ca1..d2efee687f0 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 // vore belly interactions
#define MINIMUM_CHEMICAL_VOLUME 0.01
diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm
index 49f80fd19ab..2aa9f41c5ff 100644
--- a/code/__defines/dcs/signals.dm
+++ b/code/__defines/dcs/signals.dm
@@ -813,6 +813,13 @@
#define COMSIG_OBSERVER_APC "observer_apc"
#define COMSIG_OBSERVER_GLOBALMOVED "observer_global_move"
+// Bellies
+///from /obj/belly/HandleBellyReagents() and /obj/belly/update_internal_overlay()
+#define COMSIG_BELLY_UPDATE_VORE_FX "update_vore_fx"
+///from /obj/belly/process()
+#define COMSIG_BELLY_UPDATE_PREY_LOOP "update_prey_loop"
+/// COMSIG used to get messages where they need to go
+#define COMSIG_VISIBLE_MESSAGE "visible_message"
//Unittest data update
#ifdef UNIT_TEST
diff --git a/code/__defines/map.dm b/code/__defines/map.dm
index 66c21202500..045119d1c61 100644
--- a/code/__defines/map.dm
+++ b/code/__defines/map.dm
@@ -7,11 +7,12 @@
#define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump)
#define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset.
#define MAP_LEVEL_XENOARCH_EXEMPT 0x080 // Z-levels exempt from xenoarch digsite generation.
-#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds
-#define MAP_LEVEL_MAPPABLE 0x200 // Z-levels where mapping units will work fully
-#define MAP_LEVEL_BELOW_BLOCKED 0x400 // Z-levels in multiz with level below not meant to be 'normally' accessible
+#define MAP_LEVEL_VORESPAWN 0x100 // Z-levels players are allowed to late join to via vorish means. Usually non-dangerous locations.
+#define MAP_LEVEL_PERSIST 0x200 // Z-levels where SSpersistence should persist between rounds
+#define MAP_LEVEL_MAPPABLE 0x400 // Z-levels where mapping units will work fully
+#define MAP_LEVEL_BELOW_BLOCKED 0x800 // Z-levels in multiz with level below not meant to be 'normally' accessible
// Misc map defines.
-#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. //VOREStation Edit
+#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge.
#define CELL_ALIVE(VAL) (VAL == cell_live_value)
diff --git a/code/__defines/math.dm b/code/__defines/math.dm
index 57c9b56ce30..4d141e562d6 100644
--- a/code/__defines/math.dm
+++ b/code/__defines/math.dm
@@ -228,3 +228,10 @@
if(num < 0)
return 0
return sqrt(num)
+
+//Proc to check if a flag is active to use in universal math
+/proc/global_flag_check(element, flag)
+ if(element & flag)
+ return 1
+ else
+ return 0
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 4e31ab3309f..1cf7a2c62a8 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -480,7 +480,9 @@
#define VIS_CH_STOMACH 34
-#define VIS_COUNT 34 //Must be highest number from above.
+#define VIS_SOULCATCHER 35
+
+#define VIS_COUNT 35 //Must be highest number from above.
//Some mob icon layering defines
#define BODY_LAYER -100
diff --git a/code/__defines/nif.dm b/code/__defines/nif.dm
new file mode 100644
index 00000000000..439edbab6a1
--- /dev/null
+++ b/code/__defines/nif.dm
@@ -0,0 +1,13 @@
+//These two also have NIF FLAG representations. These are the local setting representations.
+#define NIF_SC_CATCHING_ME 0x1
+#define NIF_SC_CATCHING_OTHERS 0x2
+//These are purely local setings flags, without global representation.
+#define NIF_SC_ALLOW_EARS 0x4
+#define NIF_SC_ALLOW_EYES 0x8
+#define NIF_SC_BACKUPS 0x10
+#define NIF_SC_PROJECTING 0x20
+#define SOULGEM_CATCHING_GHOSTS 0x200
+#define SOULGEM_ACTIVE 0x400
+#define SOULGEM_SHOW_VORE_SFX 0x800
+#define SOULGEM_CATCHING_DRAIN 0x1000
+#define SOULGEM_SEE_SR_SOULS 0x2000
diff --git a/code/__defines/soulcatcher.dm b/code/__defines/soulcatcher.dm
new file mode 100644
index 00000000000..871a0d77f2c
--- /dev/null
+++ b/code/__defines/soulcatcher.dm
@@ -0,0 +1,5 @@
+#define SOULCATCHER_ALLOW_CAPTURE 0x1
+#define SOULCATCHER_ALLOW_TRANSFER 0x2
+#define SOULCATCHER_ALLOW_DELETION 0x4
+#define SOULCATCHER_ALLOW_DELETION_INSTANT 0x8
+#define SOULCATCHER_ALLOW_TAKEOVER 0x10
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 1ac622f55b4..4bd3ecf7775 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -376,3 +376,27 @@ var/global/list/blacklisted_artifact_effects = list(
/datum/artifact_effect/gas/phoron,
/datum/artifact_effect/extreme
)
+
+//stuff that only synths can eat
+var/global/list/edible_tech = list(/obj/item/cell,
+ /obj/item/circuitboard,
+ /obj/item/integrated_circuit,
+ /obj/item/broken_device,
+ /obj/item/brokenbug,
+ )
+
+var/global/list/item_digestion_blacklist = list(
+ /obj/item/hand_tele,
+ /obj/item/card/id,
+ /obj/item/gun,
+ /obj/item/pinpointer,
+ /obj/item/clothing/shoes/magboots,
+ /obj/item/areaeditor/blueprints,
+ /obj/item/disk/nuclear,
+ /obj/item/perfect_tele_beacon,
+ /obj/item/organ/internal/brain/slime,
+ /obj/item/mmi/digital/posibrain,
+ /obj/item/mmi/digital/robot,
+ /obj/item/rig/protean)
+
+var/global/list/item_tf_spawnpoints = list() // Global variable tracking which items are item tf spawnpoints
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 953251c6e10..939a451cc9a 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -1584,6 +1584,7 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
. += new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags
. += new /obj/screen/plane_master{plane = PLANE_CH_STOMACH} //Stomachs
. += new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality
+ . += new /obj/screen/plane_master{plane = PLANE_SOULCATCHER} //Soulcatcher
//VOREStation Add End
/proc/CallAsync(datum/source, proctype, list/arguments)
set waitfor = FALSE
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 5508d5e168b..2f0fc843e91 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -62,6 +62,10 @@
/datum/config_entry/number/footstep_volume
default = 0
+/// In future see about making a function to adjust volume serverside in config.txt, easy to do with reenable values. - Jack
+/datum/config_entry/number/vorefootstep_volume
+ default = 75
+
/datum/config_entry/flag/use_loyalty_implants
/datum/config_entry/flag/show_human_death_message
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 909b4f501c1..abe7fd0ef58 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -29,6 +29,8 @@
var/cloaked = FALSE //If we're cloaked or not
var/image/cloaked_selfimage //The image we use for our client to let them see where we are
+ var/belly_cycles = 0 // Counting current belly process cycles for autotransfer.
+ var/autotransferable = TRUE // Toggle for autotransfer mechanics.
/atom/movable/Initialize(mapload)
. = ..()
@@ -665,3 +667,10 @@
var/direction = get_dir(old_loc, new_loc)
loc = new_loc
Moved(old_loc, direction, TRUE)
+
+// Helper procs called on entering/exiting a belly. Does nothing by default, override on children for special behavior.
+/atom/movable/proc/enter_belly(obj/belly/B)
+ return
+
+/atom/movable/proc/exit_belly(obj/belly/B)
+ return
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index d6e8d75a8b0..699ad5ade57 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -212,6 +212,8 @@
return TRUE
*/
+/datum/job/proc/update_limit(var/comperator)
+ return
// Check client-specific availability rules.
/datum/job/proc/player_has_enough_pto(client/C)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 8b9ea2d75a9..d500950cff6 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -83,6 +83,13 @@ var/global/datum/controller/occupations/job_master
return 1
return 0
+/datum/controller/occupations/proc/update_limit(var/rank, var/comperator)
+ var/datum/job/job = GetJob(rank)
+ if(job && job.total_positions != -1)
+ job.update_limit(comperator)
+ return 1
+ return 0
+
/datum/controller/occupations/proc/FindOccupationCandidates(datum/job/job, level, flag)
Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
var/list/candidates = list()
@@ -351,7 +358,7 @@ var/global/datum/controller/occupations/job_master
return 1
-/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0)
+/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0, var/announce = TRUE)
if(!H) return null
var/datum/job/job = GetJob(rank)
@@ -428,7 +435,7 @@ var/global/datum/controller/occupations/job_master
//else
if(G.slot == slot_wear_suit && H.client?.prefs?.no_jacket)
continue
- if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater)
+ if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD
continue
if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
to_chat(H, span_notice("Equipping you with \the [thing]!"))
@@ -457,7 +464,7 @@ var/global/datum/controller/occupations/job_master
var/datum/gear/G = gear_datums[thing]
if(G.slot == slot_wear_suit && H.client?.prefs?.no_jacket)
continue
- if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater)
+ if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD
continue
if(G.slot in custom_equip_slots)
spawn_in_storage += thing
@@ -499,7 +506,7 @@ var/global/datum/controller/occupations/job_master
return H
// TWEET PEEP
- if(rank == JOB_SITE_MANAGER)
+ if(rank == JOB_SITE_MANAGER && announce)
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, [alt_title ? alt_title : JOB_SITE_MANAGER] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
@@ -659,31 +666,305 @@ var/global/datum/controller/occupations/job_master
var/datum/spawnpoint/spawnpos
var/fail_deadly = FALSE
+ var/obj/belly/vore_spawn_gut
+ var/absorb_choice = FALSE // Ability to start absorbed with vorespawn
+ var/mob/living/prey_to_nomph
+ var/obj/item/item_to_be // Item TF spawning
+ var/mob/living/item_carrier // Capture crystal spawning
+ var/vorgans = FALSE // capture crystal simplemob spawning
- var/datum/job/J = SSjob.get_job(rank)
- fail_deadly = J?.offmap_spawn
+ // Remove fail_deadly addition on offmap_spawn
//Spawn them at their preferred one
if(C && C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint))
- if(!(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) in using_map.allowed_spawns))
- if(fail_deadly)
- to_chat(C, span_warning("Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice."))
- return
+ if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Vorespawn - Prey")
+ var/list/preds = list()
+ var/list/pred_names = list() //This is cringe
+ for(var/client/V in GLOB.clients)
+ if(!isliving(V.mob))
+ continue
+ var/mob/living/M = V.mob
+ if(M.stat == UNCONSCIOUS || M.stat == DEAD || (M.client.is_afk(10 MINUTES) && !M.no_latejoin_vore_warning))
+ continue
+ if(!M.latejoin_vore)
+ continue
+ if(!(M.z in using_map.vorespawn_levels))
+ continue
+ preds += M
+ pred_names += M.real_name //very cringe
+
+ if(preds.len)
+ var/pred_name = tgui_input_list(C, "Choose a Predator.", "Pred Spawnpoint", pred_names)
+ if(!pred_name)
+ return
+ var/index = pred_names.Find(pred_name)
+ var/mob/living/pred = preds[index]
+ var/list/available_bellies = list()
+ for(var/obj/belly/Y in pred.vore_organs)
+ if(Y.vorespawn_blacklist)
+ continue
+ if(LAZYLEN(Y.vorespawn_whitelist) && !(C.ckey in Y.vorespawn_whitelist))
+ continue
+ available_bellies += Y
+ var/backup = tgui_alert(C, "Do you want a mind backup?", "Confirm", list("Yes", "No"))
+ if(backup == "Yes")
+ backup = 1
+ vore_spawn_gut = tgui_input_list(C, "Choose a Belly.", "Belly Spawnpoint", available_bellies)
+ if(!vore_spawn_gut)
+ return
+ if(vore_spawn_gut.vorespawn_absorbed & VS_FLAG_ABSORB_YES)
+ absorb_choice = TRUE
+ if(vore_spawn_gut.vorespawn_absorbed & VS_FLAG_ABSORB_PREY)
+ if(tgui_alert(C, "Do you want to start absorbed into [pred]'s [vore_spawn_gut]?", "Confirm", list("Yes", "No")) != "Yes")
+ absorb_choice = FALSE
+ else if(tgui_alert(C, "[pred]'s [vore_spawn_gut] will start with you absorbed. Continue?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+ to_chat(C, span_boldwarning("[pred] has received your spawn request. Please wait."))
+ log_admin("[key_name(C)] has requested to vore spawn into [key_name(pred)]")
+ message_admins("[key_name(C)] has requested to vore spawn into [key_name(pred)]")
+
+ var/confirm
+ if(pred.no_latejoin_vore_warning)
+ if(pred.no_latejoin_vore_warning_time > 0)
+ if(absorb_choice)
+ confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn absorbed as your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), pred.no_latejoin_vore_warning_time SECONDS)
+ else
+ confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn into your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), pred.no_latejoin_vore_warning_time SECONDS)
+ if(!confirm)
+ confirm = "Yes"
+ else
+ if(absorb_choice)
+ confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn absorbed as your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"))
+ else
+ confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn into your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"))
+ if(confirm != "Yes")
+ to_chat(C, span_warning("[pred] has declined your spawn request."))
+ var/message = sanitizeSafe(input(pred,"Do you want to leave them a message?")as text|null)
+ if(message)
+ to_chat(C, span_notice("[pred] message : [message]"))
+ return
+ if(!vore_spawn_gut || QDELETED(vore_spawn_gut))
+ to_chat(C, span_warning("Somehow, the belly you were trying to enter no longer exists."))
+ return
+ if(pred.stat == UNCONSCIOUS || pred.stat == DEAD)
+ to_chat(C, span_warning("[pred] is not conscious."))
+ to_chat(pred, span_warning("You must be conscious to accept."))
+ return
+ if(!(pred.z in using_map.vorespawn_levels))
+ to_chat(C, span_warning("[pred] is no longer in station grounds."))
+ to_chat(pred, span_warning("You must be within station grounds to accept."))
+ return
+ if(backup)
+ addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS)
+ log_admin("[key_name(C)] has vore spawned into [key_name(pred)]")
+ message_admins("[key_name(C)] has vore spawned into [key_name(pred)]")
+ to_chat(C, span_notice("You have been spawned via vore. You are free to roleplay how you got there as you please, such as teleportation or having had already been there."))
+ if(vore_spawn_gut.entrance_logs)
+ to_chat(pred, span_notice("Your prey has spawned via vore. You are free to roleplay this how you please, such as teleportation or having had already been there."))
else
- to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead."))
- spawnpos = null
- else
+ to_chat(C, span_warning("No predators were available to accept you."))
+ return
spawnpos = spawntypes[C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]
+ if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Vorespawn - Pred") //Same as above, but in reverse!
+ var/list/preys = list()
+ var/list/prey_names = list() //This is still cringe
+ for(var/client/V in GLOB.clients)
+ if(!isliving(V.mob))
+ continue
+ var/mob/living/M = V.mob
+ if(M.stat == UNCONSCIOUS || M.stat == DEAD || (M.client.is_afk(10 MINUTES) && !M.no_latejoin_prey_warning))
+ continue
+ if(!M.latejoin_prey)
+ continue
+ if(!(M.z in using_map.vorespawn_levels))
+ continue
+ preys += M
+ prey_names += M.real_name
+ if(preys.len)
+ var/prey_name = tgui_input_list(C, "Choose a Prey to spawn nom.", "Prey Spawnpoint", prey_names)
+ if(!prey_name)
+ return
+ var/index = prey_names.Find(prey_name)
+ var/mob/living/prey = preys[index]
+ var/list/available_bellies = list()
+
+ var/datum/vore_preferences/P = C.prefs_vr
+ for(var/Y in P.belly_prefs)
+ available_bellies += Y["name"]
+ vore_spawn_gut = tgui_input_list(C, "Choose your Belly.", "Belly Spawnpoint", available_bellies)
+ if(!vore_spawn_gut)
+ return
+ if(alert(C, "Do you want to instantly absorb them?", "Confirm", "Yes", "No") == "Yes")
+ absorb_choice = TRUE
+ to_chat(C, span_boldwarning("[prey] has received your spawn request. Please wait."))
+ log_admin("[key_name(C)] has requested to pred spawn onto [key_name(prey)]")
+ message_admins("[key_name(C)] has requested to pred spawn onto [key_name(prey)]")
+
+ var/confirm
+ if(prey.no_latejoin_prey_warning)
+ if(prey.no_latejoin_prey_warning_time > 0)
+ if(absorb_choice)
+ confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore and instantly absorb you with their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), prey.no_latejoin_prey_warning_time SECONDS)
+ else
+ confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore you into their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), prey.no_latejoin_prey_warning_time SECONDS)
+ if(!confirm)
+ confirm = "Yes"
+ else
+ if(absorb_choice)
+ confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore and instantly absorb you with their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"))
+ else
+ confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore you into their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"))
+ if(confirm != "Yes")
+ to_chat(C, span_warning("[prey] has declined your spawn request."))
+ var/message = sanitizeSafe(input(prey,"Do you want to leave them a message?")as text|null)
+ if(message)
+ to_chat(C, span_notice("[prey] message : [message]"))
+ return
+ if(prey.stat == UNCONSCIOUS || prey.stat == DEAD)
+ to_chat(C, span_warning("[prey] is not conscious."))
+ to_chat(prey, span_warning("You must be conscious to accept."))
+ return
+ if(!(prey.z in using_map.vorespawn_levels))
+ to_chat(C, span_warning("[prey] is no longer in station grounds."))
+ to_chat(prey, span_warning("You must be within station grounds to accept."))
+ return
+ log_admin("[key_name(C)] has pred spawned onto [key_name(prey)]")
+ message_admins("[key_name(C)] has pred spawned onto [key_name(prey)]")
+ prey_to_nomph = prey
+ else
+ to_chat(C, span_warning("No prey were available to accept you."))
+ return
+ // Item TF spawnpoints!
+ else if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Item TF spawn")
+ var/list/items = list()
+ var/list/item_names = list()
+ var/list/carriers = list()
+ for(var/obj/item/I in item_tf_spawnpoints)
+ if(LAZYLEN(I.ckeys_allowed_itemspawn))
+ if(!(C.ckey in I.ckeys_allowed_itemspawn))
+ continue
+ var/atom/item_loc = I.loc
+ var/mob/living/carrier
+ while(!isturf(item_loc))
+ if(isliving(item_loc))
+ carrier = item_loc
+ break
+ else
+ item_loc = item_loc.loc
+ if(istype(carrier))
+ if(!(carrier.z in using_map.vorespawn_levels))
+ continue
+ if(carrier.stat == UNCONSCIOUS || carrier.stat == DEAD || carrier.client.is_afk(10 MINUTES))
+ continue
+ carriers += carrier
+ else
+ if(!(item_loc.z in using_map.vorespawn_levels))
+ continue
+ carriers += null
+
+ if(istype(I, /obj/item/capture_crystal))
+ if(carrier)
+ items += I
+ var/obj/item/capture_crystal/cryst = I
+ if(cryst.spawn_mob_type)
+ item_names += "\a [cryst.spawn_mob_name] inside of [carrier]'s [I.name] ([I.loc.name])"
+ else
+ item_names += "Inside of [carrier]'s [I.name] ([I.loc.name])"
+ else if(I.name == initial(I.name))
+ items += I
+ if(carrier)
+ item_names += "[carrier]'s [I.name] ([I.loc.name])"
+ else
+ item_names += "[I.name] ([I.loc.name])"
+ else
+ items += I
+ if(carrier)
+ item_names += "[carrier]'s [I.name] (\a [initial(I.name)] at [I.loc.name])"
+ else
+ item_names += "[I.name] (\a [initial(I.name)] at [I.loc.name])"
+ if(LAZYLEN(items))
+ var/backup = tgui_alert(C, "Do you want a mind backup?", "Confirm", list("Yes", "No"))
+ if(backup == "Yes")
+ backup = 1
+ var/item_name = tgui_input_list(C, "Choose an Item to spawn as.", "Item TF Spawnpoint", item_names)
+ if(!item_name)
+ return
+ var/index = item_names.Find(item_name)
+ var/obj/item/item = items[index]
+
+ var/mob/living/carrier = carriers[index]
+ if(istype(carrier))
+ to_chat(C, span_boldwarning("[carrier] has received your spawn request. Please wait."))
+ log_and_message_admins("[key_name(C)] has requested to item spawn into [key_name(carrier)]'s possession")
+
+ var/confirm = tgui_alert(carrier, "[C.prefs.real_name] is attempting to join as the [item_name] in your possession.", "Confirm", list("No", "Yes"))
+ if(confirm != "Yes")
+ to_chat(C, span_warning("[carrier] has declined your spawn request."))
+ var/message = sanitizeSafe(input(carrier,"Do you want to leave them a message?")as text|null)
+ if(message)
+ to_chat(C, span_notice("[carrier] message : [message]"))
+ return
+ if(carrier.stat == UNCONSCIOUS || carrier.stat == DEAD)
+ to_chat(C, span_warning("[carrier] is not conscious."))
+ to_chat(carrier, span_warning("You must be conscious to accept."))
+ return
+ if(!(carrier.z in using_map.vorespawn_levels))
+ to_chat(C, span_warning("[carrier] is no longer in station grounds."))
+ to_chat(carrier, span_warning("You must be within station grounds to accept."))
+ return
+ log_and_message_admins("[key_name(C)] has item spawned onto [key_name(carrier)]")
+ item_to_be = item
+ item_carrier = carrier
+ if(backup)
+ addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS)
+ else
+ var/confirm = tgui_alert(C, "\The [item.name] is currently not in any character's possession! Do you still want to spawn as it?", "Confirm", list("No", "Yes"))
+ if(confirm != "Yes")
+ return
+ log_and_message_admins("[key_name(C)] has item spawned into \a [item.name] that was not held by anyone")
+ item_to_be = item
+ if(backup)
+ addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS)
+ if(istype(item, /obj/item/capture_crystal))
+ var/obj/item/capture_crystal/cryst = item
+ if(cryst.spawn_mob_type)
+ var/confirm = tgui_alert(C, "Do you want to spawn with your slot's vore organs and prefs?", "Confirm", list("No", "Yes"))
+ if(confirm == "Yes")
+ vorgans = TRUE
+ else
+ to_chat(C, span_warning("No items were available to accept you."))
+ return
+ else
+ if(!(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) in using_map.allowed_spawns))
+ if(fail_deadly)
+ to_chat(C, span_warning("Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice."))
+ return
+ else
+ to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead."))
+ spawnpos = null
+ else
+ spawnpos = spawntypes[C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]
//We will return a list key'd by "turf" and "msg"
- . = list("turf","msg")
+ . = list("turf","msg", "voreny", "prey", "itemtf", "vorgans", "carrier") // Item TF spawnpoints, spawn as mob
+ if(vore_spawn_gut)
+ .["voreny"] = vore_spawn_gut
+ .["absorb"] = absorb_choice
+ if(prey_to_nomph)
+ .["prey"] = prey_to_nomph //We pass this on later to reverse the vorespawn in new_player.dm
+ // Item TF spawnpoints
+ if(item_to_be)
+ .["carrier"] = item_carrier
+ .["vorgans"] = vorgans
+ .["itemtf"] = item_to_be
if(spawnpos && istype(spawnpos) && spawnpos.turfs.len)
if(spawnpos.check_job_spawning(rank))
.["turf"] = spawnpos.get_spawn_position()
.["msg"] = spawnpos.msg
.["channel"] = spawnpos.announce_channel
else
- if(fail_deadly)
+ var/datum/job/J = SSjob.get_job(rank)
+ if(fail_deadly || J?.offmap_spawn)
to_chat(C, span_warning("Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Please correct your spawn point choice."))
return
to_chat(C, span_filter_warning("Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead."))
@@ -694,3 +975,9 @@ var/global/datum/controller/occupations/job_master
var/spawning = pick(latejoin)
.["turf"] = get_turf(spawning)
.["msg"] = "has arrived on the station"
+
+/datum/controller/occupations/proc/m_backup_client(var/client/C) //Same as m_backup, but takes a client entry. Used for vore late joining.
+ if(!ishuman(C.mob))
+ return
+ var/mob/living/carbon/human/CM = C.mob
+ SStranscore.m_backup(CM.mind, CM.nif, TRUE)
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index 6f8ec101af9..7f18d062319 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -22,7 +22,7 @@
/obj/machinery/bluespace_beacon/Destroy()
if(Beacon)
qdel(Beacon)
- ..()
+ . = ..()
// update the invisibility and icon
/obj/machinery/bluespace_beacon/hide(var/intact)
diff --git a/code/game/machinery/bomb_tester_vr.dm b/code/game/machinery/bomb_tester_vr.dm
index baa6c6633a4..3bdf6432dc9 100644
--- a/code/game/machinery/bomb_tester_vr.dm
+++ b/code/game/machinery/bomb_tester_vr.dm
@@ -42,7 +42,7 @@
tank1 = null //Base machine Destroy()
tank2 = null //handles deleting contents
test_canister = null
- ..()
+ . = ..()
/obj/machinery/bomb_tester/dismantle()
if(tank1)
diff --git a/code/game/machinery/computer/RCON_Console.dm b/code/game/machinery/computer/RCON_Console.dm
index 60e37ed5069..e041a567190 100644
--- a/code/game/machinery/computer/RCON_Console.dm
+++ b/code/game/machinery/computer/RCON_Console.dm
@@ -22,7 +22,7 @@
/obj/machinery/computer/rcon/Destroy()
qdel(rcon)
rcon = null
- ..()
+ . = ..()
// Proc: attack_hand()
// Parameters: 1 (user - Person which clicked this computer)
diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index eceacea8eac..f5380330237 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -18,7 +18,7 @@ var/global/list/minor_air_alarms = list()
/obj/machinery/computer/atmos_alert/Destroy()
atmosphere_alarm.unregister_alarm(src)
- ..()
+ . = ..()
/obj/machinery/computer/atmos_alert/attack_hand(mob/user)
tgui_interact(user)
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index ad469fc7c1b..b6586387005 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -17,7 +17,7 @@
/obj/machinery/computer/crew/Destroy()
qdel(crew_monitor)
crew_monitor = null
- ..()
+ . = ..()
/obj/machinery/computer/crew/attack_ai(mob/user)
attack_hand(user)
diff --git a/code/game/machinery/computer/shutoff_monitor.dm b/code/game/machinery/computer/shutoff_monitor.dm
index d770f968764..2f08d5a0364 100644
--- a/code/game/machinery/computer/shutoff_monitor.dm
+++ b/code/game/machinery/computer/shutoff_monitor.dm
@@ -13,7 +13,7 @@
/obj/machinery/computer/shutoff_monitor/Destroy()
QDEL_NULL(monitor)
- ..()
+ . = ..()
/obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user as mob)
..()
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index c7d9a32a10b..0a5692a8977 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -25,7 +25,7 @@
/obj/machinery/computer/station_alert/Destroy()
alarm_monitor.unregister_alarm(src)
qdel(alarm_monitor)
- ..()
+ . = ..()
/obj/machinery/computer/station_alert/attack_ai(mob/user)
add_fingerprint(user)
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index e5156418b32..fff5cc2e704 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -15,7 +15,7 @@ var/list/doppler_arrays = list()
/obj/machinery/doppler_array/Destroy()
doppler_arrays -= src
- ..()
+ . = ..()
/obj/machinery/doppler_array/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range,var/took)
if(stat & NOPOWER) return
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index 30c73aa30a6..f58515b19e1 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -91,7 +91,7 @@
/obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ . = ..()
/obj/machinery/embedded_controller/radio/update_icon()
if(on && program)
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index c4dbb902ad2..8b5bb2d497d 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -184,7 +184,7 @@
/obj/machinery/magnetic_module/Destroy()
if(radio_controller)
radio_controller.remove_object(src, freq)
- ..()
+ . = ..()
/obj/machinery/magnetic_controller
name = "Magnetic Control Console"
@@ -391,4 +391,4 @@
/obj/machinery/magnetic_controller/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ . = ..()
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index 775b23b6b8c..7502d9f01bc 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -202,7 +202,7 @@ Transponder Codes:
"}
/obj/machinery/navbeacon/Destroy()
navbeacons.Remove(src)
- ..()
+ . = ..()
//
diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm
index b9b3f7110ff..852ea08de41 100644
--- a/code/game/machinery/pda_multicaster.dm
+++ b/code/game/machinery/pda_multicaster.dm
@@ -30,7 +30,7 @@
/obj/machinery/pda_multicaster/Destroy()
for(var/atom/movable/AM in contents)
qdel(AM)
- ..()
+ . = ..()
/obj/machinery/pda_multicaster/update_icon()
if(on)
diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm
index 3b37c479ba9..ebfa67a1966 100644
--- a/code/game/machinery/supplybeacon.dm
+++ b/code/game/machinery/supplybeacon.dm
@@ -97,7 +97,7 @@
/obj/machinery/power/supply_beacon/Destroy()
if(use_power)
deactivate()
- ..()
+ . = ..()
/obj/machinery/power/supply_beacon/process()
if(expended)
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 1ce5c5bc0a6..e02a5309741 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -146,7 +146,7 @@
/obj/machinery/power/singularity_beacon/Destroy()
if(active)
Deactivate()
- ..()
+ . = ..()
//stealth direct power usage
/obj/machinery/power/singularity_beacon/process()
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 6f130a4825e..e93a1a4566a 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -121,7 +121,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore.
if(message_delay)
message_delay = 0
- ..()
+ . = ..()
/*
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 7887e59fd26..33a06903590 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -143,7 +143,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
for(var/obj/machinery/telecomms/comm in telecomms_list)
comm.links -= src
links = list()
- ..()
+ . = ..()
// Used in auto linking
/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T)
diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm
index 5ef38c59f2f..8476298bb26 100644
--- a/code/game/machinery/turret_control.dm
+++ b/code/game/machinery/turret_control.dm
@@ -51,7 +51,7 @@
var/area/A = control_area
if(A && istype(A))
A.turret_controls -= src
- ..()
+ . = ..()
/obj/machinery/turretid/Initialize(mapload)
if(!control_area)
diff --git a/code/game/objects/effects/decals/Cleanable/vore.dm b/code/game/objects/effects/decals/Cleanable/vore.dm
new file mode 100644
index 00000000000..904eed546c1
--- /dev/null
+++ b/code/game/objects/effects/decals/Cleanable/vore.dm
@@ -0,0 +1,48 @@
+////////////CHOMP CLEANABLE REAGENT PUDDLES/////////////////////
+
+/obj/effect/decal/cleanable/blood/reagent //Yes, we are using the blood system for this
+ name = "liquid"
+ dryname = "dried liquid"
+ desc = "It's a liquid, how boring and bland."
+ drydesc = "It's dry and crusty and boring and bland."
+ basecolor = "#FFFFFF"
+ var/ckey_source = null //The person the liquid came from
+ var/ckey_spawner = null //The person who extracted the reagent
+
+ var/custombasename = null
+ var/custombasedesc = null
+ var/custombasecolor = null
+
+/obj/effect/decal/cleanable/blood/reagent/New(var/spill_name, var/spill_color, var/spill_reagentid, var/new_amount, var/ckey_user, var/ckey_spawn)
+ switch(spill_reagentid) //To ensure that if people spill some liquids, it wont cause issues with spawning, like spilling blood. Also allow for spilling of certain things to
+ if("blood")
+ return
+ if("water") //Dont recall if we have a water puddle system, but keeping this blacklisted, would be silly with dried water puddles.
+ return
+
+ ckey_source = ckey_spawn
+ ckey_spawner = ckey_user
+
+ name = "[spill_name]"
+ dryname = "dried [spill_name]"
+ desc = "It's a puddle of [spill_name]"
+ drydesc = "It's a dried puddle of [spill_name]"
+ basecolor = spill_color
+ amount = new_amount
+
+ custombasename = "[spill_name]"
+ custombasedesc = "It's a puddle of [spill_name]"
+ custombasecolor = spill_color
+
+ update_icon()
+ START_PROCESSING(SSobj, src)
+
+/obj/effect/decal/cleanable/blood/reagent/update_icon()
+ if(custombasecolor == "rainbow") custombasecolor = get_random_colour(1)
+
+ color = custombasecolor
+ name = custombasename
+ desc = custombasedesc
+
+/obj/effect/decal/cleanable/blood/reagent/Crossed(mob/living/carbon/human/perp)
+ //Nothing, we dont wanna spread our mess all over, at least not until people want that
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index fc02ad713c8..21aaa4621a7 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -112,6 +112,9 @@
var/rock_climbing = FALSE //If true, allows climbing cliffs using click drag for single Z, walls if multiZ
var/climbing_delay = 1 //If rock_climbing, lower better.
+ var/digestable = TRUE
+ var/item_tf_spawn_allowed = FALSE
+ var/list/ckeys_allowed_itemspawn = list()
/obj/item/Initialize(mapload)
. = ..()
@@ -136,6 +139,8 @@
M.update_held_icons()
/obj/item/Destroy()
+ if(item_tf_spawn_allowed)
+ item_tf_spawnpoints -= src
if(ismob(loc))
var/mob/m = loc
m.drop_from_inventory(src)
@@ -1110,3 +1115,21 @@ Note: This proc can be overwritten to allow for different types of auto-alignmen
/obj/item/proc/get_welder()
return
+
+/obj/item/verb/toggle_digestable()
+ set category = "Object"
+ set name = "Toggle Digestable"
+ set desc = "Toggle item's digestability."
+ digestable = !digestable
+ if(!digestable)
+ to_chat(usr, span_notice("[src] is now protected from digestion."))
+
+/obj/item/proc/item_tf_spawnpoint_set()
+ if(!item_tf_spawn_allowed)
+ item_tf_spawn_allowed = TRUE
+ item_tf_spawnpoints += src
+
+/obj/item/proc/item_tf_spawnpoint_used()
+ if(item_tf_spawn_allowed)
+ item_tf_spawn_allowed = FALSE
+ item_tf_spawnpoints -= src
diff --git a/code/game/objects/items/weapons/capture_crystal.dm b/code/game/objects/items/weapons/capture_crystal.dm
index c6d55b0b1d9..0b0da723fcb 100644
--- a/code/game/objects/items/weapons/capture_crystal.dm
+++ b/code/game/objects/items/weapons/capture_crystal.dm
@@ -8,6 +8,7 @@
throwforce = 0
force = 0
actions_types = list(/datum/action/item_action/command)
+ w_class = ITEMSIZE_SMALL
var/active = FALSE //Is it set up?
var/mob/living/owner //Reference to the owner
@@ -17,6 +18,7 @@
var/last_activate //Automatically set by things that try to move the bound mob or capture things
var/empty_icon = "empty"
var/full_icon = "full"
+ var/spawn_mob_name = "A mob"
var/capture_chance_modifier = 1 //So we can have special subtypes with different capture rates!
/obj/item/capture_crystal/Initialize(mapload)
@@ -477,8 +479,9 @@
//IF the crystal somehow ends up in a tummy and digesting with a bound mob who doesn't want to be eaten, let's move them to the ground
/obj/item/capture_crystal/digest_act(var/atom/movable/item_storage = null)
- if((bound_mob in contents) && !bound_mob.devourable)
- bound_mob.forceMove(src.drop_location())
+ if(bound_mob)
+ if((bound_mob in contents) && !bound_mob.devourable)
+ bound_mob.forceMove(src.drop_location())
return ..()
//We got thrown! Let's figure out what to do
@@ -856,3 +859,102 @@
/mob/living
var/capture_crystal = TRUE //If TRUE, the mob is capturable. Otherwise it isn't.
var/capture_caught = FALSE //If TRUE, the mob has already been caught, and so cannot be caught again.
+
+/obj/item/capture_crystal/loadout
+ active = TRUE
+
+/obj/item/capture_crystal/loadout/attack(mob/living/M, mob/living/user)
+ if(!bound_mob && M != user)
+ to_chat(user, span_notice("\The [src] emits an unpleasant tone..."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ . = ..()
+
+/obj/item/capture_crystal/loadout/attack_self(mob/living/user)
+ if(!bound_mob)
+ to_chat(user, span_notice("\The [src] emits an unpleasant tone... It is not ready yet."))
+ playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
+ return
+ . = ..()
+
+/obj/item/capture_crystal/loadout/capture_chance()
+ return 0
+
+/obj/item/capture_crystal/cheap
+ name = "cheap capture crystal"
+ desc = "A silent, unassuming crystal in what appears to be some kind of steel housing. This one seems to be cheaply made and can only handle a willing mind."
+ icon = 'icons/obj/capture_crystal_vr.dmi'
+
+
+//The basic capture command does most of the registration work.
+/obj/item/capture_crystal/cheap/capture(mob/living/M, mob/living/U)
+ if(!M.capture_crystal || M.capture_caught)
+ to_chat(U, span_warning("This creature is not suitable for capture with this crystal."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ knowyoursignals(M, U)
+ if(isanimal(M) || !M.client)
+ to_chat(U, span_warning("This creature is not suitable for capture."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ owner = U
+ if(!bound_mob)
+ bound_mob = M
+ bound_mob.capture_caught = TRUE
+ persist_storable = FALSE
+ desc = "A silent, unassuming crystal in what appears to be some kind of steel housing. This one seems to be cheaply made and can only handle a willing mind."
+
+
+/obj/item/capture_crystal/cheap/activate(mob/living/user, target)
+ if(!cooldown_check()) //Are we ready to do things yet?
+ to_chat(thrower, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ if(spawn_mob_type && !bound_mob) //We don't already have a mob, but we know what kind of mob we want
+ bound_mob = new spawn_mob_type(src) //Well let's spawn it then!
+ bound_mob.faction = user.faction
+ spawn_mob_type = null
+ capture(bound_mob, user)
+ if(bound_mob) //We have a mob! Let's finish setting up.
+ user.visible_message("\The [src] clicks, and then emits a small chime.", "\The [src] grows warm in your hand, something inside is awake.")
+ active = TRUE
+ if(!owner) //Do we have an owner? It's pretty unlikely that this would ever happen! But it happens, let's claim the crystal.
+ owner = user
+ if(isanimal(bound_mob))
+ var/mob/living/simple_mob/S = bound_mob
+ S.revivedby = user.name
+ determine_action(user, target)
+ return
+ else if(isliving(target)) //So we don't have a mob, let's try to claim one! Is the target a mob?
+ var/mob/living/M = target
+ last_activate = world.time
+ if(M.capture_caught) //Can't capture things that were already caught.
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ to_chat(user, span_notice("\The [src] clicks unsatisfyingly... \The [M] is already under someone else's control."))
+ return
+ else if(M.stat == DEAD) //Is it dead? We can't influence dead things.
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ to_chat(user, span_notice("\The [src] clicks unsatisfyingly... \The [M] is not in a state to be captured."))
+ return
+ else if(M.client) //Is it player controlled?
+ capture_player(M, user) //We have to do things a little differently if so.
+ return
+ else if(!isanimal(M)) //So it's not player controlled, but it's also not a simplemob?
+ to_chat(user, span_warning("This creature is not suitable for capture."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ return
+ var/mob/living/simple_mob/S = M
+ if(!S.ai_holder) //We don't really want to capture simplemobs that don't have an AI
+ to_chat(user, span_warning("This creature is not suitable for capture."))
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ else //Shoot, it didn't work and now it's mad!!!
+ S.ai_holder.go_wake()
+ S.ai_holder.give_target(user, urgent = TRUE)
+ user.visible_message("\The [src] bonks into \the [S], angering it!")
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ to_chat(user, span_notice("\The [src] clicks unsatisfyingly."))
+ update_icon()
+ return
+ //The target is not a mob, so let's not do anything.
+ playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
+ to_chat(user, span_notice("\The [src] clicks unsatisfyingly."))
diff --git a/code/game/objects/items/weapons/storage/egg_vr.dm b/code/game/objects/items/weapons/storage/egg_vr.dm
index 7c67f2b40af..2583a1389eb 100644
--- a/code/game/objects/items/weapons/storage/egg_vr.dm
+++ b/code/game/objects/items/weapons/storage/egg_vr.dm
@@ -15,6 +15,7 @@
show_messages = 0
allow_quick_empty = TRUE
use_sound = 'sound/items/drop/flesh.ogg'
+ var/egg_name = null
/obj/item/storage/vore_egg/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/structures/props/puzzledoor.dm b/code/game/objects/structures/props/puzzledoor.dm
index 9573614cddf..55a19f404fc 100644
--- a/code/game/objects/structures/props/puzzledoor.dm
+++ b/code/game/objects/structures/props/puzzledoor.dm
@@ -51,7 +51,7 @@
for(var/obj/structure/prop/lock/L in locks)
L.linked_objects -= src
locks -= L
- ..()
+ . = ..()
/obj/machinery/door/blast/puzzle/attack_hand(mob/user as mob)
if(check_locks())
diff --git a/code/game/objects/trash_eating.dm b/code/game/objects/trash_eating.dm
index 0dcc92ba521..58364078572 100644
--- a/code/game/objects/trash_eating.dm
+++ b/code/game/objects/trash_eating.dm
@@ -91,8 +91,6 @@
/obj/item/capture_crystal/after_trash_eaten(var/mob/living/user)
if(bound_mob && (bound_mob in contents))
if(isbelly(loc))
- var/obj/belly/B = loc
- to_chat(bound_mob, span_notice("Outside of your crystal, you can see; " + span_notice("[B.desc]")))
to_chat(user, span_notice("You can taste the the power of command."))
// Most trash has no special check, so the rest of these are just after_trash_eaten()
diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm
index 8375496cce5..41f87b30f8c 100644
--- a/code/game/turfs/turf_changing.dm
+++ b/code/game/turfs/turf_changing.dm
@@ -150,6 +150,8 @@
if(is_open != was_open)
do
cur_turf = GetBelow(cur_turf)
+ if(!istype(cur_turf, /turf/simulated))
+ break
var/area/A = cur_turf.loc
if(is_open && !A.isAlwaysIndoors())
cur_turf.make_outdoors()
diff --git a/code/modules/asset_cache/assets/belly_assets.dm b/code/modules/asset_cache/assets/belly_assets.dm
new file mode 100644
index 00000000000..8ed46381930
--- /dev/null
+++ b/code/modules/asset_cache/assets/belly_assets.dm
@@ -0,0 +1,273 @@
+/datum/belly_overlays
+ var/belly_icon
+
+/datum/belly_overlays/vbo_belly1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly1.dmi'
+
+/datum/belly_overlays/vbo_belly2
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly2.dmi'
+
+/datum/belly_overlays/vbo_belly3
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly3.dmi'
+
+/datum/belly_overlays/vbo_belly4
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly4.dmi'
+
+/datum/belly_overlays/vbo_belly5
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly5.dmi'
+
+/datum/belly_overlays/vbo_belly6
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly6.dmi'
+
+/datum/belly_overlays/vbo_belly7
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly7.dmi'
+
+/datum/belly_overlays/vbo_belly8
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly8.dmi'
+
+/datum/belly_overlays/vbo_belly9
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly9.dmi'
+
+/datum/belly_overlays/vbo_belly9_fluidless
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_belly9_fluidless.dmi'
+
+/datum/belly_overlays/vbo_breast
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_breast.dmi'
+
+/datum/belly_overlays/vbo_breast1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_breast1.dmi'
+
+/datum/belly_overlays/vbo_coils
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_coils.dmi'
+
+/datum/belly_overlays/vbo_coils1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_coils1.dmi'
+
+/datum/belly_overlays/vbo_darkslit
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_darkslit.dmi'
+
+/datum/belly_overlays/vbo_fleshs
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_fleshs.dmi'
+
+/datum/belly_overlays/vbo_fleshs1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_fleshs1.dmi'
+
+/datum/belly_overlays/vbo_foot
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_foot.dmi'
+
+/datum/belly_overlays/vbo_gematically_angular
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_gematically_angular.dmi'
+
+/datum/belly_overlays/vbo_intestines1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines1.dmi'
+
+/datum/belly_overlays/vbo_intestines2
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines2.dmi'
+
+/datum/belly_overlays/vbo_intestines3
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines3.dmi'
+
+/datum/belly_overlays/vbo_intestines4
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines4.dmi'
+
+/datum/belly_overlays/vbo_intestines5
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines5.dmi'
+
+/datum/belly_overlays/vbo_intestines6
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines6.dmi'
+
+/datum/belly_overlays/vbo_intestines7
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines7.dmi'
+
+/datum/belly_overlays/vbo_intestines8
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines8.dmi'
+
+/datum/belly_overlays/vbo_intestines9
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines9.dmi'
+
+/datum/belly_overlays/vbo_intestines9_fluidless
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_intestines9_fluidless.dmi'
+
+/datum/belly_overlays/vbo_maw1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw1.dmi'
+
+/datum/belly_overlays/vbo_maw2
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw2.dmi'
+
+/datum/belly_overlays/vbo_maw3
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw3.dmi'
+
+/datum/belly_overlays/vbo_maw4
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw4.dmi'
+
+/datum/belly_overlays/vbo_maw5
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw5.dmi'
+
+/datum/belly_overlays/vbo_maw6
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw6.dmi'
+
+/datum/belly_overlays/vbo_maw7
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw7.dmi'
+
+/datum/belly_overlays/vbo_maw8
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw8.dmi'
+
+/datum/belly_overlays/vbo_maw9
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw9.dmi'
+
+/datum/belly_overlays/vbo_maw10
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw10.dmi'
+
+/datum/belly_overlays/vbo_maw11
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw11.dmi'
+
+/datum/belly_overlays/vbo_maw12
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw12.dmi'
+
+/datum/belly_overlays/vbo_maw13
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw13.dmi'
+
+/datum/belly_overlays/vbo_maw14
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw14.dmi'
+
+/datum/belly_overlays/vbo_maw15
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw15.dmi'
+
+/datum/belly_overlays/vbo_maw16
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw16.dmi'
+
+/datum/belly_overlays/vbo_maw17
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw17.dmi'
+
+/datum/belly_overlays/vbo_maw18
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw18.dmi'
+
+/datum/belly_overlays/vbo_maw19
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw19.dmi'
+
+/datum/belly_overlays/vbo_maw20
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw20.dmi'
+
+/datum/belly_overlays/vbo_maw21
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw21.dmi'
+
+/datum/belly_overlays/vbo_maw22
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw22.dmi'
+
+/datum/belly_overlays/vbo_maw23
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw23.dmi'
+
+/datum/belly_overlays/vbo_maw24
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw24.dmi'
+
+/datum/belly_overlays/vbo_maw25
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw25.dmi'
+
+/datum/belly_overlays/vbo_maw26
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_maw26.dmi'
+
+/datum/belly_overlays/vbo_notbelly
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_notbelly.dmi'
+
+/datum/belly_overlays/vbo_paw
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_paw.dmi'
+
+/datum/belly_overlays/vbo_synth1
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_synth1.dmi'
+
+/datum/belly_overlays/vbo_synth2
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_synth2.dmi'
+
+/datum/belly_overlays/vbo_trash
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_trash.dmi'
+
+/datum/belly_overlays/vbo_vines
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_vines.dmi'
+
+/datum/belly_overlays/vbo_wriggly
+ belly_icon = 'icons/mob/vore_fullscreens/VBO_wriggly.dmi'
+
+/datum/belly_overlays/vboanim_belly1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly1.dmi'
+
+/datum/belly_overlays/vboanim_belly2
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly2.dmi'
+
+/datum/belly_overlays/vboanim_belly3
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly3.dmi'
+
+/datum/belly_overlays/vboanim_belly4
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly4.dmi'
+
+/datum/belly_overlays/vboanim_belly5
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly5.dmi'
+
+/datum/belly_overlays/vboanim_belly6
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly6.dmi'
+
+/datum/belly_overlays/vboanim_belly7
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly7.dmi'
+
+/datum/belly_overlays/vboanim_belly8
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly8.dmi'
+
+/datum/belly_overlays/vboanim_belly9
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly9.dmi'
+
+/datum/belly_overlays/vboanim_belly10
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly10.dmi'
+
+/datum/belly_overlays/vboanim_gullet1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_gullet1.dmi'
+
+/datum/belly_overlays/vboanim_intestine1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_intestine1.dmi'
+
+/datum/belly_overlays/vboanim_intestine2
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_intestine2.dmi'
+
+/datum/belly_overlays/vboanim_snakebelly1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_snakebelly1.dmi'
+
+/datum/belly_overlays/vboanim_synthbelly1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_synthbelly1.dmi'
+
+/datum/belly_overlays/vboanim_taurbelly1
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_taurbelly1.dmi'
+
+/datum/belly_overlays/a_tumby
+ belly_icon = 'icons/mob/vore_fullscreens/a_tumby.dmi'
+
+/datum/belly_overlays/another_tumby
+ belly_icon = 'icons/mob/vore_fullscreens/another_tumby.dmi'
+
+/datum/belly_overlays/base
+ belly_icon = 'icons/mob/vore_fullscreens/base.dmi'
+
+/datum/belly_overlays/brown_internals
+ belly_icon = 'icons/mob/vore_fullscreens/brown_internals.dmi'
+
+/datum/belly_overlays/brown_internals_hole
+ belly_icon = 'icons/mob/vore_fullscreens/brown_internals_hole.dmi'
+
+/datum/belly_overlays/da_tumby
+ belly_icon = 'icons/mob/vore_fullscreens/da_tumby.dmi'
+
+/datum/belly_overlays/dark
+ belly_icon = 'icons/mob/vore_fullscreens/dark.dmi'
+
+/datum/belly_overlays/synth_flesh_mono
+ belly_icon = 'icons/mob/vore_fullscreens/synth_flesh_mono.dmi'
+
+/datum/belly_overlays/synth_flesh_mono_hole
+ belly_icon = 'icons/mob/vore_fullscreens/synth_flesh_mono_hole.dmi'
+
+/datum/belly_overlays/yet_another_tumby
+ belly_icon = 'icons/mob/vore_fullscreens/yet_another_tumby.dmi'
+
+//Compatibility assets due to renames...
+/datum/belly_overlays/anim_belly
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly1.dmi'
+
+/datum/belly_overlays/a_anim_belly
+ belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly1.dmi'
diff --git a/code/modules/asset_cache/assets/spritesheets/vore.dm b/code/modules/asset_cache/assets/spritesheets/vore.dm
index 625043d89d7..4881e0ede6d 100644
--- a/code/modules/asset_cache/assets/spritesheets/vore.dm
+++ b/code/modules/asset_cache/assets/spritesheets/vore.dm
@@ -2,14 +2,14 @@
name = "vore"
/datum/asset/spritesheet/vore/create_spritesheets()
- var/icon/downscaled = icon('icons/mob/screen_full_vore.dmi')
+ var/icon/downscaled = icon('icons/mob/screen_full_vore_list.dmi') // preserving save data
downscaled.Scale(240, 240)
InsertAll("", downscaled)
-/datum/asset/spritesheet/vore_colorized //This should be getting loaded in the TGUI vore panel but the game refuses to do so, for some reason. It only loads the vore spritesheet.
- name = "colorizedvore"
+/datum/asset/spritesheet/vore_fixed //This should be getting loaded in the TGUI vore panel but the game refuses to do so, for some reason. It only loads the vore spritesheet.
+ name = "fixedvore"
-/datum/asset/spritesheet/vore_colorized/create_spritesheets()
- var/icon/downscaledVC = icon('icons/mob/screen_full_colorized_vore.dmi')
- downscaledVC.Scale(240, 240)
- InsertAll("", downscaledVC)
+/datum/asset/spritesheet/vore_fixed/create_spritesheets() // preserving save data
+ var/icon/downscaledVF = icon('icons/mob/screen_full_vore.dmi')
+ downscaledVF.Scale(240, 240)
+ InsertAll("", downscaledVF)
diff --git a/code/modules/client/preference_setup/loadout/loadout_item_tf.dm b/code/modules/client/preference_setup/loadout/loadout_item_tf.dm
new file mode 100644
index 00000000000..b2ddbc1b3e9
--- /dev/null
+++ b/code/modules/client/preference_setup/loadout/loadout_item_tf.dm
@@ -0,0 +1,65 @@
+GLOBAL_DATUM_INIT(gear_tweak_item_tf_spawn, /datum/gear_tweak/item_tf_spawn, new())
+
+/datum/gear_tweak/item_tf_spawn
+
+/datum/gear_tweak/item_tf_spawn/get_contents(var/metadata)
+ if(!islist(metadata) || metadata["state"] == "Not Enabled")
+ return "Item TF spawnpoint: Not Enabled"
+ else if(metadata["state"] == "Anyone")
+ return "Item TF spawnpoint: Enabled"
+ else
+ return "Item TF spawnpoint: Only ckeys [english_list(metadata["valid"], and_text = ", ")]"
+
+/datum/gear_tweak/item_tf_spawn/get_default()
+ . = list()
+ .["state"] = "Not Enabled"
+ .["valid"] = list()
+
+/datum/gear_tweak/item_tf_spawn/get_metadata(var/user, var/list/metadata)
+ . = get_default()
+ metadata = islist(metadata) ? metadata : .
+ var/entry = tgui_input_list(user, "Choose an entry.", "Character Preference", list("Not Enabled", "Anyone", "Only Specific Players"), metadata["state"])
+ if(entry)
+ .["state"] = entry
+ if(entry == "Only Specific Players")
+ var/ckey_input = tgui_input_text(user, "Input ckeys allowed to join on separate lines", "Allowed Players", jointext(metadata["valid"], "\n"), multiline = TRUE)
+ .["valid"] = splittext(lowertext(ckey_input), "\n")
+ else
+ .["valid"] = metadata["valid"]
+ else
+ return metadata
+
+/datum/gear_tweak/item_tf_spawn/tweak_item(var/obj/item/I, var/metadata)
+ if(!islist(metadata))
+ return
+ if(metadata["state"] == "Not Enabled")
+ return
+ else if(metadata["state"] == "Anyone")
+ I.item_tf_spawnpoint_set()
+ else if(metadata["state"] == "Only Specific Players")
+ I.item_tf_spawnpoint_set()
+ I.ckeys_allowed_itemspawn = metadata["valid"]
+
+/datum/gear_tweak/simplemob_picker
+ var/list/simplemob_list
+
+/datum/gear_tweak/simplemob_picker/New(var/list/valid_simplemobs)
+ src.simplemob_list = valid_simplemobs
+ ..()
+
+/datum/gear_tweak/simplemob_picker/get_contents(var/metadata)
+ return "Type: [metadata]"
+
+/datum/gear_tweak/simplemob_picker/get_default()
+ return simplemob_list[1]
+
+/datum/gear_tweak/simplemob_picker/get_metadata(var/user, var/metadata)
+ return tgui_input_list(user, "Choose a type.", "Character Preference", simplemob_list, metadata)
+
+/datum/gear_tweak/simplemob_picker/tweak_item(var/obj/item/capture_crystal/I, var/metadata)
+ if(!(metadata in simplemob_list))
+ return
+ if(!istype(I))
+ return
+ I.spawn_mob_type = simplemob_list[metadata]
+ I.spawn_mob_name = metadata
diff --git a/code/modules/client/preferences_spawnpoints.dm b/code/modules/client/preferences_spawnpoints.dm
index 14789bf17b3..96e3abc2953 100644
--- a/code/modules/client/preferences_spawnpoints.dm
+++ b/code/modules/client/preferences_spawnpoints.dm
@@ -18,6 +18,7 @@ var/list/spawntypes = list()
var/list/restrict_job = null
var/list/disallow_job = null
var/announce_channel = "Common"
+ var/allow_offmap_spawn = FALSE // add option to allow offmap spawns to a spawnpoint without entirely restricting that spawnpoint
var/allowed_mob_types = JOB_SILICON|JOB_CARBON
/datum/spawnpoint/proc/check_job_spawning(job)
@@ -31,7 +32,7 @@ var/list/spawntypes = list()
if(!J) // Couldn't find, admin shenanigans? Allow it
return 1
- if(J.offmap_spawn && !(job in restrict_job))
+ if(J.offmap_spawn && !allow_offmap_spawn && !(job in restrict_job)) // add option to allow offmap spawns to a spawnpoint without entirely restricting that spawnpoint
return 0
if(!(J.mob_type & allowed_mob_types))
@@ -109,3 +110,12 @@ var/global/list/latejoin_tram = list()
/datum/spawnpoint/tram/New()
..()
turfs = latejoin_tram
+
+/datum/spawnpoint/vore
+ display_name = "Vorespawn - Prey"
+ msg = "has arrived on the station"
+ allow_offmap_spawn = TRUE
+
+/datum/spawnpoint/vore/pred
+ display_name = "Vorespawn - Pred"
+ msg = "has arrived on the station"
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index 2d251102b0e..f72326913c2 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -111,6 +111,11 @@
if(istype(M, /mob/living/carbon))
//TODO: replace with standard_feed_mob() call.
+
+ if(!M.consume_liquid_belly)
+ if(liquid_belly_check())
+ to_chat(user, span_infoplain("[user == M ? "You can't" : "\The [M] can't"] consume that, it contains something produced from a belly!"))
+ return FALSE
var/swallow_whole = FALSE
var/obj/belly/belly_target // These are surprise tools that will help us later
diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm
index 17c39924602..5074a338bbf 100644
--- a/code/modules/holodeck/HolodeckControl.dm
+++ b/code/modules/holodeck/HolodeckControl.dm
@@ -197,7 +197,7 @@
//This could all be done better, but it works for now.
/obj/machinery/computer/HolodeckControl/Destroy()
emergencyShutdown()
- ..()
+ . = ..()
/obj/machinery/computer/HolodeckControl/ex_act(severity)
emergencyShutdown()
diff --git a/code/modules/hydroponics/trays/tray_soil.dm b/code/modules/hydroponics/trays/tray_soil.dm
index 75eabd4b0d2..000fa68fe32 100644
--- a/code/modules/hydroponics/trays/tray_soil.dm
+++ b/code/modules/hydroponics/trays/tray_soil.dm
@@ -89,4 +89,4 @@
for(var/obj/effect/plant/plant in get_turf(src))
if(plant.invisibility == INVISIBILITY_MAXIMUM)
plant.invisibility = initial(plant.invisibility)
- ..()
+ . = ..()
diff --git a/code/modules/looking_glass/lg_console.dm b/code/modules/looking_glass/lg_console.dm
index 4d0f44d36e1..e3eaca92560 100644
--- a/code/modules/looking_glass/lg_console.dm
+++ b/code/modules/looking_glass/lg_console.dm
@@ -155,7 +155,7 @@
//This could all be done better, but it works for now.
/obj/machinery/computer/looking_glass/Destroy()
unload_program()
- ..()
+ . = ..()
/obj/machinery/computer/looking_glass/ex_act(severity)
unload_program()
diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm
index 74495331240..46817e679e0 100644
--- a/code/modules/mob/dead/observer/login.dm
+++ b/code/modules/mob/dead/observer/login.dm
@@ -6,6 +6,7 @@
plane_holder.set_vis(VIS_CLOAKED, TRUE)
plane_holder.set_vis(VIS_AI_EYE, TRUE)
plane_holder.set_vis(VIS_AUGMENTED, TRUE) //VOREStation Add - GHOST VISION IS AUGMENTED
+ plane_holder.set_vis(VIS_SOULCATCHER, TRUE) // Soulcatcher
plane = PLANE_GHOSTS
if(cleanup_timer)
deltimer(cleanup_timer)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 656a35e07f4..950af3d6291 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -3,6 +3,7 @@
desc = "This shouldn't appear"
density = FALSE
vis_flags = NONE
+ var/mob/living/body_backup = null //add reforming
/mob/observer/dead
name = "ghost"
@@ -582,6 +583,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/list/following_mobs = list()
/mob/observer/dead/Destroy()
+ if(body_backup)
+ body_backup.moveToNullspace() //YEET
+ qdel(body_backup)
+ body_backup = null
visualnet.addVisibility(src, src.client)
visualnet = null
if(ismob(following))
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 37141ddb47d..d6ac428b600 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -18,6 +18,7 @@
var/obj/item/organ/internal/brain/brainobj = null //The current brain organ.
var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm.
var/obj/item/radio/headset/mmi_radio/radio = null//Let's give it a radio.
+ var/mob/living/body_backup = null //add reforming
/obj/item/mmi/New()
radio = new(src)//Spawns a radio inside the MMI.
@@ -146,6 +147,8 @@
rig.forced_move(direction, user)
/obj/item/mmi/Destroy()
+ if(body_backup)
+ qdel(body_backup)
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
borg.mmi = null
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 11b8142028f..0f24332e3ab 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -200,6 +200,9 @@
if(stomach_vision)
compiled_vis += VIS_CH_STOMACH
+ if(soulgem?.flag_check(SOULGEM_SEE_SR_SOULS))
+ compiled_vis += VIS_SOULCATCHER
+
if(!compiled_vis.len && !vis_enabled.len)
return //Nothin' doin'.
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 7fbfd14c57d..89259996b1a 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1241,14 +1241,12 @@
var/sound/growlsound = sound(get_sfx("hunger_sounds"))
var/growlmultiplier = 100 - (nutrition / 250 * 100)
playsound(src, growlsound, vol = growlmultiplier, vary = 1, falloff = 0.1, ignore_walls = TRUE, preference = /datum/preference/toggle/digestion_noises)
- /* //Unused here, used downstream.
if(nutrition > 500 && noisy_full == TRUE)
var/belch_prob = 5 //Maximum belch prob.
if(nutrition < 4075)
belch_prob = ((nutrition-500)/3575)*5 //Scale belch prob with fullness if not already at max. If editing make sure the multiplier matches the max prob above.
if(prob(belch_prob))
src.emote("belch")
- */
if((CE_DARKSIGHT in chem_effects) && chemical_darksight == 0)
recalculate_vis()
chemical_darksight = 1
@@ -1670,11 +1668,8 @@
else
clear_alert("high")
- if(!isbelly(loc))
+ if(!surrounding_belly() && !previewing_belly) //VOREStation Add - Belly fullscreens safety
clear_fullscreen("belly")
- clear_fullscreen("belly2")
- clear_fullscreen("belly3")
- clear_fullscreen("belly4")
if(CONFIG_GET(flag/welder_vision))
var/found_welder
diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
index c4b8f253509..60bdef3a160 100644
--- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
+++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
@@ -148,7 +148,7 @@
var/list/potentials = living_mobs(0)
if(potentials.len)
var/mob/living/target = pick(potentials)
- if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected)
+ if(istype(target) && target.devourable && target.can_be_drop_prey && target.phase_vore && vore_selected && phase_vore)
target.forceMove(vore_selected)
to_chat(target,span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
diff --git a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
index b1f8988fdc4..0102a18f95b 100644
--- a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
+++ b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
@@ -428,6 +428,8 @@
B.forceMove(blob)
B.owner = blob
+ soulgem.owner = blob
+
//We can still speak our languages!
blob.languages = languages.Copy()
@@ -495,6 +497,8 @@
B.forceMove(src)
B.owner = src
+ soulgem.owner = src
+
//vore_organs.Cut()
if(blob.l_hand) blob.drop_from_inventory(blob.l_hand)
diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
index 7ee90806c5a..59018faecf1 100644
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
@@ -500,6 +500,8 @@
B.owner = blob
vore_organs.Cut()
+ soulgem.owner = blob
+
//We can still speak our languages!
blob.languages = languages.Copy()
blob.name = real_name
@@ -605,6 +607,8 @@
B.owner = src
languages = blob.languages.Copy()
+ soulgem.owner = src
+
Life(1) //Fix my blindness right meow //Has to be moved up here, there exists a circumstance where blob could be deleted without vore organs moving right.
//Get rid of friend blob
diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
index 0d31b901cfe..a16d98d9aa3 100644
--- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
@@ -635,6 +635,8 @@
to_chat(T, span_danger("An odd sensation flows through your body as you as [src] begins to drain you to dangerous levels!"))
if(51 to 98)
if(T.stat == DEAD)
+ if(soulgem?.flag_check(SOULGEM_ACTIVE | SOULGEM_CATCHING_DRAIN, TRUE))
+ soulgem.catch_mob(T)
T.apply_damage(500, OXY) //Bit of fluff.
absorbing_prey = 0
to_chat(src, span_notice("You have completely drained [T], killing them."))
@@ -649,6 +651,8 @@
if(drain_finalized != 1)
stage = 51
if(100) //They shouldn't survive long enough to get here, but just in case.
+ if(soulgem?.flag_check(SOULGEM_ACTIVE | SOULGEM_CATCHING_DRAIN, TRUE))
+ soulgem.catch_mob(T)
T.apply_damage(500, OXY) //Kill them.
absorbing_prey = 0
to_chat(src, span_notice("You have completely drained [T], killing them in the process."))
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index ab322eb9bcc..16d7589bdbe 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -20,11 +20,24 @@
add_verb(src, /mob/living/proc/smell)
add_verb(src, /mob/living/proc/switch_scaling)
add_verb(src, /mob/living/proc/center_offset)
+ add_verb(src, /mob/living/proc/mute_entry)
+ add_verb(src, /mob/living/proc/liquidbelly_visuals)
+ add_verb(src, /mob/living/proc/fix_vore_effects)
if(!no_vore)
add_verb(src, /mob/living/proc/vorebelly_printout)
if(!vorePanel)
AddComponent(/datum/component/vore_panel)
+
+ add_verb(src,/mob/living/proc/vore_transfer_reagents) // If mob doesnt have bellies it cant use this verb for anything
+ add_verb(src,/mob/living/proc/vore_check_reagents) // If mob doesnt have bellies it cant use this verb for anything
+ add_verb(src,/mob/living/proc/vore_bellyrub) // If mob doesnt have bellies it probably won't be needing this anyway
+ add_verb(src,/mob/proc/nsay_vore)
+ add_verb(src,/mob/proc/nme_vore)
+ add_verb(src,/mob/proc/nsay_vore_ch)
+ add_verb(src,/mob/proc/nme_vore_ch)
+ add_verb(src,/mob/proc/enter_soulcatcher)
+
//VOREStation Add Start
if(!voice_sounds_list.len || !voice_sounds_list)
if(client.prefs.voice_sound)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index e5a9bcdf230..c8c88f58169 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -612,7 +612,7 @@ var/list/ai_verbs_default = list(
switch(choice)
if("Color")
- input = tgui_color_picker("Choose a color:", "Hologram Color", holo_color)
+ input = tgui_color_picker(src, "Choose a color:", "Hologram Color", holo_color)
if(input)
holo_color = input
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
index 7248718f8a8..3cc70c3ecae 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
@@ -594,7 +594,7 @@
var/actual_brute = T.getBruteLoss() - old_brute
var/actual_burn = T.getFireLoss() - old_burn
var/damage_gain = actual_brute + actual_burn
- drain(-25 * damage_gain) //25*total loss as with voreorgan stats.
+ hound.adjust_nutrition(2.5 * damage_gain) //drain(-25 * damage_gain) //25*total loss as with voreorgan stats.
if(T.stat == DEAD)
if(ishuman(T))
log_admin("[key_name(hound)] has digested [key_name(T)] with a cyborg belly. ([hound ? "JMP" : "null"])")
@@ -643,6 +643,7 @@
//Handle the target being anything but a /mob/living
var/obj/item/T = target
if(istype(T))
+ var/is_trash = istype(T, /obj/item/trash)
var/digested = T.digest_act(item_storage = src)
if(!digested)
items_preserved |= T
@@ -667,10 +668,13 @@
plastic.add_charge(total_material)
if(material == MAT_WOOD && wood)
wood.add_charge(total_material)
- drain(-50 * digested)
+ if(is_trash)
+ hound.adjust_nutrition(digested)
+ else
+ hound.adjust_nutrition(5 * digested) //drain(-50 * digested)
else if(istype(target,/obj/effect/decal/remains))
qdel(target)
- drain(-100)
+ hound.adjust_nutrition(10) //drain(-100)
else
items_preserved |= target
update_patient()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index c733cc52188..48b650789af 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -7,6 +7,7 @@
icon_state = "robot"
maxHealth = 200
health = 200
+ nutrition = 0
mob_bump_flag = ROBOT
mob_swap_flags = ~HEAVY
@@ -1456,6 +1457,13 @@
undeploy()
..()
+/mob/living/silicon/robot/use_power()
+ if(cell && cell.charge < cell.maxcharge)
+ if(nutrition >= 1 * CYBORG_POWER_USAGE_MULTIPLIER)
+ adjust_nutrition(-(1 * CYBORG_POWER_USAGE_MULTIPLIER))
+ cell.charge += 10 * CYBORG_POWER_USAGE_MULTIPLIER
+ ..()
+
// Those basic ones require quite detailled checks on the robot's vars to see if they are installed!
/mob/living/silicon/robot/proc/has_basic_upgrade(var/given_type)
if(given_type == /obj/item/borg/upgrade/basic/vtec)
@@ -1563,3 +1571,14 @@
if(issilicon(user))
return TRUE
return FALSE
+
+/mob/living/silicon/robot/verb/purge_nutrition()
+ set name = "Purge Nutrition"
+ set category = "Abilities.Vore"
+ set desc = "Allows you to clear out most of your nutrition if needed."
+
+ if (stat != CONSCIOUS || nutrition <= 1000)
+ return
+ nutrition = 1000
+ to_chat(src, span_warning("You have purged most of the nutrition lingering in your systems."))
+ return TRUE
diff --git a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm
index ccf1908c166..0a1bc88dcc2 100644
--- a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm
+++ b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm
@@ -27,3 +27,14 @@
laws = new /datum/ai_laws/gravekeeper()
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
+
+/mob/living/silicon/robot/gravekeeper/proc/scramble_hardware(var/chance)
+ if(prob(chance)) //Small chance to spawn with a scrambled
+ emag_items = 1
+
+/mob/living/silicon/robot/gravekeeper/handle_special_unlocks()
+ if(!emag_items)
+ scramble_hardware(10)
+ if (churn_count == 5)
+ module.emag += new /obj/item/self_repair_system/advanced(module)
+ hud_used.update_robot_modules_display()
diff --git a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm
index 9f0aa11446c..dd86141e48d 100644
--- a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm
+++ b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm
@@ -334,3 +334,10 @@
return new /datum/ai_laws/tyrant()
return
+
+/mob/living/silicon/robot/lost/handle_special_unlocks()
+ if(!emag_items)
+ scramble_hardware(20)
+ if (churn_count == 5)
+ module.emag += new /obj/item/self_repair_system/advanced(module)
+ hud_used.update_robot_modules_display()
diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm
index 1fa6813ea19..c3b995dca70 100644
--- a/code/modules/mob/living/simple_mob/simple_mob.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob.dm
@@ -182,6 +182,8 @@
//vars for vore_icons toggle control
var/vore_icons_cache = null // null by default. Going from ON to OFF should store vore_icons val here, OFF to ON reset as null
+ //no stripping of simplemobs
+ strip_pref = FALSE
/mob/living/simple_mob/Initialize(mapload)
remove_verb(src, /mob/verb/observe)
diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm
index 66098286c43..3b08da3eca8 100644
--- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm
@@ -207,18 +207,19 @@
if(!vore_active || no_vore || !voremob_loaded)
return
- if(!IsAdvancedToolUser())
- add_verb(src, /mob/living/simple_mob/proc/animal_nom)
- add_verb(src, /mob/living/proc/shred_limb)
+ AddElement(/datum/element/slosh) // Sloshy element
- if(LAZYLEN(vore_organs))
- return
+ if(!soulgem)
+ soulgem = new(src)
// Since they have bellies, add verbs to toggle settings on them.
add_verb(src, /mob/living/simple_mob/proc/toggle_digestion)
add_verb(src, /mob/living/simple_mob/proc/toggle_fancygurgle)
add_verb(src, /mob/living/proc/vertical_nom)
+ if(LAZYLEN(vore_organs))
+ return
+
//A much more detailed version of the default /living implementation
var/obj/belly/B = new /obj/belly(src)
vore_selected = B
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
index c088debcc20..ab2f8219035 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
@@ -68,7 +68,7 @@
/obj/item/holder,
/obj/machinery/camera,
/obj/belly,
- //obj/soulgem, // Used downstream.
+ /obj/soulgem,
/obj/screen,
/atom/movable/emissive_blocker,
/obj/item/material,
@@ -118,6 +118,8 @@
/mob/living/simple_mob/vore/alienanimals/catslug/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm
index de0eb06a881..4c49f016e90 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm
@@ -98,6 +98,8 @@ GLOBAL_VAR_INIT(jellyfish_count, 0)
/mob/living/simple_mob/vore/alienanimals/space_jellyfish/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "internal chamber"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm
index c984051369c..c8dce0ba26c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/skeleton.dm
@@ -89,6 +89,8 @@
/mob/living/simple_mob/vore/alienanimals/skeleton/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm
index 5cd0282a371..ae034505e01 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/space_mouse.dm
@@ -64,6 +64,8 @@
/mob/living/simple_mob/vore/alienanimals/dustjumper/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spacewhale.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spacewhale.dm
index d598e959341..a130d0b23ff 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spacewhale.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spacewhale.dm
@@ -54,6 +54,8 @@
/mob/living/simple_mob/vore/overmap/spacewhale/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
index a90ad11d44e..9836c678506 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm
@@ -94,6 +94,8 @@
/mob/living/simple_mob/vore/alienanimals/startreader/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "gastric sac"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/succlet.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/succlet.dm
index bb5d71b8d45..cc3346533c6 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/succlet.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/succlet.dm
@@ -75,6 +75,8 @@
/mob/living/simple_mob/vore/alienanimals/succlet/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stummy"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
index cc34ded2a1b..478a8710f22 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
@@ -168,6 +168,8 @@ GLOBAL_VAR_INIT(teppi_count, 0) // How mant teppi DO we have?
/mob/living/simple_mob/vore/alienanimals/teppi/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm
index 1b9e64e004b..093eced1e45 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm
@@ -1,6 +1,8 @@
/mob/living/simple_mob/animal/passive/cat/runtime/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "Stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/pets/fox_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/pets/fox_vr.dm
index 98fca7c314b..97ac2d1b02a 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/pets/fox_vr.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/pets/fox_vr.dm
@@ -53,6 +53,8 @@
/mob/living/simple_mob/animal/passive/fox/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "Stomach"
@@ -201,6 +203,8 @@
/mob/living/simple_mob/animal/passive/fox/renault/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "Stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm
index f8e59c6c9e2..19b13e86f45 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm
@@ -232,6 +232,8 @@
/mob/living/simple_mob/animal/space/carp/large/huge/vorny/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm
index d452a8bf346..7f9421e6359 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm
@@ -90,6 +90,8 @@ TODO: Make them light up and heat the air when exposed to oxygen.
/mob/living/simple_mob/animal/passive/gaslamp/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "internal chamber"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm
index 1f481d5070b..d16ed292722 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm
@@ -68,6 +68,8 @@
/mob/living/simple_mob/animal/passive/snake/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/squirrel.dm b/code/modules/mob/living/simple_mob/subtypes/animal/squirrel.dm
index 62adc06c81d..8cae159ef0d 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/squirrel.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/squirrel.dm
@@ -72,6 +72,8 @@
/mob/living/simple_mob/vore/squirrel/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm b/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm
index 33f48276fbf..c32700026b2 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm
@@ -46,12 +46,14 @@
/mob/living/simple_mob/vore/turkeygirl/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The hot churning stomach of a turkey girl! The doughy flesh presses inward to form to your figure, thick slime coating everything, and very shortly that includes you as well! There isn't any escaping that constant full body motion, as her body works to ball yours up into a tight little package. Gurgling and glubbing with every shifting movement, while her pulse throbs through the flesh all around you with every beat of her heart. All in all, one thing is for certain! You've become turkey stuffing! Oh no..."
B.mode_flags = DM_FLAG_THICKBELLY | DM_FLAG_NUMBING
- B.belly_fullscreen = "anibelly"
+ B.belly_fullscreen = "anim_belly"
B.digest_brute = 1
B.digest_burn = 6
B.digestchance = 0
diff --git a/code/modules/mob/living/simple_mob/subtypes/glamour/blaidd.dm b/code/modules/mob/living/simple_mob/subtypes/glamour/blaidd.dm
index 8be2d053eed..e3e7d20eb22 100644
--- a/code/modules/mob/living/simple_mob/subtypes/glamour/blaidd.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/glamour/blaidd.dm
@@ -57,6 +57,8 @@
/mob/living/simple_mob/vore/blaidd/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/glamour/ddraig.dm b/code/modules/mob/living/simple_mob/subtypes/glamour/ddraig.dm
index bfb22f979c5..a28c22fdab8 100644
--- a/code/modules/mob/living/simple_mob/subtypes/glamour/ddraig.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/glamour/ddraig.dm
@@ -79,6 +79,8 @@
/mob/living/simple_mob/vore/ddraig/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm b/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm
index 6a85304ac3e..5acd20a470a 100644
--- a/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm
@@ -44,6 +44,8 @@
/mob/living/simple_mob/vore/fluffball/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "tail"
diff --git a/code/modules/mob/living/simple_mob/subtypes/glamour/unicorn.dm b/code/modules/mob/living/simple_mob/subtypes/glamour/unicorn.dm
index 55749ab469b..5826668a651 100644
--- a/code/modules/mob/living/simple_mob/subtypes/glamour/unicorn.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/glamour/unicorn.dm
@@ -38,6 +38,8 @@
/mob/living/simple_mob/vore/horse/unicorn/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm b/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
index 66272c6c66b..843c555432a 100644
--- a/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
@@ -80,7 +80,7 @@ var/list/_slime_default_emotes = list(
var/injection_amount = 5 // This determines how much.
var/mood = ":3" // Icon to use to display 'mood', as an overlay.
- can_enter_vent_with = list(/obj/item/clothing/head)
+ can_enter_vent_with = list(/obj/item/clothing/head, /obj/soulgem)
/mob/living/simple_mob/slime/get_available_emotes()
return global._slime_default_emotes.Copy()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm
index 6ab6004b85d..abe819f730e 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm
@@ -45,6 +45,8 @@
/mob/living/simple_mob/vore/bat/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
index adf6642a77b..1ab27a5d5b3 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
@@ -505,7 +505,9 @@ I think I covered everything.
/// My thanks to Raeschen for these descriptions
/mob/living/simple_mob/vore/bigdragon/init_vore()
- if(!voremob_loaded || LAZYLEN(vore_organs))
+ if(!voremob_loaded)
+ return
+ if(LAZYLEN(vore_organs))
return
var/obj/belly/B = new /obj/belly/dragon/maw(src)
B.affects_vore_sprites = FALSE
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
index 458d2d63e0c..4fd9a530343 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
@@ -128,6 +128,8 @@
/mob/living/simple_mob/vore/aggressive/corrupthound/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "fuel processor"
@@ -152,6 +154,8 @@
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "fuel processor"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm b/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
index a44eed03cae..cba90855ac8 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
@@ -71,6 +71,8 @@
/mob/living/simple_mob/vore/cryptdrake/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
index b0611359347..35e7ed6d3f4 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
@@ -84,6 +84,8 @@
/mob/living/simple_mob/vore/aggressive/deathclaw/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm
index 2382cc89144..33f6d19d038 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm
@@ -47,6 +47,8 @@
/mob/living/simple_mob/vore/demon/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "Stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/devil.dm b/code/modules/mob/living/simple_mob/subtypes/vore/devil.dm
index 9c07faa3e17..95fb1362df3 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/devil.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/devil.dm
@@ -45,6 +45,8 @@
/mob/living/simple_mob/vore/devil/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm b/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm
index cb830008a21..d5c06ccd789 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm
@@ -132,6 +132,8 @@
/mob/living/simple_mob/vore/fennec/huge/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "Stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
index 7e3476699d1..902bffa0433 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
@@ -119,6 +119,8 @@
/mob/living/simple_mob/vore/greatwolf/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
index 1201e791061..63531849a61 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
@@ -82,6 +82,8 @@
/mob/living/simple_mob/vore/horse/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
@@ -141,6 +143,8 @@
/mob/living/simple_mob/vore/horse/kelpie/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/lamia.dm b/code/modules/mob/living/simple_mob/subtypes/vore/lamia.dm
index a4de696dfae..0ab26d55388 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/lamia.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/lamia.dm
@@ -79,6 +79,8 @@
/mob/living/simple_mob/vore/lamia/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
index fe7dc6fe6c4..0c57d763dde 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
@@ -77,6 +77,8 @@
/mob/living/simple_mob/vore/leopardmander/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
@@ -148,6 +150,8 @@
/mob/living/simple_mob/vore/leopardmander/exotic/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm b/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm
index c4c64dd4002..80a252104db 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm
@@ -41,6 +41,8 @@
/mob/living/simple_mob/vore/meowl/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/oregrub.dm b/code/modules/mob/living/simple_mob/subtypes/vore/oregrub.dm
index 13a4cfcd043..b4cf8c593ea 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/oregrub.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/oregrub.dm
@@ -166,6 +166,8 @@
/mob/living/simple_mob/vore/oregrub/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/pakkun.dm b/code/modules/mob/living/simple_mob/subtypes/vore/pakkun.dm
index 85b19d365af..bd69a97dc64 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/pakkun.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/pakkun.dm
@@ -151,6 +151,8 @@
/mob/living/simple_mob/vore/pakkun/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
@@ -277,6 +279,8 @@
/mob/living/simple_mob/vore/pakkun/snapdragon/snappy/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.digest_mode = DM_HOLD
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
index 7d43ea18cfc..927d2ce2b41 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
@@ -65,6 +65,8 @@
/mob/living/simple_mob/vore/aggressive/panther/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm b/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm
index 4a15908f6b9..f9bf82723ab 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm
@@ -57,6 +57,8 @@
/mob/living/simple_mob/vore/peasant/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm b/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm
index 68c4d9fb926..2d7b37e0a0a 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/plants.dm
@@ -41,6 +41,8 @@
/mob/living/simple_mob/vore/mantrap/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "trap"
@@ -135,6 +137,8 @@
/mob/living/simple_mob/vore/pitcher/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm b/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
index 55c43c31d1f..2d9da07787b 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
@@ -85,6 +85,8 @@
/mob/living/simple_mob/vore/raptor/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
index 201daac8f1c..12f1c0c344c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
@@ -75,6 +75,8 @@
/mob/living/simple_mob/vore/aggressive/rat/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
index 0be9730340c..e24d4ecafbf 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
@@ -97,6 +97,8 @@
/mob/living/simple_mob/vore/scel/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm b/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm
index b857427f9cc..bd27289b08c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm
@@ -43,6 +43,8 @@
/mob/living/simple_mob/vore/scrubble/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
index 6f68198e178..490f555fa93 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
@@ -58,6 +58,8 @@
/mob/living/simple_mob/vore/sheep/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/snake.dm b/code/modules/mob/living/simple_mob/subtypes/vore/snake.dm
index 8a06d838772..9ec393ee0ce 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/snake.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/snake.dm
@@ -66,6 +66,8 @@
/mob/living/simple_mob/vore/aggressive/giant_snake/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
index c862a61c485..2d7082fbed3 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
@@ -97,6 +97,8 @@
/mob/living/simple_mob/vore/woof/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm
index 008259919a8..68da46aa4c1 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm
@@ -145,6 +145,8 @@ List of things solar grubs should be able to do:
/mob/living/simple_mob/vore/solargrub/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm
index f423abe71fa..b282e85135c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm
@@ -46,6 +46,8 @@
/mob/living/simple_mob/vore/sonadile/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm b/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm
index f9fc1e9c310..cbc412f281a 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm
@@ -46,6 +46,8 @@
/mob/living/simple_mob/vore/stalker/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm b/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm
index 67fa43187d1..17dc8122cde 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm
@@ -58,6 +58,8 @@
/mob/living/simple_mob/vore/succubus/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm
index e1d61f69433..c622aa68e43 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm
@@ -57,6 +57,8 @@
/mob/living/simple_mob/vore/vampire/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
index 7fd294c6955..55172c26970 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
@@ -1,6 +1,7 @@
/mob/living/simple_mob/vore
mob_class = MOB_CLASS_ANIMAL
mob_bump_flag = 0
+ can_be_drop_pred = TRUE
/mob/living/simple_mob
var/nameset
@@ -21,6 +22,11 @@
ooc_notes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes)
ooc_notes_likes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_likes)
ooc_notes_dislikes = client.prefs.read_preference(/datum/preference/text/living/ooc_notes_dislikes)
+ /* Not implemented on virgo
+ ooc_notes_favs = read_preference(/datum/preference/text/living/ooc_notes_favs)
+ ooc_notes_maybes = read_preference(/datum/preference/text/living/ooc_notes_maybes)
+ ooc_notes_style = read_preference(/datum/preference/toggle/living/ooc_notes_style)
+ */
private_notes = client.prefs.read_preference(/datum/preference/text/living/private_notes)
digestable = client.prefs_vr.digestable
devourable = client.prefs_vr.devourable
@@ -30,7 +36,7 @@
can_be_drop_pred = client.prefs_vr.can_be_drop_pred
throw_vore = client.prefs_vr.throw_vore
food_vore = client.prefs_vr.food_vore
- allow_inbelly_spawning = client.prefs_vr.allow_inbelly_spawning
+ consume_liquid_belly = client.prefs_vr.consume_liquid_belly
allow_spontaneous_tf = client.prefs_vr.allow_spontaneous_tf
digest_leave_remains = client.prefs_vr.digest_leave_remains
allowmobvore = client.prefs_vr.allowmobvore
@@ -51,6 +57,26 @@
pickup_pref = client.prefs_vr.pickup_pref
allow_mind_transfer = client.prefs_vr.allow_mind_transfer
+ phase_vore = client.prefs_vr.phase_vore
+ latejoin_vore = client.prefs_vr.latejoin_vore
+ latejoin_prey = client.prefs_vr.latejoin_prey
+ receive_reagents = client.prefs_vr.receive_reagents
+ give_reagents = client.prefs_vr.give_reagents
+ apply_reagents = client.prefs_vr.apply_reagents
+ autotransferable = client.prefs_vr.autotransferable
+ noisy_full = client.prefs_vr.noisy_full
+ strip_pref = client.prefs_vr.strip_pref
+ vore_sprite_color = client.prefs_vr.vore_sprite_color
+ vore_sprite_multiply = client.prefs_vr.vore_sprite_multiply
+ no_latejoin_vore_warning = client.prefs_vr.no_latejoin_vore_warning
+ no_latejoin_prey_warning = client.prefs_vr.no_latejoin_prey_warning
+ no_latejoin_vore_warning_time = client.prefs_vr.no_latejoin_vore_warning_time
+ no_latejoin_prey_warning_time = client.prefs_vr.no_latejoin_prey_warning_time
+ no_latejoin_vore_warning_persists = client.prefs_vr.no_latejoin_vore_warning_persists
+ no_latejoin_prey_warning_persists = client.prefs_vr.no_latejoin_prey_warning_persists
+ belly_rub_target = client.prefs_vr.belly_rub_target
+ soulcatcher_pref_flags = client.prefs_vr.soulcatcher_pref_flags
+
/mob/living/simple_mob/proc/set_name()
set name = "Set Name"
set desc = "Sets your mobs name. You only get to do this once."
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm
index 78422f22b0c..45487a947e1 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm
@@ -73,6 +73,8 @@
/mob/living/simple_mob/vore/vore_hostile/abyss_lurker/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "interior"
@@ -193,6 +195,8 @@
/mob/living/simple_mob/vore/vore_hostile/leaper/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
@@ -311,6 +315,8 @@
/mob/living/simple_mob/vore/vore_hostile/gelatinous_cube/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "interior"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/wolftaur.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolftaur.dm
index 3687687c93e..95e413ca152 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/wolftaur.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/wolftaur.dm
@@ -71,6 +71,8 @@
/mob/living/simple_mob/vore/wolftaur/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm b/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm
index 0607a2b8f71..6129996e836 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm
@@ -224,6 +224,8 @@
/mob/living/simple_mob/animal/space/carp/holographic/init_vore()
if(!voremob_loaded)
return
+ if(LAZYLEN(vore_organs))
+ return
. = ..()
var/safe = (faction == FACTION_NEUTRAL)
for(var/obj/belly/B as anything in vore_organs)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index a2de68dfa54..e5e5f7395e4 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -15,7 +15,7 @@
spellremove(src)
if(!istype(src,/mob/observer))
ghostize()
- // QDEL_NULL(soulgem) //Soulcatcher. Needs to be ported sometime.
+ QDEL_NULL(soulgem) //Soulcatcher
QDEL_NULL(dna)
QDEL_NULL(plane_holder)
QDEL_NULL(hud_used)
diff --git a/code/modules/mob/mob_helpers_vr.dm b/code/modules/mob/mob_helpers_vr.dm
index 5f1b49bbbfc..302b9f34dc0 100644
--- a/code/modules/mob/mob_helpers_vr.dm
+++ b/code/modules/mob/mob_helpers_vr.dm
@@ -19,6 +19,14 @@
if(VIS_CH_VANTAG in vis_enabled)
plane_holder.set_vis(VIS_CH_VANTAG,FALSE)
vis_enabled -= VIS_CH_VANTAG
+
+ if(soulgem?.flag_check(SOULGEM_SEE_SR_SOULS))
+ plane_holder.set_vis(VIS_SOULCATCHER, TRUE)
+ vis_enabled += VIS_SOULCATCHER
+ else
+ plane_holder.set_vis(VIS_SOULCATCHER, FALSE)
+ vis_enabled -= VIS_SOULCATCHER
+
return
diff --git a/code/modules/mob/mob_planes_vr.dm b/code/modules/mob/mob_planes_vr.dm
index 521ad9a7977..0cfc9341094 100644
--- a/code/modules/mob/mob_planes_vr.dm
+++ b/code/modules/mob/mob_planes_vr.dm
@@ -5,6 +5,7 @@
plane_masters[VIS_CH_BACKUP] = new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status
plane_masters[VIS_CH_VANTAG] = new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags
plane_masters[VIS_CH_STOMACH] = new /obj/screen/plane_master{plane = PLANE_CH_STOMACH} //Stomach
+ plane_masters[VIS_SOULCATCHER] = new /obj/screen/plane_master{plane = PLANE_SOULCATCHER} // Soulcatcher
plane_masters[VIS_AUGMENTED] = new /obj/screen/plane_master/augmented(M = my_mob) //Augmented reality
..()
diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm
index 0bd757f3f3e..cdfec3a2de6 100644
--- a/code/modules/nifsoft/software/13_soulcatcher.dm
+++ b/code/modules/nifsoft/software/13_soulcatcher.dm
@@ -1,12 +1,3 @@
-//These two also have NIF FLAG representations. These are the local setting representations.
-#define NIF_SC_CATCHING_ME 0x1
-#define NIF_SC_CATCHING_OTHERS 0x2
-//These are purely local setings flags, without global representation.
-#define NIF_SC_ALLOW_EARS 0x4
-#define NIF_SC_ALLOW_EYES 0x8
-#define NIF_SC_BACKUPS 0x10
-#define NIF_SC_PROJECTING 0x20
-
///////////
// Soulcatcher - Like a posibrain, sorta!
/datum/nifsoft/soulcatcher
@@ -237,6 +228,7 @@
//Complex version for catching in-round characters
/datum/nifsoft/soulcatcher/proc/catch_mob(var/mob/M)
if(!M.mind) return
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE)) return
//Create a new brain mob
var/mob/living/carbon/brain/caught_soul/brainmob = new(nif)
@@ -267,6 +259,11 @@
brainmob.ooc_notes = H.ooc_notes
brainmob.ooc_notes_likes = H.ooc_notes_likes
brainmob.ooc_notes_dislikes = H.ooc_notes_dislikes
+ /* Not implemented on virgo
+ brainmob.ooc_notes_favs = H.ooc_notes_favs
+ brainmob.ooc_notes_maybes = H.ooc_notes_maybes
+ brainmob.ooc_notes_style = H.ooc_notes_style
+ */
brainmob.timeofhostdeath = H.timeofdeath
SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it.
@@ -311,6 +308,7 @@
/mob/living/carbon/brain/caught_soul/Login()
..()
plane_holder.set_vis(VIS_AUGMENTED, TRUE)
+ plane_holder.set_vis(VIS_SOULCATCHER, TRUE)
identifying_gender = client.prefs.identifying_gender
/mob/living/carbon/brain/caught_soul/Destroy()
@@ -332,7 +330,7 @@
. = ..()
- if(!parent_mob && !transient &&(life_tick % 150 == 0) && soulcatcher.setting_flags & NIF_SC_BACKUPS)
+ if(!parent_mob && !transient &&(life_tick % 150 == 0) && soulcatcher?.setting_flags & NIF_SC_BACKUPS)
SStranscore.m_backup(mind,0) //Passed 0 means "Don't touch the nif fields on the mind record"
life_tick++
@@ -347,20 +345,23 @@
if(parent_mob) return
//If they're blinded
- if(ext_blind)
- eye_blind = 5
- client.screen.Remove(global_hud.whitense)
- overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
- else
- eye_blind = 0
- clear_fullscreens()
- client.screen.Add(global_hud.whitense)
+ if(soulcatcher) // needs it's own handling to allow vore_fx
+ if(ext_blind)
+ eye_blind = 5
+ client.screen.Remove(global_hud.whitense)
+ overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
+ else
+ eye_blind = 0
+ clear_fullscreens()
+ client.screen.Add(global_hud.whitense)
//If they're deaf
if(ext_deaf)
ear_deaf = 5
+ //deaf_loop.start(skip_start_sound = TRUE) // Not implemented on Virgo
else
ear_deaf = 0
+ //deaf_loop.stop() // Not implemented on Virgo
/mob/living/carbon/brain/caught_soul/hear_say()
if(ext_deaf || !client)
@@ -429,7 +430,7 @@
plane = PLANE_AUGMENTED
icon = 'icons/obj/machines/ar_elements.dmi'
icon_state = "beacon"
- var/mob/living/carbon/human/parent_human
+ var/mob/living/parent_human
/mob/observer/eye/ar_soul/New(var/mob/brainmob, var/human)
ASSERT(brainmob && brainmob.client)
@@ -490,19 +491,38 @@
///////////////////
//The catching hook
-/hook/death/proc/nif_soulcatcher(var/mob/living/carbon/human/H)
- if(!istype(H) || !H.mind) return TRUE //Hooks must return TRUE
+/hook/death/proc/nif_soulcatcher(var/mob/living/L)
+ if(!istype(L) || !L.mind) return TRUE //Hooks must return TRUE
- if(isbelly(H.loc)) //Died in someone
- var/obj/belly/B = H.loc
+ if(isbelly(L.loc)) //Died in someone
+ var/obj/belly/B = L.loc
+ var/mob/living/owner = B.owner
+ var/obj/soulgem/gem = owner.soulgem
+ if(gem && gem.flag_check(SOULGEM_ACTIVE | NIF_SC_CATCHING_OTHERS, TRUE))
+ var/to_use_custom_name = null
+ if(isanimal(L))
+ to_use_custom_name = L.name
+ gem.catch_mob(L, to_use_custom_name)
+ return TRUE
var/mob/living/carbon/human/HP = B.owner
+ var/mob/living/carbon/human/H = L
+ if(!istype(H)) return TRUE
if(istype(HP) && HP.nif && HP.nif.flag_check(NIF_O_SCOTHERS,NIF_FLAGS_OTHER))
var/datum/nifsoft/soulcatcher/SC = HP.nif.imp_check(NIF_SOULCATCHER)
SC.catch_mob(H)
- else if(H.nif && H.nif.flag_check(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)) //They are caught in their own NIF
- var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER)
- SC.catch_mob(H)
-
+ else
+ var/obj/soulgem/gem = L.soulgem
+ if(gem && gem.flag_check(SOULGEM_ACTIVE | NIF_SC_CATCHING_ME, TRUE))
+ var/to_use_custom_name = null
+ if(isanimal(L))
+ to_use_custom_name = L.name
+ gem.catch_mob(L, to_use_custom_name)
+ return TRUE
+ var/mob/living/carbon/human/H = L
+ if(!istype(H)) return TRUE
+ if(H.nif && H.nif.flag_check(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)) //They are caught in their own NIF
+ var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER)
+ SC.catch_mob(H)
return TRUE
///////////////////
@@ -571,7 +591,7 @@
///////////////////
//Verbs for soulbrains
/mob/living/carbon/brain/caught_soul/verb/ar_project()
- set name = "AR Project"
+ set name = "AR/SR Project"
set desc = "Project your form into Augmented Reality for those around your predator with the appearance of your loaded character."
set category = "Soulcatcher"
@@ -633,10 +653,3 @@
if(message)
var/sane_message = sanitize(message)
soulcatcher.emote_into(sane_message,src,null)
-
-#undef NIF_SC_CATCHING_ME
-#undef NIF_SC_CATCHING_OTHERS
-#undef NIF_SC_ALLOW_EARS
-#undef NIF_SC_ALLOW_EYES
-#undef NIF_SC_BACKUPS
-#undef NIF_SC_PROJECTING
diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm
index ffbc08484a4..13c3da89220 100644
--- a/code/modules/power/antimatter/control.dm
+++ b/code/modules/power/antimatter/control.dm
@@ -9,8 +9,8 @@
idle_power_usage = 100
active_power_usage = 1000
- var/list/obj/machinery/am_shielding/linked_shielding
- var/list/obj/machinery/am_shielding/linked_cores
+ var/list/obj/machinery/am_shielding/linked_shielding = list()
+ var/list/obj/machinery/am_shielding/linked_cores = list()
var/obj/item/am_containment/fueljar
var/update_shield_icons = 0
var/stability = 100
@@ -28,17 +28,10 @@
var/stored_power = 0//Power to deploy per tick
-
-/obj/machinery/power/am_control_unit/Initialize(mapload)
- . = ..()
- linked_shielding = list()
- linked_cores = list()
-
-
/obj/machinery/power/am_control_unit/Destroy()//Perhaps damage and run stability checks rather than just qdel on the others
for(var/obj/machinery/am_shielding/AMS in linked_shielding)
qdel(AMS)
- ..()
+ . = ..()
/obj/machinery/power/am_control_unit/process()
diff --git a/code/modules/power/antimatter/shielding.dm b/code/modules/power/antimatter/shielding.dm
index 98f7d27d1a1..e40795338ab 100644
--- a/code/modules/power/antimatter/shielding.dm
+++ b/code/modules/power/antimatter/shielding.dm
@@ -74,8 +74,7 @@
if(processing) shutdown_core()
visible_message(span_red("The [src.name] melts!"))
//Might want to have it leave a mess on the floor but no sprites for now
- ..()
- return
+ . = ..()
/obj/machinery/am_shielding/CanPass(atom/movable/mover, turf/target)
diff --git a/code/modules/power/fusion/core/core_control.dm b/code/modules/power/fusion/core/core_control.dm
index 3641180ccd1..dc9b699cbeb 100644
--- a/code/modules/power/fusion/core/core_control.dm
+++ b/code/modules/power/fusion/core/core_control.dm
@@ -19,7 +19,7 @@
/obj/machinery/computer/fusion_core_control/Destroy()
QDEL_NULL(monitor)
- ..()
+ . = ..()
/obj/machinery/computer/fusion_core_control/attackby(var/obj/item/thing, var/mob/user)
..()
diff --git a/code/modules/power/fusion/fuel_assembly/fuel_control.dm b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
index 55eb334d258..7ff0542453a 100644
--- a/code/modules/power/fusion/fuel_assembly/fuel_control.dm
+++ b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
@@ -17,7 +17,7 @@
/obj/machinery/computer/fusion_fuel_control/Destroy()
QDEL_NULL(monitor)
- ..()
+ . = ..()
/obj/machinery/computer/fusion_fuel_control/attack_ai(var/mob/user)
attack_hand(user)
diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
index f11544efed8..f9349a3496d 100644
--- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm
+++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
@@ -19,7 +19,7 @@
/obj/machinery/computer/gyrotron_control/Destroy()
QDEL_NULL(monitor)
- ..()
+ . = ..()
/obj/machinery/computer/gyrotron_control/attack_ai(var/mob/user)
attack_hand(user)
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 0fc411857bb..c7ad66d6738 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -59,7 +59,7 @@
message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1)
log_game("EMITTER([x],[y],[z]) Destroyed/deleted.")
investigate_log(span_red("deleted") + " at ([x],[y],[z])","singulo")
- ..()
+ . = ..()
/obj/machinery/power/emitter/update_icon()
if (active && powernet && avail(active_power_usage))
diff --git a/code/modules/power/singularity/particle_accelerator/particle_smasher.dm b/code/modules/power/singularity/particle_accelerator/particle_smasher.dm
index 65b843e2870..9f4a09dbf28 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_smasher.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_smasher.dm
@@ -37,7 +37,7 @@
for(var/datum/particle_smasher_recipe/D in recipes)
qdel(D)
recipes.Cut()
- ..()
+ . = ..()
/obj/machinery/particle_smasher/examine(mob/user)
. = ..()
diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm
index bc29919636d..ed5f5e84c5f 100644
--- a/code/modules/power/tracker.dm
+++ b/code/modules/power/tracker.dm
@@ -26,7 +26,7 @@
/obj/machinery/power/tracker/Destroy()
unset_control() //remove from control computer
- ..()
+ . = ..()
//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/tracker/proc/set_control(var/obj/machinery/power/solar_control/SC)
diff --git a/code/modules/reagents/holder/holder.dm b/code/modules/reagents/holder/holder.dm
index 5e1c33b58fc..4bf8c1542dd 100644
--- a/code/modules/reagents/holder/holder.dm
+++ b/code/modules/reagents/holder/holder.dm
@@ -274,7 +274,7 @@
return splash_mob(target, amount, copy)
if(isturf(target))
return trans_to_turf(target, amount, multiplier, copy)
- if(isobj(target) && target.is_open_container())
+ if(isobj(target) && target.is_open_container() && !isbelly(target.loc))
return trans_to_obj(target, amount, multiplier, copy)
return 0
diff --git a/code/modules/reagents/holder/vorebelly.dm b/code/modules/reagents/holder/vorebelly.dm
new file mode 100644
index 00000000000..78b8b68d7a2
--- /dev/null
+++ b/code/modules/reagents/holder/vorebelly.dm
@@ -0,0 +1,26 @@
+/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(isliving(target))
+ if(type == CHEM_VORE)
+ var/datum/reagents/R = target_belly.reagents
+ if(!R)
+ R = new /datum/reagents(amount)
+ target_belly.reagents = R
+ return trans_to_holder(R, amount, multiplier, copy)
+ if(type == CHEM_INGEST && iscarbon(target))
+ var/mob/living/carbon/C = target
+ 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/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/reagents/machinery/distillery.dm b/code/modules/reagents/machinery/distillery.dm
index b602da0c5bc..a8288ac4f08 100644
--- a/code/modules/reagents/machinery/distillery.dm
+++ b/code/modules/reagents/machinery/distillery.dm
@@ -99,7 +99,7 @@
qdel(OutputBeaker)
OutputBeaker = null
- ..()
+ . = ..()
/obj/machinery/portable_atmospherics/powered/reagent_distillery/examine(mob/user)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/_reagent_containers.dm b/code/modules/reagents/reagent_containers/_reagent_containers.dm
index c817f9e565c..b9153a08242 100644
--- a/code/modules/reagents/reagent_containers/_reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers/_reagent_containers.dm
@@ -101,6 +101,11 @@
to_chat(user, span_notice("\The [src] is empty."))
return TRUE
+ if(!target.consume_liquid_belly)
+ if(liquid_belly_check())
+ to_chat(user, span_infoplain("[user == target ? "You can't" : "\The [target] can't"] consume that, it contains something produced from a belly!"))
+ return FALSE
+
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!H.check_has_mouth())
@@ -145,3 +150,9 @@
var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
to_chat(user, span_notice("You transfer [trans] units of the solution to [target]."))
return 1
+
+/obj/item/reagent_containers/proc/liquid_belly_check()
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(R.from_belly)
+ return TRUE
+ return FALSE
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 6b7c05d6130..41d6ebc4789 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -35,6 +35,10 @@
return
if (!istype(M))
return
+ if(!M.consume_liquid_belly)
+ if(liquid_belly_check())
+ to_chat(user, span_infoplain("[user == M ? "You can't" : "\The [M] can't"] take that, it contains something produced from a belly!"))
+ return FALSE
var/mob/living/carbon/human/H = M
if(istype(H))
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 6536fe14f75..55e1b093814 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -23,6 +23,10 @@
icon_state = "[base_state][rand(1, 4)]" //preset pills only use colour changing or unique icons
/obj/item/reagent_containers/pill/attack(mob/M as mob, mob/user as mob)
+ if(!M.consume_liquid_belly)
+ if(liquid_belly_check())
+ to_chat(user, span_infoplain("[user == M ? "You can't" : "\The [M] can't"] consume that, it contains something produced from a belly!"))
+ return FALSE
if(M == user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index c9b6c923236..fe939643cc8 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -194,6 +194,10 @@
var/mob/living/carbon/human/H = target
var/obj/item/organ/external/affected //VOREStation Edit - Moved this outside this if
if(istype(H))
+ if(!H.consume_liquid_belly)
+ if(liquid_belly_check())
+ to_chat(user, span_infoplain("[user == H ? "You can't" : "\The [H] can't"] take that, it contains something produced from a belly!"))
+ return
affected = H.get_organ(user.zone_sel.selecting) //VOREStation Edit - See above comment.
if(!affected)
to_chat(user, span_danger("\The [H] is missing that limb!"))
diff --git a/code/modules/reagents/reagents/_reagents.dm b/code/modules/reagents/reagents/_reagents.dm
index 4f37c1aee22..76a1d337133 100644
--- a/code/modules/reagents/reagents/_reagents.dm
+++ b/code/modules/reagents/reagents/_reagents.dm
@@ -44,6 +44,8 @@
var/glass_desc = "It's a glass of... what, exactly?"
var/list/glass_special = null // null equivalent to list()
+ var/from_belly = FALSE
+
/datum/reagent/proc/remove_self(var/amount) // Shortcut
if(holder)
holder.remove_reagent(id, amount)
diff --git a/code/modules/reagents/reagents/dispenser.dm b/code/modules/reagents/reagents/dispenser.dm
index b72ca66fe62..5cea4764805 100644
--- a/code/modules/reagents/reagents/dispenser.dm
+++ b/code/modules/reagents/reagents/dispenser.dm
@@ -331,6 +331,22 @@
new /obj/effect/decal/cleanable/greenglow(T)
return
+/datum/reagent/radium/concentrated
+ name = REAGENT_CONCENTRATEDRADIUM
+ id = REAGENT_ID_CONCENTRATEDRADIUM
+ description = "Concentrated Radium is a more potent variant of regular radium, able to pierce and irradiate a subject through their skin."
+ taste_mult = 0 //Apparently radium is tasteless
+ reagent_state = SOLID
+ color = "#C7C7C7"
+
+/datum/reagent/radium/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
+ if(issmall(M)) removed *= 2
+ M.apply_effect(10 * removed, IRRADIATE, 0) // Radium may increase your chances to cure a disease
+
+/datum/reagent/radium/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
+ if(issmall(M)) removed *= 2
+ M.apply_effect(10 * removed, IRRADIATE, 0) // Radium may increase your chances to cure a disease
+
/datum/reagent/acid
name = REAGENT_SACID
id = REAGENT_ID_SACID
diff --git a/code/modules/reagents/reagents/liquid_belly.dm b/code/modules/reagents/reagents/liquid_belly.dm
new file mode 100644
index 00000000000..21c098b25a6
--- /dev/null
+++ b/code/modules/reagents/reagents/liquid_belly.dm
@@ -0,0 +1,49 @@
+// Subtypes of other reagents specifically used in liquid bellies, otherwise identical to the parent
+
+/datum/reagent/water/liquid_belly
+ id = REAGENT_ID_WATER_BELLY
+ from_belly = TRUE
+
+/datum/reagent/drink/milk/liquid_belly
+ id = REAGENT_ID_MILK_BELLY
+ from_belly = TRUE
+
+/datum/reagent/drink/milk/cream/liquid_belly
+ id = REAGENT_ID_CREAM_BELLY
+ from_belly = TRUE
+
+/datum/reagent/nutriment/honey/liquid_belly
+ id = REAGENT_ID_HONEY_BELLY
+ from_belly = TRUE
+
+/datum/reagent/nutriment/cherryjelly/liquid_belly
+ id = REAGENT_ID_CHERRYJELLY_BELLY
+ from_belly = TRUE
+
+/datum/reagent/acid/digestive/liquid_belly
+ id = REAGENT_ID_STOMACID_BELLY
+ from_belly = TRUE
+
+/datum/reagent/acid/diet_digestive/liquid_belly
+ id = REAGENT_ID_DIETSTOMACID_BELLY
+ from_belly = TRUE
+
+/datum/reagent/space_cleaner/liquid_belly
+ id = REAGENT_ID_CLEANER_BELLY
+ from_belly = TRUE
+
+/datum/reagent/lube/liquid_belly
+ id = REAGENT_ID_LUBE_BELLY
+ from_belly = TRUE
+
+/datum/reagent/nutriment/biomass/liquid_belly
+ id = REAGENT_ID_BIOMASS_BELLY
+ from_belly = TRUE
+
+/datum/reagent/radium/concentrated/liquid_belly
+ id = REAGENT_ID_CONCENTRATEDRADIUM_BELLY
+ from_belly = TRUE
+
+/datum/reagent/tricordrazine/liquid_belly
+ id = REAGENT_ID_TRICORDRAZINE_BELLY
+ from_belly = TRUE
diff --git a/code/modules/reagents/reagents/medicine_vr.dm b/code/modules/reagents/reagents/medicine_vr.dm
index 0f714451299..9cd16baf70d 100644
--- a/code/modules/reagents/reagents/medicine_vr.dm
+++ b/code/modules/reagents/reagents/medicine_vr.dm
@@ -223,6 +223,8 @@
M.vore_selected = null
ourmob.mob_belly_transfer(M)
+ M.soulgem.transfer_self(ourmob) // Soulcatcher
+
ourmob.Life(1)
if(ishuman(M))
for(var/obj/item/W in M)
diff --git a/code/modules/reagents/reagents/toxins.dm b/code/modules/reagents/reagents/toxins.dm
index 07f0eb65a16..1546957a6a6 100644
--- a/code/modules/reagents/reagents/toxins.dm
+++ b/code/modules/reagents/reagents/toxins.dm
@@ -485,6 +485,16 @@
power = 2
meltdose = 30
+/datum/reagent/acid/diet_digestive
+ name = REAGENT_DIETSTOMACID
+ id = REAGENT_ID_DIETSTOMACID
+ description = "Some form of digestive slurry."
+ taste_description = "vomit"
+ reagent_state = LIQUID
+ color = "#664330"
+ power = 0.4
+ meltdose = 150
+
/datum/reagent/thermite/venom
name = REAGENT_THERMITEV
id = REAGENT_ID_THERMITEV
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index a63cc880924..59a489c32f0 100755
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -478,4 +478,4 @@
/obj/machinery/disposal/deliveryChute/Destroy()
if(trunk)
trunk.linked = null
- ..()
+ . = ..()
diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm
index cd0e6ed2464..f3b7ff395f1 100644
--- a/code/modules/research/message_server.dm
+++ b/code/modules/research/message_server.dm
@@ -288,7 +288,7 @@ var/obj/machinery/blackbox_recorder/blackbox
BR.messages_admin = messages_admin
if(blackbox != BR)
blackbox = BR
- ..()
+ . = ..()
/obj/machinery/blackbox_recorder/proc/find_feedback_datum(var/variable)
for(var/datum/feedback_variable/FV in feedback)
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 1d30e198517..1798f3203b1 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -21,7 +21,7 @@
/obj/machinery/r_n_d/server/Destroy()
griefProtection()
- ..()
+ . = ..()
/obj/machinery/r_n_d/server/RefreshParts()
var/tot_rating = 0
diff --git a/code/modules/shieldgen/sheldwallgen.dm b/code/modules/shieldgen/sheldwallgen.dm
index 106a57af490..84fc3227ec3 100644
--- a/code/modules/shieldgen/sheldwallgen.dm
+++ b/code/modules/shieldgen/sheldwallgen.dm
@@ -209,7 +209,7 @@
src.cleanup(2)
src.cleanup(4)
src.cleanup(8)
- ..()
+ . = ..()
/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj)
storedpower -= 400 * Proj.get_structure_damage()
@@ -254,7 +254,7 @@
/obj/machinery/shieldwall/Destroy()
update_nearby_tiles()
- ..()
+ . = ..()
/obj/machinery/shieldwall/attack_hand(mob/user as mob)
return
diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm
index ef89d145cb2..ca63a334044 100644
--- a/code/modules/ventcrawl/ventcrawl.dm
+++ b/code/modules/ventcrawl/ventcrawl.dm
@@ -11,6 +11,7 @@ var/list/ventcrawl_machinery = list(
/obj/item/holder,
/obj/machinery/camera,
/obj/belly,
+ /obj/soulgem,
/obj/screen,
/atom/movable/emissive_blocker,
/obj/item/rig/protean
diff --git a/code/modules/vore/eating/belly_import.dm b/code/modules/vore/eating/belly_import.dm
index 002987ba00d..e7eb74ee32b 100644
--- a/code/modules/vore/eating/belly_import.dm
+++ b/code/modules/vore/eating/belly_import.dm
@@ -91,14 +91,13 @@
if(islist(belly_data["addons"]))
new_belly.mode_flags = 0
- //new_belly.slow_digestion = FALSE // Not implemented on virgo
- //new_belly.speedy_mob_processing = FALSE // Not implemented on virgo
+ new_belly.slow_digestion = FALSE
+ new_belly.speedy_mob_processing = FALSE
STOP_PROCESSING(SSbellies, new_belly)
- // STOP_PROCESSING(SSobj, new_belly) // Not implemented on virgo
+ STOP_PROCESSING(SSobj, new_belly)
START_PROCESSING(SSbellies, new_belly)
for(var/addon in belly_data["addons"])
new_belly.mode_flags += new_belly.mode_flag_list[addon]
- /* Not implemented on virgo
switch(addon)
if("Slow Body Digestion")
new_belly.slow_digestion = TRUE
@@ -106,7 +105,6 @@
new_belly.speedy_mob_processing = TRUE
STOP_PROCESSING(SSbellies, new_belly)
START_PROCESSING(SSobj, new_belly)
- */
// Descriptions
if(istext(belly_data["desc"]))
@@ -140,262 +138,262 @@
if(islist(belly_data["digest_messages_prey"]))
var/new_digest_messages_prey = sanitize(jointext(belly_data["digest_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_digest_messages_prey)
- new_belly.set_messages(new_digest_messages_prey,"dmp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_digest_messages_prey,DIGEST_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["digest_messages_owner"]))
var/new_digest_messages_owner = sanitize(jointext(belly_data["digest_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_digest_messages_owner)
- new_belly.set_messages(new_digest_messages_owner,"dmo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_digest_messages_owner,DIGEST_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorb_messages_prey"]))
var/new_absorb_messages_prey = sanitize(jointext(belly_data["absorb_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorb_messages_prey)
- new_belly.set_messages(new_absorb_messages_prey,"amp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorb_messages_prey,ABSORB_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorb_messages_owner"]))
var/new_absorb_messages_owner = sanitize(jointext(belly_data["absorb_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorb_messages_owner)
- new_belly.set_messages(new_absorb_messages_owner,"amo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorb_messages_owner,ABSORB_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["unabsorb_messages_prey"]))
var/new_unabsorb_messages_prey = sanitize(jointext(belly_data["unabsorb_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_unabsorb_messages_prey)
- new_belly.set_messages(new_unabsorb_messages_prey,"uamp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_unabsorb_messages_prey,UNABSORBS_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["unabsorb_messages_owner"]))
var/new_unabsorb_messages_owner = sanitize(jointext(belly_data["unabsorb_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_unabsorb_messages_owner)
- new_belly.set_messages(new_unabsorb_messages_owner,"uamo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_unabsorb_messages_owner,UNABSORBS_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["struggle_messages_outside"]))
var/new_struggle_messages_outside = sanitize(jointext(belly_data["struggle_messages_outside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_struggle_messages_outside)
- new_belly.set_messages(new_struggle_messages_outside,"smo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_struggle_messages_outside,STRUGGLE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["struggle_messages_inside"]))
var/new_struggle_messages_inside = sanitize(jointext(belly_data["struggle_messages_inside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_struggle_messages_inside)
- new_belly.set_messages(new_struggle_messages_inside,"smi", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_struggle_messages_inside,STRUGGLE_INSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorbed_struggle_messages_outside"]))
var/new_absorbed_struggle_messages_outside = sanitize(jointext(belly_data["absorbed_struggle_messages_outside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorbed_struggle_messages_outside)
- new_belly.set_messages(new_absorbed_struggle_messages_outside,"asmo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorbed_struggle_messages_outside,ABSORBED_STRUGGLE_OUSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorbed_struggle_messages_inside"]))
var/new_absorbed_struggle_messages_inside = sanitize(jointext(belly_data["absorbed_struggle_messages_inside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorbed_struggle_messages_inside)
- new_belly.set_messages(new_absorbed_struggle_messages_inside,"asmi", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorbed_struggle_messages_inside,ABSORBED_STRUGGLE_INSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_attempt_messages_prey"]))
var/new_escape_attempt_messages_prey = sanitize(jointext(belly_data["escape_attempt_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_attempt_messages_prey)
- new_belly.set_messages(new_escape_attempt_messages_prey,"escap", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_attempt_messages_prey,ESCAPE_ATTEMPT_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_attempt_messages_owner"]))
var/new_escape_attempt_messages_owner = sanitize(jointext(belly_data["escape_attempt_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_attempt_messages_owner)
- new_belly.set_messages(new_escape_attempt_messages_owner,"escao", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_attempt_messages_owner,ESCAPE_ATTEMPT_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_messages_prey"]))
var/new_escape_messages_prey = sanitize(jointext(belly_data["escape_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_messages_prey)
- new_belly.set_messages(new_escape_messages_prey,"escp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_messages_prey,ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_messages_owner"]))
var/new_escape_messages_owner = sanitize(jointext(belly_data["escape_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_messages_owner)
- new_belly.set_messages(new_escape_messages_owner,"esco", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_messages_owner,ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_messages_outside"]))
var/new_escape_messages_outside = sanitize(jointext(belly_data["escape_messages_outside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_messages_outside)
- new_belly.set_messages(new_escape_messages_outside,"escout", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_messages_outside,ESCAPE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_item_messages_prey"]))
var/new_escape_item_messages_prey = sanitize(jointext(belly_data["escape_item_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_item_messages_prey)
- new_belly.set_messages(new_escape_item_messages_prey,"escip", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_item_messages_prey,ESCAPE_ITEM_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_item_messages_owner"]))
var/new_escape_item_messages_owner = sanitize(jointext(belly_data["escape_item_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_item_messages_owner)
- new_belly.set_messages(new_escape_item_messages_owner,"escio", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_item_messages_owner,ESCAPE_ITEM_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_item_messages_outside"]))
var/new_escape_item_messages_outside = sanitize(jointext(belly_data["escape_item_messages_outside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_item_messages_outside)
- new_belly.set_messages(new_escape_item_messages_outside,"esciout", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_item_messages_outside,ESCAPE_ITEM_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_fail_messages_prey"]))
var/new_escape_fail_messages_prey = sanitize(jointext(belly_data["escape_fail_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_fail_messages_prey)
- new_belly.set_messages(new_escape_fail_messages_prey,"escfp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_fail_messages_prey,ESCAPE_FAIL_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_fail_messages_owner"]))
var/new_escape_fail_messages_owner = sanitize(jointext(belly_data["escape_fail_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_fail_messages_owner)
- new_belly.set_messages(new_escape_fail_messages_owner,"escfo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_fail_messages_owner,ESCAPE_FAIL_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_attempt_absorbed_messages_prey"]))
var/new_escape_attempt_absorbed_messages_prey = sanitize(jointext(belly_data["escape_attempt_absorbed_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_attempt_absorbed_messages_prey)
- new_belly.set_messages(new_escape_attempt_absorbed_messages_prey,"aescap", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_attempt_absorbed_messages_prey,ABSORBED_ESCAPE_ATTEMPT_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_attempt_absorbed_messages_owner"]))
var/new_escape_attempt_absorbed_messages_owner = sanitize(jointext(belly_data["escape_attempt_absorbed_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_attempt_absorbed_messages_owner)
- new_belly.set_messages(new_escape_attempt_absorbed_messages_owner,"aescao", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_attempt_absorbed_messages_owner,ABSORBED_ESCAPE_ATTEMPT_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_absorbed_messages_prey"]))
var/new_escape_absorbed_messages_prey = sanitize(jointext(belly_data["escape_absorbed_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_absorbed_messages_prey)
- new_belly.set_messages(new_escape_absorbed_messages_prey,"aescp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_absorbed_messages_prey,ABSORBED_ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_absorbed_messages_owner"]))
var/new_escape_absorbed_messages_owner = sanitize(jointext(belly_data["escape_absorbed_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_absorbed_messages_owner)
- new_belly.set_messages(new_escape_absorbed_messages_owner,"aesco", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_absorbed_messages_owner,ABSORBED_ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_absorbed_messages_outside"]))
var/new_escape_absorbed_messages_outside = sanitize(jointext(belly_data["escape_absorbed_messages_outside"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_absorbed_messages_outside)
- new_belly.set_messages(new_escape_absorbed_messages_outside,"aescout", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_absorbed_messages_outside,ABSORBED_ESCAPE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_fail_absorbed_messages_prey"]))
var/new_escape_fail_absorbed_messages_prey = sanitize(jointext(belly_data["escape_fail_absorbed_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_fail_absorbed_messages_prey)
- new_belly.set_messages(new_escape_fail_absorbed_messages_prey,"aescfp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_fail_absorbed_messages_prey,FULL_ABSORBED_ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["escape_fail_absorbed_messages_owner"]))
var/new_escape_fail_absorbed_messages_owner = sanitize(jointext(belly_data["escape_fail_absorbed_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_escape_fail_absorbed_messages_owner)
- new_belly.set_messages(new_escape_fail_absorbed_messages_owner,"aescfo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_escape_fail_absorbed_messages_owner,FULL_ABSORBED_ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["primary_transfer_messages_prey"]))
var/new_primary_transfer_messages_prey = sanitize(jointext(belly_data["primary_transfer_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_primary_transfer_messages_prey)
- new_belly.set_messages(new_primary_transfer_messages_prey,"trnspp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_primary_transfer_messages_prey,PRIMARY_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["primary_transfer_messages_owner"]))
var/new_primary_transfer_messages_owner = sanitize(jointext(belly_data["primary_transfer_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_primary_transfer_messages_owner)
- new_belly.set_messages(new_primary_transfer_messages_owner,"trnspo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_primary_transfer_messages_owner,PRIMARY_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["secondary_transfer_messages_prey"]))
var/new_secondary_transfer_messages_prey = sanitize(jointext(belly_data["secondary_transfer_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_secondary_transfer_messages_prey)
- new_belly.set_messages(new_secondary_transfer_messages_prey,"trnssp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_secondary_transfer_messages_prey,SECONDARY_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["secondary_transfer_messages_owner"]))
var/new_secondary_transfer_messages_owner = sanitize(jointext(belly_data["secondary_transfer_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_secondary_transfer_messages_owner)
- new_belly.set_messages(new_secondary_transfer_messages_owner,"trnsso", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_secondary_transfer_messages_owner,SECONDARY_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["primary_autotransfer_messages_prey"]))
var/new_primary_autotransfer_messages_prey = sanitize(jointext(belly_data["primary_autotransfer_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_primary_autotransfer_messages_prey)
- new_belly.set_messages(new_primary_autotransfer_messages_prey,"atrnspp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_primary_autotransfer_messages_prey,PRIMARY_AUTO_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["primary_autotransfer_messages_owner"]))
var/new_primary_autotransfer_messages_owner = sanitize(jointext(belly_data["primary_autotransfer_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_primary_autotransfer_messages_owner)
- new_belly.set_messages(new_primary_autotransfer_messages_owner,"atrnspo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_primary_autotransfer_messages_owner,PRIMARY_AUTO_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["secondary_autotransfer_messages_prey"]))
var/new_secondary_autotransfer_messages_prey = sanitize(jointext(belly_data["secondary_autotransfer_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_secondary_autotransfer_messages_prey)
- new_belly.set_messages(new_secondary_autotransfer_messages_prey,"atrnssp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_secondary_autotransfer_messages_prey,SECONDARY_AUTO_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["secondary_autotransfer_messages_owner"]))
var/new_secondary_autotransfer_messages_owner = sanitize(jointext(belly_data["secondary_autotransfer_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_secondary_autotransfer_messages_owner)
- new_belly.set_messages(new_secondary_autotransfer_messages_owner,"atrnsso", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_secondary_autotransfer_messages_owner,SECONDARY_AUTO_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["digest_chance_messages_prey"]))
var/new_digest_chance_messages_prey = sanitize(jointext(belly_data["digest_chance_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_digest_chance_messages_prey)
- new_belly.set_messages(new_digest_chance_messages_prey,"stmodp", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_digest_chance_messages_prey,DIGEST_CHANCE_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["digest_chance_messages_owner"]))
var/new_digest_chance_messages_owner = sanitize(jointext(belly_data["digest_chance_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_digest_chance_messages_owner)
- new_belly.set_messages(new_digest_chance_messages_owner,"stmodo", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_digest_chance_messages_owner,DIGEST_CHANCE_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorb_chance_messages_prey"]))
var/new_absorb_chance_messages_prey = sanitize(jointext(belly_data["absorb_chance_messages_prey"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorb_chance_messages_prey)
- new_belly.set_messages(new_absorb_chance_messages_prey,"stmoap", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorb_chance_messages_prey,ABSORB_CHANCE_PREY, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["absorb_chance_messages_owner"]))
var/new_absorb_chance_messages_owner = sanitize(jointext(belly_data["absorb_chance_messages_owner"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_absorb_chance_messages_owner)
- new_belly.set_messages(new_absorb_chance_messages_owner,"stmoao", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_absorb_chance_messages_owner,ABSORB_CHANCE_OWNER, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["examine_messages"]))
var/new_examine_messages = sanitize(jointext(belly_data["examine_messages"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_examine_messages)
- new_belly.set_messages(new_examine_messages,"em", limit = MAX_MESSAGE_LEN / 2)
+ new_belly.set_messages(new_examine_messages,EXAMINES, limit = MAX_MESSAGE_LEN / 2)
if(islist(belly_data["examine_messages_absorbed"]))
var/new_examine_messages_absorbed = sanitize(jointext(belly_data["examine_messages_absorbed"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_examine_messages_absorbed)
- new_belly.set_messages(new_examine_messages_absorbed,"ema", limit = MAX_MESSAGE_LEN / 2)
+ new_belly.set_messages(new_examine_messages_absorbed,EXAMINES_ABSORBED, limit = MAX_MESSAGE_LEN / 2)
if(islist(belly_data["emotes_digest"]))
var/new_emotes_digest = sanitize(jointext(belly_data["emotes_digest"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_digest)
- new_belly.set_messages(new_emotes_digest,"im_digest", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_digest,BELLY_MODE_DIGEST, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_hold"]))
var/new_emotes_hold = sanitize(jointext(belly_data["emotes_hold"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_hold)
- new_belly.set_messages(new_emotes_hold,"im_hold", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_hold,BELLY_MODE_HOLD, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_holdabsorbed"]))
var/new_emotes_holdabsorbed = sanitize(jointext(belly_data["emotes_holdabsorbed"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_holdabsorbed)
- new_belly.set_messages(new_emotes_holdabsorbed,"im_holdabsorbed", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_holdabsorbed,BELLY_MODE_HOLD_ABSORB, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_absorb"]))
var/new_emotes_absorb = sanitize(jointext(belly_data["emotes_absorb"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_absorb)
- new_belly.set_messages(new_emotes_absorb,"im_absorb", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_absorb,BELLY_MODE_ABSORB, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_heal"]))
var/new_emotes_heal = sanitize(jointext(belly_data["emotes_heal"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_heal)
- new_belly.set_messages(new_emotes_heal,"im_heal", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_heal,BELLY_MODE_HEAL, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_drain"]))
var/new_emotes_drain = sanitize(jointext(belly_data["emotes_drain"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_drain)
- new_belly.set_messages(new_emotes_drain,"im_drain", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_drain,BELLY_MODE_DRAIN, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_steal"]))
var/new_emotes_steal = sanitize(jointext(belly_data["emotes_steal"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_steal)
- new_belly.set_messages(new_emotes_steal,"im_steal", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_steal,BELLY_MODE_STEAL, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_egg"]))
var/new_emotes_egg = sanitize(jointext(belly_data["emotes_egg"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_egg)
- new_belly.set_messages(new_emotes_egg,"im_egg", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_egg,BELLY_MODE_EGG, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_shrink"]))
var/new_emotes_shrink = sanitize(jointext(belly_data["emotes_shrink"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_shrink)
- new_belly.set_messages(new_emotes_shrink,"im_shrink", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_shrink,BELLY_MODE_SHRINK, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_grow"]))
var/new_emotes_grow = sanitize(jointext(belly_data["emotes_grow"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_grow)
- new_belly.set_messages(new_emotes_grow,"im_grow", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_grow,BELLY_MODE_GROW, limit = MAX_MESSAGE_LEN / 4)
if(islist(belly_data["emotes_unabsorb"]))
var/new_emotes_unabsorb = sanitize(jointext(belly_data["emotes_unabsorb"],"\n\n"),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_emotes_unabsorb)
- new_belly.set_messages(new_emotes_unabsorb,"im_unabsorb", limit = MAX_MESSAGE_LEN / 4)
+ new_belly.set_messages(new_emotes_unabsorb,BELLY_MODE_UNABSORB, limit = MAX_MESSAGE_LEN / 4)
// Options
if(isnum(belly_data["can_taste"]))
@@ -405,14 +403,12 @@
if(new_can_taste == 1)
new_belly.can_taste = TRUE
- /* Not implemented on virgo
if(isnum(belly_data["is_feedable"]))
var/new_is_feedable = belly_data["is_feedable"]
if(new_is_feedable == 0)
new_belly.is_feedable = FALSE
if(new_is_feedable == 1)
new_belly.is_feedable = TRUE
- */
if(isnum(belly_data["contaminates"]))
var/new_contaminates = belly_data["contaminates"]
@@ -469,33 +465,32 @@
var/new_emote_time = belly_data["emote_time"]
new_belly.emote_time = CLAMP(new_emote_time, 60, 600)
- // new_belly.set_zero_digestion_damage() // Not implemented on virgo; needed for importing a belly to overwrite an existing belly; otherwise pre-existing values throw off the unused digestion damage.
+ new_belly.set_zero_digestion_damage() // Not implemented on virgo; CHOMPEnale needed for importing a belly to overwrite an existing belly; otherwise pre-existing values throw off the unused digestion damage.
if(isnum(belly_data["digest_brute"]))
var/new_digest_brute = belly_data["digest_brute"]
- new_belly.digest_brute = CLAMP(new_digest_brute, 0, 6)
+ new_belly.digest_brute = CLAMP(new_digest_brute, 0, new_belly.get_unused_digestion_damage())
if(isnum(belly_data["digest_burn"]))
var/new_digest_burn = belly_data["digest_burn"]
- new_belly.digest_burn = CLAMP(new_digest_burn, 0, 6)
+ new_belly.digest_burn = CLAMP(new_digest_burn, 0, new_belly.get_unused_digestion_damage())
if(isnum(belly_data["digest_oxy"]))
var/new_digest_oxy = belly_data["digest_oxy"]
- new_belly.digest_oxy = CLAMP(new_digest_oxy, 0, 12)
+ new_belly.digest_oxy = CLAMP(new_digest_oxy, 0, new_belly.get_unused_digestion_damage())
if(isnum(belly_data["digest_tox"]))
var/new_digest_tox = belly_data["digest_tox"]
- new_belly.digest_tox = CLAMP(new_digest_tox, 0, 6)
+ new_belly.digest_tox = CLAMP(new_digest_tox, 0, new_belly.get_unused_digestion_damage())
if(isnum(belly_data["digest_clone"]))
var/new_digest_clone = belly_data["digest_clone"]
- new_belly.digest_clone = CLAMP(new_digest_clone, 0, 6)
+ new_belly.digest_clone = CLAMP(new_digest_clone, 0, new_belly.get_unused_digestion_damage())
if(isnum(belly_data["shrink_grow_size"]))
var/new_shrink_grow_size = belly_data["shrink_grow_size"]
new_belly.shrink_grow_size = CLAMP(new_shrink_grow_size, 0.25, 2)
- /* Not implemented on virgo
if(isnum(belly_data["vorespawn_blacklist"]))
var/new_vorespawn_blacklist = belly_data["vorespawn_blacklist"]
if(new_vorespawn_blacklist == 0)
@@ -516,7 +511,6 @@
new_vorespawn_absorbed |= VS_FLAG_ABSORB_YES
new_vorespawn_absorbed |= VS_FLAG_ABSORB_PREY
new_belly.vorespawn_absorbed = new_vorespawn_absorbed
- */
if(istext(belly_data["egg_type"]))
var/new_egg_type = sanitize(belly_data["egg_type"],MAX_MESSAGE_LEN,0,0,0)
@@ -524,7 +518,6 @@
if(new_egg_type in global_vore_egg_types)
new_belly.egg_type = new_egg_type
- /* Not implemented on virgo
if(istext(belly_data["egg_name"]))
var/new_egg_name = html_encode(belly_data["egg_name"])
if(new_egg_name)
@@ -566,7 +559,6 @@
new_belly.item_digest_logs = FALSE
if(new_item_digest_logs == 1)
new_belly.item_digest_logs = TRUE
- */
if(istext(belly_data["selective_preference"]))
var/new_selective_preference = belly_data["selective_preference"]
@@ -575,14 +567,12 @@
if(new_selective_preference == "Absorb")
new_belly.selective_preference = DM_ABSORB
- /* Not implemented on virgo
if(isnum(belly_data["private_struggle"]))
var/new_private_struggle = belly_data["private_struggle"]
if(new_private_struggle == 0)
new_belly.private_struggle = FALSE
if(new_private_struggle == 1)
new_belly.private_struggle = TRUE
- */
if(istext(belly_data["eating_privacy_local"]))
var/new_eating_privacy_local = html_encode(belly_data["eating_privacy_local"])
@@ -638,7 +628,6 @@
if (!new_belly.fancy_vore && (new_release_sound in classic_release_sounds))
new_belly.release_sound = new_release_sound
- /* Not implemented on virgo
if(isnum(belly_data["sound_volume"]))
var/new_sound_volume = belly_data["sound_volume"]
new_belly.sound_volume = sanitize_integer(new_sound_volume, 0, 100, initial(new_belly.sound_volume))
@@ -646,7 +635,6 @@
if(isnum(belly_data["noise_freq"]))
var/new_noise_freq = belly_data["noise_freq"]
new_belly.noise_freq = sanitize_integer(new_noise_freq, MIN_VOICE_FREQ, MAX_VOICE_FREQ, initial(new_belly.noise_freq))
- */
// Visuals
if(isnum(belly_data["affects_vore_sprites"]))
@@ -769,21 +757,20 @@
var/new_belly_fullscreen_color = sanitize_hexcolor(belly_data["belly_fullscreen_color"],new_belly.belly_fullscreen_color)
new_belly.belly_fullscreen_color = new_belly_fullscreen_color
- if(istext(belly_data["belly_fullscreen_color_secondary"]))
- var/new_belly_fullscreen_color_secondary = sanitize_hexcolor(belly_data["belly_fullscreen_color_secondary"],new_belly.belly_fullscreen_color_secondary)
- new_belly.belly_fullscreen_color_secondary = new_belly_fullscreen_color_secondary
- else if (istext(belly_data["belly_fullscreen_color2"])) // Inter server support between virgo and chomp!
- var/new_belly_fullscreen_color_secondary = sanitize_hexcolor(belly_data["belly_fullscreen_color2"],new_belly.belly_fullscreen_color_secondary)
- new_belly.belly_fullscreen_color_secondary = new_belly_fullscreen_color_secondary
+ if(istext(belly_data["belly_fullscreen_color2"]))
+ var/new_belly_fullscreen_color2 = sanitize_hexcolor(belly_data["belly_fullscreen_color2"],new_belly.belly_fullscreen_color2)
+ new_belly.belly_fullscreen_color2 = new_belly_fullscreen_color2
+ else if(istext(belly_data["belly_fullscreen_color_secondary"])) // Inter server support between virgo and chomp!
+ var/new_belly_fullscreen_color2 = sanitize_hexcolor(belly_data["belly_fullscreen_color_secondary"],new_belly.belly_fullscreen_color2)
+ new_belly.belly_fullscreen_color2 = new_belly_fullscreen_color2
- if(istext(belly_data["belly_fullscreen_color_trinary"]))// Inter server support between virgo and chomp!
- var/new_belly_fullscreen_color_trinary = sanitize_hexcolor(belly_data["belly_fullscreen_color_trinary"],new_belly.belly_fullscreen_color_trinary)
- new_belly.belly_fullscreen_color_trinary = new_belly_fullscreen_color_trinary
- else if(istext(belly_data["belly_fullscreen_color3"]))
- var/new_belly_fullscreen_color_trinary = sanitize_hexcolor(belly_data["belly_fullscreen_color3"],new_belly.belly_fullscreen_color_trinary)
- new_belly.belly_fullscreen_color_trinary = new_belly_fullscreen_color_trinary
+ if(istext(belly_data["belly_fullscreen_color3"]))
+ var/new_belly_fullscreen_color3 = sanitize_hexcolor(belly_data["belly_fullscreen_color3"],new_belly.belly_fullscreen_color3)
+ new_belly.belly_fullscreen_color3 = new_belly_fullscreen_color3
+ else if(istext(belly_data["belly_fullscreen_color_trinary"])) // Inter server support between virgo and chomp!
+ var/new_belly_fullscreen_color3 = sanitize_hexcolor(belly_data["belly_fullscreen_color_trinary"],new_belly.belly_fullscreen_color3)
+ new_belly.belly_fullscreen_color3 = new_belly_fullscreen_color3
- /* Not implemented on virgo
if(istext(belly_data["belly_fullscreen_color4"]))
var/new_belly_fullscreen_color4 = sanitize_hexcolor(belly_data["belly_fullscreen_color4"],new_belly.belly_fullscreen_color4)
new_belly.belly_fullscreen_color4 = new_belly_fullscreen_color4
@@ -791,7 +778,6 @@
if(istext(belly_data["belly_fullscreen_alpha"]))
var/new_belly_fullscreen_alpha = sanitize_integer(belly_data["belly_fullscreen_alpha"],0,255,initial(new_belly.belly_fullscreen_alpha))
new_belly.belly_fullscreen_alpha = new_belly_fullscreen_alpha
- */
if(isnum(belly_data["colorization_enabled"]))
var/new_colorization_enabled = belly_data["colorization_enabled"]
@@ -807,12 +793,9 @@
if(new_disable_hud == 1)
new_belly.disable_hud = TRUE
- var/possible_fullscreens = icon_states('icons/mob/screen_full_colorized_vore.dmi')
+ var/possible_fullscreens = icon_states('icons/mob/screen_full_vore_list.dmi')
if(!new_belly.colorization_enabled)
possible_fullscreens = icon_states('icons/mob/screen_full_vore.dmi')
- possible_fullscreens -= "a_synth_flesh_mono"
- possible_fullscreens -= "a_synth_flesh_mono_hole"
- possible_fullscreens -= "a_anim_belly"
if(!(new_belly.belly_fullscreen in possible_fullscreens))
new_belly.belly_fullscreen = ""
@@ -875,7 +858,6 @@
if(new_transferlocation_secondary == new_belly.name)
new_belly.transferlocation_secondary = null
- /* Not implemented on virgo
if(islist(belly_data["autotransfer_whitelist"]))
new_belly.autotransfer_whitelist = 0
for(var/at_flag in belly_data["autotransfer_whitelist"])
@@ -895,7 +877,6 @@
new_belly.autotransfer_secondary_blacklist = 0
for(var/at_flag in belly_data["autotransfer_secondary_blacklist"])
new_belly.autotransfer_secondary_blacklist += new_belly.autotransfer_flags_list[at_flag]
- */
if(isnum(belly_data["absorbchance"]))
var/new_absorbchance = belly_data["absorbchance"]
@@ -905,14 +886,12 @@
var/new_digestchance = belly_data["digestchance"]
new_belly.digestchance = sanitize_integer(new_digestchance, 0, 100, initial(new_belly.digestchance))
- /* Not implemented on virgo
if(isnum(belly_data["autotransfer_enabled"]))
var/new_autotransfer_enabled = belly_data["autotransfer_enabled"]
if(new_autotransfer_enabled == 0)
new_belly.autotransfer_enabled = FALSE
if(new_autotransfer_enabled == 1)
new_belly.autotransfer_enabled = TRUE
- */
if(isnum(belly_data["autotransferwait"]))
var/new_autotransferwait = belly_data["autotransferwait"]
@@ -934,7 +913,6 @@
if(new_autotransferlocation == new_belly.name)
new_belly.autotransferlocation = null
- /* Not implemented on virgo
if(islist(belly_data["autotransferextralocation"]))
var/new_autotransferextralocation = belly_data["autotransferextralocation"]
if(new_autotransferextralocation)
@@ -1169,11 +1147,10 @@
var/new_fullness5_messages = sanitize(jointext(belly_data["fullness5_messages"],"\n\n"),MAX_MESSAGE_LEN,0,0,0)
if(new_fullness5_messages)
new_belly.set_reagent_messages(new_fullness5_messages,"full5")
- */
// After import updates
new_belly.items_preserved.Cut()
- // new_belly.update_internal_overlay() // Signal not implemented!
+ new_belly.update_internal_overlay() // Signal not implemented! CHOMPEnable
host.handle_belly_update()
host.updateVRPanel()
diff --git a/code/modules/vore/eating/belly_messages.dm b/code/modules/vore/eating/belly_messages.dm
index 197a0b3e629..f95b41aeb20 100644
--- a/code/modules/vore/eating/belly_messages.dm
+++ b/code/modules/vore/eating/belly_messages.dm
@@ -93,6 +93,18 @@
var/list/secondary_transfer_messages_prey = list(
"Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into %pred's %dest!")
+ var/list/primary_autotransfer_messages_owner = list(
+ "%prey moves along into your %dest!")
+
+ var/list/primary_autotransfer_messages_prey = list(
+ "%pred's %belly moves you along into their %dest!")
+
+ var/list/secondary_autotransfer_messages_owner = list(
+ "%prey moves along into your %dest!")
+
+ var/list/secondary_autotransfer_messages_prey = list(
+ "%pred's %belly moves you along into their %dest!")
+
var/list/digest_chance_messages_owner = list(
"You feel your %belly beginning to become active!")
@@ -223,7 +235,7 @@ GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","
// but can easily make the message vary based on how many people are inside, etc.
// Returns a string which shoul be appended to the Examine output.
/obj/belly/proc/get_examine_msg()
- if(!(contents.len) || !(examine_messages.len))
+ if(!(LAZYLEN(contents)) || !(LAZYLEN(examine_messages)))
return ""
var/raw_message = pick(examine_messages)
@@ -244,7 +256,7 @@ GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","
return(span_red(span_italics("[belly_format_string(raw_message, english_list(vore_contents))]")))
/obj/belly/proc/get_examine_msg_absorbed()
- if(!(contents.len) || !(examine_messages_absorbed.len) || !display_absorbed_examine)
+ if(!(LAZYLEN(contents)) || !(LAZYLEN(examine_messages_absorbed)) || !display_absorbed_examine)
return ""
var/raw_message = pick(examine_messages_absorbed)
@@ -265,105 +277,113 @@ GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","
// 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_messages(type, delim = "\n\n")
- ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb")
+ VB_MESSAGE_SANIRY(type)
var/list/raw_messages
switch(type)
- if("smo")
+ if(STRUGGLE_OUTSIDE)
raw_messages = struggle_messages_outside
- if("smi")
+ if(STRUGGLE_INSIDE)
raw_messages = struggle_messages_inside
- if("asmo")
+ if(ABSORBED_STRUGGLE_OUSIDE)
raw_messages = absorbed_struggle_messages_outside
- if("asmi")
+ if(ABSORBED_STRUGGLE_INSIDE)
raw_messages = absorbed_struggle_messages_inside
- if("escao")
+ if(ESCAPE_ATTEMPT_OWNER)
raw_messages = escape_attempt_messages_owner
- if("escap")
+ if(ESCAPE_ATTEMPT_PREY)
raw_messages = escape_attempt_messages_prey
- if("esco")
+ if(ESCAPE_OWNER)
raw_messages = escape_messages_owner
- if("escp")
+ if(ESCAPE_PREY)
raw_messages = escape_messages_prey
- if("escout")
+ if(ESCAPE_OUTSIDE)
raw_messages = escape_messages_outside
- if("escio")
+ if(ESCAPE_ITEM_OWNER)
raw_messages = escape_item_messages_owner
- if("escip")
+ if(ESCAPE_ITEM_PREY)
raw_messages = escape_item_messages_prey
- if("esciout")
+ if(ESCAPE_ITEM_OUTSIDE)
raw_messages = escape_item_messages_outside
- if("escfo")
+ if(ESCAPE_FAIL_OWNER)
raw_messages = escape_fail_messages_owner
- if("escfp")
+ if(ESCAPE_FAIL_PREY)
raw_messages = escape_fail_messages_prey
- if("aescao")
+ if(ABSORBED_ESCAPE_ATTEMPT_OWNER)
raw_messages = escape_attempt_absorbed_messages_owner
- if("aescap")
+ if(ABSORBED_ESCAPE_ATTEMPT_PREY)
raw_messages = escape_attempt_absorbed_messages_prey
- if("aesco")
+ if(ABSORBED_ESCAPE_OWNER)
raw_messages = escape_absorbed_messages_owner
- if("aescp")
+ if(ABSORBED_ESCAPE_PREY)
raw_messages = escape_absorbed_messages_prey
- if("aescout")
+ if(ABSORBED_ESCAPE_OUTSIDE)
raw_messages = escape_absorbed_messages_outside
- if("aescfo")
+ if(FULL_ABSORBED_ESCAPE_OWNER)
raw_messages = escape_fail_absorbed_messages_owner
- if("aescfp")
+ if(FULL_ABSORBED_ESCAPE_PREY)
raw_messages = escape_fail_absorbed_messages_prey
- if("trnspo")
+ if(PRIMARY_TRANSFER_OWNER)
raw_messages = primary_transfer_messages_owner
- if("trnspp")
+ if(PRIMARY_TRANSFER_PREY)
raw_messages = primary_transfer_messages_prey
- if("trnsso")
+ if(SECONDARY_TRANSFER_OWNER)
raw_messages = secondary_transfer_messages_owner
- if("trnssp")
+ if(SECONDARY_TRANSFER_PREY)
raw_messages = secondary_transfer_messages_prey
- if("stmodo")
+ if(PRIMARY_AUTO_TRANSFER_OWNER)
+ raw_messages = primary_autotransfer_messages_owner
+ if(PRIMARY_AUTO_TRANSFER_PREY)
+ raw_messages = primary_autotransfer_messages_prey
+ if(SECONDARY_AUTO_TRANSFER_OWNER)
+ raw_messages = secondary_autotransfer_messages_owner
+ if(SECONDARY_AUTO_TRANSFER_PREY)
+ raw_messages = secondary_autotransfer_messages_prey
+ if(DIGEST_CHANCE_OWNER)
raw_messages = digest_chance_messages_owner
- if("stmodp")
+ if(DIGEST_CHANCE_PREY)
raw_messages = digest_chance_messages_prey
- if("stmoao")
+ if(ABSORB_CHANCE_OWNER)
raw_messages = absorb_chance_messages_owner
- if("stmoap")
+ if(ABSORB_CHANCE_PREY)
raw_messages = absorb_chance_messages_prey
- if("dmo")
+ if(DIGEST_OWNER)
raw_messages = digest_messages_owner
- if("dmp")
+ if(DIGEST_PREY)
raw_messages = digest_messages_prey
- if("em")
+ if(EXAMINES)
raw_messages = examine_messages
- if("ema")
+ if(EXAMINES_ABSORBED)
raw_messages = examine_messages_absorbed
- if("amo")
+ if(ABSORB_OWNER)
raw_messages = absorb_messages_owner
- if("amp")
+ if(ABSORB_PREY)
raw_messages = absorb_messages_prey
- if("uamo")
+ if(UNABSORBS_OWNER)
raw_messages = unabsorb_messages_owner
- if("uamp")
+ if(UNABSORBS_PREY)
raw_messages = unabsorb_messages_prey
- if("im_digest")
+ if(BELLY_MODE_DIGEST)
raw_messages = emote_lists[DM_DIGEST]
- if("im_hold")
+ if(BELLY_MODE_HOLD)
raw_messages = emote_lists[DM_HOLD]
- if("im_holdabsorbed")
+ if(BELLY_MODE_HOLD_ABSORB)
raw_messages = emote_lists[DM_HOLD_ABSORBED]
- if("im_absorb")
+ if(BELLY_MODE_ABSORB)
raw_messages = emote_lists[DM_ABSORB]
- if("im_heal")
+ if(BELLY_MODE_HEAL)
raw_messages = emote_lists[DM_HEAL]
- if("im_drain")
+ if(BELLY_MODE_DRAIN)
raw_messages = emote_lists[DM_DRAIN]
- if("im_steal")
+ if(BELLY_MODE_STEAL)
raw_messages = emote_lists[DM_SIZE_STEAL]
- if("im_egg")
+ if(BELLY_MODE_EGG)
raw_messages = emote_lists[DM_EGG]
- if("im_shrink")
+ if(BELLY_MODE_SHRINK)
raw_messages = emote_lists[DM_SHRINK]
- if("im_grow")
+ if(BELLY_MODE_GROW)
raw_messages = emote_lists[DM_GROW]
- if("im_unabsorb")
+ if(BELLY_MODE_UNABSORB)
raw_messages = emote_lists[DM_UNABSORB]
var/messages = null
if(raw_messages)
@@ -377,7 +397,7 @@ GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","
/obj/belly/proc/set_messages(raw_text, type, delim = "\n\n", limit)
if(!limit)
CRASH("[src] set message called without limit!")
- ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb")
+ VB_MESSAGE_SANIRY(type)
var/list/raw_list
@@ -410,99 +430,107 @@ GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","
ASSERT(raw_list.len <= 10) //Sanity
switch(type)
- if("smo")
+ if(STRUGGLE_OUTSIDE)
struggle_messages_outside = raw_list
- if("smi")
+ if(STRUGGLE_INSIDE)
struggle_messages_inside = raw_list
- if("asmo")
+ if(ABSORBED_STRUGGLE_OUSIDE)
absorbed_struggle_messages_outside = raw_list
- if("asmi")
+ if(ABSORBED_STRUGGLE_INSIDE)
absorbed_struggle_messages_inside = raw_list
- if("escao")
+ if(ESCAPE_ATTEMPT_OWNER)
escape_attempt_messages_owner = raw_list
- if("escap")
+ if(ESCAPE_ATTEMPT_PREY)
escape_attempt_messages_prey = raw_list
- if("esco")
+ if(ESCAPE_OWNER)
escape_messages_owner = raw_list
- if("escp")
+ if(ESCAPE_PREY)
escape_messages_prey = raw_list
- if("escout")
+ if(ESCAPE_OUTSIDE)
escape_messages_outside = raw_list
- if("escio")
+ if(ESCAPE_ITEM_OWNER)
escape_item_messages_owner = raw_list
- if("escip")
+ if(ESCAPE_ITEM_PREY)
escape_item_messages_prey = raw_list
- if("esciout")
+ if(ESCAPE_ITEM_OUTSIDE)
escape_item_messages_outside = raw_list
- if("escfo")
+ if(ESCAPE_FAIL_OWNER)
escape_fail_messages_owner = raw_list
- if("escfp")
+ if(ESCAPE_FAIL_PREY)
escape_fail_messages_prey = raw_list
- if("aescao")
+ if(ABSORBED_ESCAPE_ATTEMPT_OWNER)
escape_attempt_absorbed_messages_owner = raw_list
- if("aescap")
+ if(ABSORBED_ESCAPE_ATTEMPT_PREY)
escape_attempt_absorbed_messages_prey = raw_list
- if("aesco")
+ if(ABSORBED_ESCAPE_OWNER)
escape_absorbed_messages_owner = raw_list
- if("aescp")
+ if(ABSORBED_ESCAPE_PREY)
escape_absorbed_messages_prey = raw_list
- if("aescout")
+ if(ABSORBED_ESCAPE_OUTSIDE)
escape_absorbed_messages_outside = raw_list
- if("aescfo")
+ if(FULL_ABSORBED_ESCAPE_OWNER)
escape_fail_absorbed_messages_owner = raw_list
- if("aescfp")
+ if(FULL_ABSORBED_ESCAPE_PREY)
escape_fail_absorbed_messages_prey = raw_list
- if("trnspo")
+ if(PRIMARY_TRANSFER_OWNER)
primary_transfer_messages_owner = raw_list
- if("trnspp")
+ if(PRIMARY_TRANSFER_PREY)
primary_transfer_messages_prey = raw_list
- if("trnsso")
+ if(SECONDARY_TRANSFER_OWNER)
secondary_transfer_messages_owner = raw_list
- if("trnssp")
+ if(SECONDARY_TRANSFER_PREY)
secondary_transfer_messages_prey = raw_list
- if("stmodo")
+ if(PRIMARY_AUTO_TRANSFER_OWNER)
+ primary_autotransfer_messages_owner = raw_list
+ if(PRIMARY_AUTO_TRANSFER_PREY)
+ primary_autotransfer_messages_prey = raw_list
+ if(SECONDARY_AUTO_TRANSFER_OWNER)
+ secondary_autotransfer_messages_owner = raw_list
+ if(SECONDARY_AUTO_TRANSFER_PREY)
+ secondary_autotransfer_messages_prey = raw_list
+ if(DIGEST_CHANCE_OWNER)
digest_chance_messages_owner = raw_list
- if("stmodp")
+ if(DIGEST_CHANCE_PREY)
digest_chance_messages_prey = raw_list
- if("stmoao")
+ if(ABSORB_CHANCE_OWNER)
absorb_chance_messages_owner = raw_list
- if("stmoap")
+ if(ABSORB_CHANCE_PREY)
absorb_chance_messages_prey = raw_list
- if("dmo")
+ if(DIGEST_OWNER)
digest_messages_owner = raw_list
- if("dmp")
+ if(DIGEST_PREY)
digest_messages_prey = raw_list
- if("amo")
+ if(ABSORB_OWNER)
absorb_messages_owner = raw_list
- if("amp")
+ if(ABSORB_PREY)
absorb_messages_prey = raw_list
- if("uamo")
+ if(UNABSORBS_OWNER)
unabsorb_messages_owner = raw_list
- if("uamp")
+ if(UNABSORBS_PREY)
unabsorb_messages_prey = raw_list
- if("em")
+ if(EXAMINES)
examine_messages = raw_list
- if("ema")
+ if(EXAMINES_ABSORBED)
examine_messages_absorbed = raw_list
- if("im_digest")
+ if(BELLY_MODE_DIGEST)
emote_lists[DM_DIGEST] = raw_list
- if("im_hold")
+ if(BELLY_MODE_HOLD)
emote_lists[DM_HOLD] = raw_list
- if("im_holdabsorbed")
+ if(BELLY_MODE_HOLD_ABSORB)
emote_lists[DM_HOLD_ABSORBED] = raw_list
- if("im_absorb")
+ if(BELLY_MODE_ABSORB)
emote_lists[DM_ABSORB] = raw_list
- if("im_heal")
+ if(BELLY_MODE_HEAL)
emote_lists[DM_HEAL] = raw_list
- if("im_drain")
+ if(BELLY_MODE_DRAIN)
emote_lists[DM_DRAIN] = raw_list
- if("im_steal")
+ if(BELLY_MODE_STEAL)
emote_lists[DM_SIZE_STEAL] = raw_list
- if("im_egg")
+ if(BELLY_MODE_EGG)
emote_lists[DM_EGG] = raw_list
- if("im_shrink")
+ if(BELLY_MODE_SHRINK)
emote_lists[DM_SHRINK] = raw_list
- if("im_grow")
+ if(BELLY_MODE_GROW)
emote_lists[DM_GROW] = raw_list
- if("im_unabsorb")
+ if(BELLY_MODE_UNABSORB)
emote_lists[DM_UNABSORB] = raw_list
diff --git a/code/modules/vore/eating/belly_obj_liquids.dm b/code/modules/vore/eating/belly_obj_liquids.dm
new file mode 100644
index 00000000000..764ead5049e
--- /dev/null
+++ b/code/modules/vore/eating/belly_obj_liquids.dm
@@ -0,0 +1,391 @@
+///////////////////// NUTRITION REAGENT PRODUCTION /////////////////
+
+/obj/belly/proc/HandleBellyReagents()
+ if(show_liquids && reagentbellymode && reagent_mode_flags & DM_FLAG_REAGENTSNUTRI && reagents.total_volume < custom_max_volume && !isnewplayer(owner)) //Removed if(reagentbellymode == TRUE) since that's less optimized
+ if(isrobot(owner))
+ var/mob/living/silicon/robot/R = owner
+ if(R.cell && R.cell.charge >= gen_cost*10 && gen_interval >= gen_time)
+ GenerateBellyReagents()
+ gen_interval = 0
+ else
+ gen_interval++
+ else
+ if(owner.nutrition >= gen_cost && gen_interval >= gen_time)
+ GenerateBellyReagents()
+ gen_interval = 0
+ else
+ gen_interval++
+
+/obj/belly/proc/HandleBellyReagentEffects(var/list/touchable_atoms)
+ if(LAZYLEN(contents))
+ if(show_liquids && reagent_touches && reagents.total_volume >= 5)
+ var/affecting_amt = reagents.total_volume / max(LAZYLEN(touchable_atoms), 1)
+ if(affecting_amt > 5)
+ affecting_amt = 5
+ if(affecting_amt >= 1)
+ for(var/mob/living/L in touchable_atoms)
+ if(!L.apply_reagents)
+ continue
+ if((L.digestable && digest_mode == DM_DIGEST))
+ if(!L.permit_healbelly && is_beneficial) // Healing reagents turned off in preferences!
+ continue
+ if(reagents.total_volume)
+ reagents.trans_to(L, affecting_amt, 1, FALSE)
+ if(L.permit_healbelly && digest_mode == DM_HEAL)
+ if(is_beneficial && reagents.total_volume)
+ reagents.trans_to(L, affecting_amt, 1, FALSE)
+ for(var/obj/item/I in touchable_atoms)
+ if(is_type_in_list(I, item_digestion_blacklist))
+ continue
+ if(reagents.total_volume)
+ reagents.trans_to(I, affecting_amt, 1, FALSE)
+ SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, FALSE, reagents.total_volume) // Signals vore_fx() reagents updates.
+ for(var/mob/living/L in contents)
+ vore_fx(L, FALSE, reagents.total_volume)
+ if(owner.previewing_belly == src)
+ vore_fx(owner, FALSE, reagents.total_volume)
+
+/obj/belly/proc/GenerateBellyReagents()
+ if(isrobot(owner))
+ var/mob/living/silicon/robot/R = owner
+ if(!R.use_direct_power(gen_cost*10, 200))
+ return
+ else
+ owner.nutrition -= gen_cost
+ for(var/reagent in generated_reagents)
+ reagents.add_reagent(reagent, generated_reagents[reagent])
+ if(count_liquid_for_sprite)
+ owner.handle_belly_update() //This is run whenever a belly's contents are changed.
+ if(LAZYLEN(belly_surrounding))
+ SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, FALSE, reagents.total_volume) // Signals vore_fx() reagents updates.
+
+//////////////////////////// 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) <= custom_max_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 / gen_cost)
+ else
+ owner_adjust_nutrition(digest_nutri_gain * owner.get_digestion_efficiency_modifier())
+ digest_nutri_gain = 0
+
+/obj/belly/proc/GenerateBellyReagents_digested()
+ if(reagents.total_volume <= custom_max_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 * (custom_max_volume - reagents.total_volume))
+ digest_nutri_gain = 0
+
+//////////////////////////// REAGENT_ABSORB ////////////////////////
+
+/obj/belly/proc/GenerateBellyReagents_absorbing()
+ if(reagents.total_volume <= custom_max_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 * (custom_max_volume - reagents.total_volume))
+
+/obj/belly/proc/GenerateBellyReagents_absorbed()
+ if(reagents.total_volume <= custom_max_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 * (custom_max_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()
+ var/list/our_reagents = list()
+ for(var/entry in reagent_choices)
+ our_reagents.Add(lowertext(entry))
+ switch(reagent_chosen)
+ if(REAGENT_WATER)
+ generated_reagents = list(REAGENT_ID_WATER_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_WATER)
+ gen_amount = 1
+ gen_cost = 1
+ reagentid = REAGENT_ID_WATER_BELLY
+ reagentcolor = "#0064C877"
+ if(REAGENT_MILK)
+ generated_reagents = list(REAGENT_ID_MILK_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_MILK)
+ gen_amount = 1
+ gen_cost = 5
+ reagentid = REAGENT_ID_MILK_BELLY
+ reagentcolor = "#DFDFDF"
+ if(REAGENT_CREAM)
+ generated_reagents = list(REAGENT_ID_CREAM_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_CREAM)
+ gen_amount = 1
+ gen_cost = 5
+ reagentid = REAGENT_ID_CREAM_BELLY
+ reagentcolor = "#DFD7AF"
+ if(REAGENT_HONEY)
+ generated_reagents = list(REAGENT_ID_HONEY_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_HONEY)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_HONEY_BELLY
+ reagentcolor = "#FFFF00"
+ if(REAGENT_CHERRYJELLY) //Kinda WIP, allows slime like folks something to stuff others with, should make a generic jelly in future
+ generated_reagents = list(REAGENT_ID_CHERRYJELLY_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_CHERRYJELLY)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_CHERRYJELLY_BELLY
+ reagentcolor = "#801E28"
+ if(REAGENT_STOMACID)
+ generated_reagents = list(REAGENT_ID_STOMACID_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_STOMACID)
+ gen_amount = 1
+ gen_cost = 1
+ reagentid = REAGENT_ID_STOMACID_BELLY
+ reagentcolor = "#664330"
+ if(REAGENT_DIETSTOMACID)
+ generated_reagents = list(REAGENT_ID_DIETSTOMACID_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_DIETSTOMACID)
+ gen_amount = 1
+ gen_cost = 1
+ reagentid = REAGENT_ID_DIETSTOMACID_BELLY
+ reagentcolor = "#664330"
+ if(REAGENT_CLEANER)
+ generated_reagents = list(REAGENT_ID_CLEANER_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_CLEANER)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_CLEANER_BELLY
+ reagentcolor = "#A5F0EE"
+ if(REAGENT_LUBE)
+ generated_reagents = list(REAGENT_ID_LUBE_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_LUBE)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_LUBE_BELLY
+ reagentcolor = "#009CA8"
+ if(REAGENT_BIOMASS)
+ generated_reagents = list(REAGENT_ID_BIOMASS_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_BIOMASS)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_BIOMASS_BELLY
+ reagentcolor = "#DF9FBF"
+ if(REAGENT_CONCENTRATEDRADIUM)
+ generated_reagents = list(REAGENT_ID_CONCENTRATEDRADIUM_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_CONCENTRATEDRADIUM)
+ gen_amount = 1
+ gen_cost = 1
+ reagentid = REAGENT_ID_CONCENTRATEDRADIUM_BELLY
+ reagentcolor = "#C7C7C7"
+ if(REAGENT_TRICORDRAZINE)
+ generated_reagents = list(REAGENT_ID_TRICORDRAZINE_BELLY = 1)
+ if(reagent_name in our_reagents)
+ reagent_name = lowertext(REAGENT_TRICORDRAZINE)
+ gen_amount = 1
+ gen_cost = 10
+ reagentid = REAGENT_ID_TRICORDRAZINE_BELLY
+ reagentcolor = "#8040FF"
+ is_beneficial = TRUE
+
+
+/////////////////////// 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(span_red("[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(span_red("[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(span_red("[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(span_red("[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(span_red("[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 = raw_messages.Join(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 = splittext(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
+
+/////////////////////////// Process Cycle Lite /////////////////////////// CHOMP PCL
+/obj/belly/proc/quick_cycle() //For manual belly cycling without straining the bellies subsystem.
+ HandleBellyReagents() //reagent belly stuff.
+ // VERY early exit
+ if(!contents.len)
+ return
+
+ var/to_update = FALSE //Did anything update worthy happen?
+
+/////////////////////////// Exit Early //////////////////////////// CHOMP PCL
+ var/list/touchable_atoms = contents - items_preserved
+ if(!length(touchable_atoms))
+ return
+
+ var/datum/digest_mode/DM = GLOB.digest_modes["[digest_mode]"]
+ if(!DM)
+ log_debug("Digest mode [digest_mode] didn't exist in the digest_modes list!!")
+ return FALSE
+ if(DM.handle_atoms(src, touchable_atoms))
+ updateVRPanels()
+ return
+
+ var/list/touchable_mobs = null
+
+ var/list/hta_returns = handle_touchable_atoms(touchable_atoms)
+ if(islist(hta_returns))
+ if(hta_returns["touchable_mobs"])
+ touchable_mobs = hta_returns["touchable_mobs"]
+ if(hta_returns["to_update"])
+ to_update = hta_returns["to_update"]
+
+ if(!LAZYLEN(touchable_mobs))
+ return
+
+///////////////////// Time to actually process mobs ///////////////////// CHOMP PCL
+ for(var/target in touchable_mobs)
+ var/mob/living/L = target
+ if(!istype(L))
+ continue
+ var/list/returns = DM.process_mob(src, target)
+ if(istype(returns) && returns["to_update"])
+ to_update = TRUE
+
+ if(to_update)
+ updateVRPanels()
+/////////////////////////// CHOMP PCL END ///////////////////////////
+
+/obj/belly/proc/update_internal_overlay()
+ if(LAZYLEN(belly_surrounding))
+ SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, TRUE) // Signals vore_fx() to listening atoms. Atoms must handle appropriate isliving() checks.
+ for(var/A in belly_surrounding)
+ if(isliving(A))
+ vore_fx(A,1)
+ if(owner.previewing_belly == src)
+ if(isbelly(owner.loc))
+ owner.previewing_belly = null
+ return
+ vore_fx(owner,1)
+
+/obj/belly/deserialize(var/list/data)
+ ..()
+ STOP_PROCESSING(SSbellies, src)
+ STOP_PROCESSING(SSobj, src)
+ if(speedy_mob_processing)
+ START_PROCESSING(SSobj, src)
+ else
+ START_PROCESSING(SSbellies, src)
diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm
index 2f03e95ac02..d3c52d74e9b 100644
--- a/code/modules/vore/eating/belly_obj_vr.dm
+++ b/code/modules/vore/eating/belly_obj_vr.dm
@@ -19,6 +19,7 @@
var/human_prey_swallow_time = 100 // Time in deciseconds to swallow /mob/living/carbon/human
var/nonhuman_prey_swallow_time = 30 // Time in deciseconds to swallow anything else
var/nutrition_percent = 100 // Nutritional percentage per tick in digestion mode
+ var/digest_max = 36 // maximum total damage across all types
var/digest_brute = 0.5 // Brute damage per tick in digestion mode
var/digest_burn = 0.5 // Burn damage per tick in digestion mode
var/digest_oxy = 0 // Oxy damage per tick in digestion mode
@@ -52,16 +53,20 @@
var/obj/item/storage/vore_egg/ownegg // Is this belly creating an egg?
var/egg_type = "Egg" // Default egg type and path.
var/egg_path = /obj/item/storage/vore_egg
+ var/egg_name = null // Custom egg name
+ var/egg_size = 0 // Custom egg size
var/list/list/emote_lists = list() // Idle emotes that happen on their own, depending on the bellymode. Contains lists of strings indexed by bellymode
var/emote_time = 60 // How long between stomach emotes at prey (in seconds)
var/emote_active = TRUE // Are we even giving emotes out at all or not?
var/next_emote = 0 // When we're supposed to print our next emote, as a world.time
var/selective_preference = DM_DIGEST // Which type of selective bellymode do we default to?
var/eating_privacy_local = "default" //Overrides eating_privacy_global if not "default". Determines if attempt/success messages are subtle/loud
+ var/is_feedable = TRUE // If this belly shows up in belly selections for others.
var/silicon_belly_overlay_preference = "Sleeper" //Selects between placing belly overlay in sleeper or normal vore mode. Exclusive
var/belly_mob_mult = 1 //Multiplier for how filling mob types are in borg bellies
var/belly_item_mult = 1 //Multiplier for how filling items are in borg borg bellies. Items are also weighted on item size
var/belly_overall_mult = 1 //Multiplier applied ontop of any other specific multipliers
+ var/private_struggle = FALSE // If struggles are made public or not
var/vore_sprite_flags = DM_FLAG_VORESPRITE_BELLY
@@ -94,14 +99,33 @@
var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location
var/autotransferwait = 10 // Time between trying to transfer.
var/autotransferlocation // Place to send them
+ var/autotransferextralocation = list() // List of extra places this could go
+ var/autotransfer_whitelist = 0 // Flags for what can be transferred to the primary location
+ var/autotransfer_blacklist = 2 // Flags for what can not be transferred to the primary location, defaults to Absorbed
+ var/autotransfer_whitelist_items = 0 // Flags for what can be transferred to the primary location
+ var/autotransfer_blacklist_items = 0 // Flags for what can not be transferred to the primary location
+ var/autotransferchance_secondary = 0 // % Chance of prey being autotransferred to secondary transfer location
+ var/autotransferlocation_secondary // Second place to send them
+ var/autotransferextralocation_secondary = list() // List of extra places the secondary transfer could go
+ var/autotransfer_secondary_whitelist = 0// Flags for what can be transferred to the secondary location
+ var/autotransfer_secondary_blacklist = 2// Flags for what can not be transferred to the secondary location, defaults to Absorbed
+ var/autotransfer_secondary_whitelist_items = 0// Flags for what can be transferred to the secondary location
+ var/autotransfer_secondary_blacklist_items = 0// Flags for what can not be transferred to the secondary location
+ var/autotransfer_enabled = FALSE // Player toggle
+ var/autotransfer_min_amount = 0 // Minimum amount of things to pass at once.
+ var/autotransfer_max_amount = 0 // Maximum amount of things to pass at once.
+ var/tmp/list/autotransfer_queue = list()// Reserve for above things.
+ //Auto-transfer flags for whitelist
+ var/tmp/static/list/autotransfer_flags_list = list("Creatures" = AT_FLAG_CREATURES, "Absorbed" = AT_FLAG_ABSORBED, "Carbon" = AT_FLAG_CARBON, "Silicon" = AT_FLAG_SILICON, "Mobs" = AT_FLAG_MOBS, "Animals" = AT_FLAG_ANIMALS, "Mice" = AT_FLAG_MICE, "Dead" = AT_FLAG_DEAD, "Digestable Creatures" = AT_FLAG_CANDIGEST, "Absorbable Creatures" = AT_FLAG_CANABSORB, "Full Health" = AT_FLAG_HEALTHY)
+ var/tmp/static/list/autotransfer_flags_list_items = list("Items" = AT_FLAG_ITEMS, "Trash" = AT_FLAG_TRASH, "Eggs" = AT_FLAG_EGGS, "Remains" = AT_FLAG_REMAINS, "Indigestible Items" = AT_FLAG_INDIGESTIBLE, "Recyclable Items" = AT_FLAG_RECYCLABLE, "Ores" = AT_FLAG_ORES, "Clothes and Bags" = AT_FLAG_CLOTHES, "Food" = AT_FLAG_FOOD)
//I don't think we've ever altered these lists. making them static until someone actually overrides them somewhere.
//Actual full digest modes
var/tmp/static/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_ABSORB,DM_DRAIN,DM_SELECT,DM_UNABSORB,DM_HEAL,DM_SHRINK,DM_GROW,DM_SIZE_STEAL,DM_EGG)
//Digest mode addon flags
- var/tmp/static/list/mode_flag_list = list("Numbing" = DM_FLAG_NUMBING, "Stripping" = DM_FLAG_STRIPPING, "Leave Remains" = DM_FLAG_LEAVEREMAINS, "Muffles" = DM_FLAG_THICKBELLY, "Affect Worn Items" = DM_FLAG_AFFECTWORN, "Jams Sensors" = DM_FLAG_JAMSENSORS, "Complete Absorb" = DM_FLAG_FORCEPSAY, "Spare Prosthetics" = DM_FLAG_SPARELIMB)
+ var/tmp/static/list/mode_flag_list = list("Numbing" = DM_FLAG_NUMBING, "Stripping" = DM_FLAG_STRIPPING, "Leave Remains" = DM_FLAG_LEAVEREMAINS, "Muffles" = DM_FLAG_THICKBELLY, "Affect Worn Items" = DM_FLAG_AFFECTWORN, "Jams Sensors" = DM_FLAG_JAMSENSORS, "Complete Absorb" = DM_FLAG_FORCEPSAY, "Spare Prosthetics" = DM_FLAG_SPARELIMB, "Slow Body Digestion" = DM_FLAG_SLOWBODY, "Muffle Items" = DM_FLAG_MUFFLEITEMS, "TURBO MODE" = DM_FLAG_TURBOMODE)
//Item related modes
- var/tmp/static/list/item_digest_modes = list(IM_HOLD,IM_DIGEST_FOOD,IM_DIGEST)
+ var/tmp/static/list/item_digest_modes = list(IM_HOLD,IM_DIGEST_FOOD,IM_DIGEST,IM_DIGEST_PARALLEL)
//drain modes
var/tmp/static/list/drainmodes = list(DR_NORMAL,DR_SLEEP,DR_FAKE,DR_WEIGHT)
@@ -116,17 +140,125 @@
var/tmp/digested_prey_count = 0 // Amount of prey that have been digested
var/item_digest_mode = IM_DIGEST_FOOD // Current item-related mode from item_digest_modes
- var/contaminates = FALSE // Whether the belly will contaminate stuff
+ var/contaminates = TRUE // Whether the belly will contaminate stuff
var/contamination_flavor = "Generic" // Determines descriptions of contaminated items
var/contamination_color = "green" // Color of contamination overlay
// Lets you do a fullscreen overlay. Set to an icon_state string.
var/belly_fullscreen = ""
var/disable_hud = FALSE
- var/colorization_enabled = FALSE
+ var/colorization_enabled = TRUE
var/belly_fullscreen_color = "#823232"
- var/belly_fullscreen_color_secondary = "#428242"
- var/belly_fullscreen_color_trinary = "#f0f0f0"
+ var/belly_fullscreen_color2 = "#FFFFFF"
+ var/belly_fullscreen_color3 = "#823232"
+ var/belly_fullscreen_color4 = "#FFFFFF"
+ var/belly_fullscreen_alpha = 255
+
+ // Liquid belly vars
+ 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/show_liquids = FALSE //Moved from vorepanel_ch to be a belly var
+ var/show_fullness_messages = FALSE //Moved from vorepanel_ch to be a belly var
+ var/liquid_overlay = TRUE //Belly-specific liquid overlay toggle
+ var/max_liquid_level = 100 //Custom max level for liquid overlay
+ var/mush_overlay = FALSE //Toggle for nutrition mush overlay
+ var/reagent_touches = TRUE //If reagents touch and interact with things in belly
+ var/mush_color = "#664330" //Nutrition mush overlay color
+ var/mush_alpha = 255 //Mush overlay transparency.
+ var/max_mush = 500 //How much nutrition for full mush overlay
+ var/min_mush = 0 //Manual setting for lowest mush level
+ var/item_mush_val = 0 //How much solid belly contents raise mush level per item
+ var/metabolism_overlay = FALSE //Extra mush layer for ingested reagents currently in metabolism.
+ var/metabolism_mush_ratio = 15 //Metabolism reagent volume per unit compared to nutrition units.
+ var/max_ingested = 500 //How much metabolism content for full overlay.
+ var/ingested_color = "#664330" //Normal color holder for ingested layer. Blended from existing reagent colors.
+ var/custom_ingested_color = null //Custom color for ingested reagent layer.
+ var/custom_ingested_alpha = 255 //Custom alpha for ingested reagent layer if not using normal mush layer.
+
+ var/nutri_reagent_gen = FALSE //if belly produces reagent over time using nutrition, needs to be optimized to use subsystem - Jack
+ var/is_beneficial = FALSE //Sets a reagent as a beneficial one / healing reagents
+ var/list/generated_reagents = list(REAGENT_ID_WATER = 1) //Any number of reagents, the associated value is how many units are generated per process()
+ var/reagent_name = REAGENT_ID_WATER //What is shown when reagents are removed, doesn't need to be an actual reagent
+ var/reagentid = REAGENT_ID_WATER //Selected reagent's id, for use in puddle system currently
+ var/reagentcolor = "#0064C877" //Selected reagent's color, for use in puddle system currently
+ var/custom_reagentcolor //Custom reagent color. Blank for normal reagent color
+ var/custom_reagentalpha //Custom reagent alpha. Blank for capacity based alpha
+ 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 = 5 //Time it takes in seconds to produce one cycle of reagents, technically add 1 second to it for the tick where the fluid is produced
+ var/gen_time_display = "1 hour" //The displayed time it takes from a belly to go from 0 to 100
+ var/custom_max_volume = 100 //Variable for people to limit amount of liquid they can receive/produce in a belly
+ 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/reagent_transfer_verb = "injects" //verb for transfer of reagent from a vore belly
+
+ var/vorefootsteps_sounds = FALSE //If this belly can make sounds when someone walks around
+ 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/vorespawn_blacklist = FALSE
+ var/vorespawn_whitelist = list()
+ var/vorespawn_absorbed = 0
+
+ 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!"
+ )
+
+ var/tmp/reagent_chosen = REAGENT_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
+ REAGENT_WATER,
+ REAGENT_MILK,
+ REAGENT_CREAM,
+ REAGENT_HONEY,
+ REAGENT_CHERRYJELLY,
+ REAGENT_STOMACID,
+ REAGENT_DIETSTOMACID,
+ REAGENT_CLEANER,
+ REAGENT_LUBE,
+ REAGENT_BIOMASS,
+ REAGENT_CONCENTRATEDRADIUM,
+ REAGENT_TRICORDRAZINE
+ )
+
+ // Special var section
+ var/special_entrance_sound // Mob specific custom entry sound set by mob's init_vore when applicable
+ var/slow_digestion = FALSE // Gradual corpse digestion
+ var/slow_brutal = FALSE // Gradual corpse digestion: Stumpy's Special
+ var/sound_volume = 100 // Volume knob.
+ var/speedy_mob_processing = FALSE // Independent belly processing to utilize SSobj instead of SSbellies 3x speed.
+ var/cycle_sloshed = FALSE // Has vorgan entrance made a wet slosh this cycle? Soundspam prevention for multiple items entered.
+ var/egg_cycles = 0 // Process egg mode after 10 cycles.
+ var/recycling = FALSE // Recycling mode.
+ var/entrance_logs = TRUE // Belly-specific entry message toggle.
+ var/noise_freq = 42500 // Tasty sound prefs.
+ var/item_digest_logs = FALSE // Chat messages for digested items.
+ var/storing_nutrition = FALSE // Storing gained nutrition as paste instead of absorbing it.
+ var/belchchance = 0 // % Chance of pred belching on prey struggle
+
+ var/list/belly_surrounding = list() // A list of living mobs surrounded by this belly, including inside containers, food, on mobs, etc. Exclusing inside other bellies.
//For serialization, keep this updated, required for bellies to save correctly.
/obj/belly/vars_to_save()
@@ -159,6 +291,7 @@
"transferchance_secondary",
"transferlocation",
"transferlocation_secondary",
+ "belchchance",
"bulge_size",
"display_absorbed_examine",
"shrink_grow_size",
@@ -187,6 +320,10 @@
"primary_transfer_messages_prey",
"secondary_transfer_messages_owner",
"secondary_transfer_messages_prey",
+ "primary_autotransfer_messages_owner",
+ "primary_autotransfer_messages_prey",
+ "secondary_autotransfer_messages_owner",
+ "secondary_autotransfer_messages_prey",
"digest_chance_messages_owner",
"digest_chance_messages_prey",
"absorb_chance_messages_owner",
@@ -214,10 +351,95 @@
"wet_loop",
"belly_fullscreen",
"disable_hud",
+ "reagent_mode_flags",
"belly_fullscreen_color",
- "belly_fullscreen_color_secondary",
- "belly_fullscreen_color_trinary",
+ "belly_fullscreen_color2",
+ "belly_fullscreen_color3",
+ "belly_fullscreen_color4",
+ "belly_fullscreen_alpha",
"colorization_enabled",
+ "show_liquids",
+ "reagentbellymode",
+ "liquid_fullness1_messages",
+ "liquid_fullness2_messages",
+ "liquid_fullness3_messages",
+ "liquid_fullness4_messages",
+ "liquid_fullness5_messages",
+ "reagent_name",
+ "reagent_chosen",
+ "reagentid",
+ "reagentcolor",
+ "liquid_overlay",
+ "max_liquid_level",
+ "reagent_touches",
+ "mush_overlay",
+ "mush_color",
+ "mush_alpha",
+ "max_mush",
+ "min_mush",
+ "item_mush_val",
+ "custom_reagentcolor",
+ "custom_reagentalpha",
+ "metabolism_overlay",
+ "metabolism_mush_ratio",
+ "max_ingested",
+ "custom_ingested_color",
+ "custom_ingested_alpha",
+ "gen_cost",
+ "gen_amount",
+ "gen_time",
+ "gen_time_display",
+ "reagent_transfer_verb",
+ "custom_max_volume",
+ "generated_reagents",
+ "vorefootsteps_sounds",
+ "fullness1_messages",
+ "fullness2_messages",
+ "fullness3_messages",
+ "fullness4_messages",
+ "fullness5_messages",
+ "vorespawn_blacklist",
+ "vorespawn_whitelist",
+ "vorespawn_absorbed",
+ "absorbed_multiplier",
+ "count_liquid_for_sprite",
+ "liquid_multiplier",
+ "undergarment_chosen",
+ "undergarment_if_none",
+ "undergarment_color",
+ "autotransferchance",
+ "autotransferwait",
+ "autotransferlocation",
+ "autotransferextralocation",
+ "autotransfer_enabled",
+ "autotransferchance_secondary",
+ "autotransferextralocation_secondary",
+ "autotransferlocation_secondary",
+ "autotransfer_secondary_whitelist",
+ "autotransfer_secondary_blacklist",
+ "autotransfer_whitelist",
+ "autotransfer_blacklist",
+ "autotransfer_secondary_whitelist_items",
+ "autotransfer_secondary_blacklist_items",
+ "autotransfer_whitelist_items",
+ "autotransfer_blacklist_items",
+ "autotransfer_min_amount",
+ "autotransfer_max_amount",
+ "slow_digestion",
+ "slow_brutal",
+ "sound_volume",
+ "speedy_mob_processing",
+ "egg_name",
+ "egg_size",
+ "recycling",
+ "storing_nutrition",
+ "is_feedable",
+ "entrance_logs",
+ "noise_freq",
+ "private_struggle",
+ "item_digest_logs",
+ "show_fullness_messages",
+ "digest_max",
"egg_type",
"save_digest_mode",
"eating_privacy_local",
@@ -252,10 +474,19 @@
owner = loc
owner.vore_organs |= src
if(isliving(loc))
- START_PROCESSING(SSbellies, src)
+ if(mode_flags & DM_FLAG_TURBOMODE)
+ START_PROCESSING(SSobj, src)
+ else
+ START_PROCESSING(SSbellies, src)
+
+ create_reagents(300) // 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()
- STOP_PROCESSING(SSbellies, src)
+ if(mode_flags & DM_FLAG_TURBOMODE)
+ STOP_PROCESSING(SSobj, src)
+ else
+ STOP_PROCESSING(SSbellies, src)
owner?.vore_organs?.Remove(src)
owner = null
for(var/mob/observer/G in src)
@@ -264,7 +495,18 @@
// Called whenever an atom enters this belly
/obj/belly/Entered(atom/movable/thing, atom/OldLoc)
-
+ . = ..()
+ if(!owner)
+ thing.forceMove(get_turf(src))
+ return
+ thing.enter_belly(src) // Atom movable proc, does nothing by default. Overridden in children for special behavior.
+ if(owner && istype(owner.loc,/turf/simulated) && !cycle_sloshed && reagents.total_volume > 0)
+ // var/turf/simulated/T = owner.loc
+ var/S = pick(GLOB.slosh)
+ if(S)
+ playsound(owner.loc, S, sound_volume * (reagents.total_volume / 100), FALSE, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises)
+ cycle_sloshed = TRUE
+ thing.belly_cycles = 0 //reset cycle count
if(istype(thing, /mob/observer)) //Ports CHOMPStation PR#3072
if(desc) //Ports CHOMPStation PR#4772
//Allow ghosts see where they are if they're still getting squished along inside.
@@ -272,10 +514,13 @@
if(OldLoc in contents)
return //Someone dropping something (or being stripdigested)
+ if(istype(OldLoc, /mob/observer) || istype(OldLoc, /obj/item/mmi)) // Prevent reforming causing a lot of log spam/sounds
+ return //Someone getting reformed most likely (And if not, uh... shouldn't happen anyways?)
//Generic entered message
- if(!istype(thing, /mob/observer)) //Don't have ghosts announce they're reentering the belly on death
- to_chat(owner,span_vnotice("[thing] slides into your [lowertext(name)]."))
+ if(!owner.mute_entry && entrance_logs)
+ if(!istype(thing, /mob/observer)) //Don't have ghosts announce they're reentering the belly on death
+ to_chat(owner,span_vnotice("[thing] slides into your [lowertext(name)]."))
//Sound w/ antispam flag setting
if(vore_sound && !recent_sound && !istype(thing, /mob/observer))
@@ -284,13 +529,27 @@
soundfile = classic_vore_sounds[vore_sound]
else
soundfile = fancy_vore_sounds[vore_sound]
+ if(special_entrance_sound) // Custom sound set by mob's init_vore or ingame varedits.
+ soundfile = special_entrance_sound
if(soundfile)
- playsound(src, soundfile, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ playsound(src, soundfile, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
recent_sound = TRUE
+ if(reagents.total_volume >= 5 && !isliving(thing) && (item_digest_mode == IM_DIGEST || item_digest_mode == IM_DIGEST_PARALLEL))
+ reagents.trans_to(thing, reagents.total_volume * 0.1, 1 / max(LAZYLEN(contents), 1), FALSE)
//Messages if it's a mob
+ // Include indirect viewers in seeing vorefx
+ var/list/startfx = list()
if(isliving(thing))
- var/mob/living/M = thing
+ var/mob/living/L = thing
+ startfx.Add(L)
+ startfx.Add(get_belly_surrounding(L.contents))
+ owner.handle_belly_update() // This is run whenever a belly's contents are changed.
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ startfx.Add(get_belly_surrounding(I.contents))
+
+ for(var/mob/living/M in startfx) // End of indirect vorefx changes
M.updateVRPanel()
var/raw_desc //Let's use this to avoid needing to write the reformat code twice
if(absorbed_desc && M.absorbed)
@@ -304,119 +563,238 @@
to_chat(M, span_vnotice(span_bold("[belly_format_string(raw_desc, M)]")))
var/taste
- if(can_taste && (taste = M.get_taste_message(FALSE)))
+ if(can_taste && M.loc == src && (taste = M.get_taste_message(FALSE))) // Prevent indirect tasting
to_chat(owner, span_vnotice("[M] tastes of [taste]."))
- vore_fx(M)
+ vore_fx(M, TRUE)
+ if(owner.previewing_belly == src)
+ vore_fx(owner, TRUE)
//Stop AI processing in bellies
if(M.ai_holder)
- M.ai_holder.handle_eaten()
-
- owner.handle_belly_update()
-
- // Intended for simple mobs
- if(!owner.client && autotransferlocation && autotransferchance > 0)
- addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/belly, check_autotransfer), thing, autotransferlocation), autotransferwait)
+ M.ai_holder.go_sleep()
+ if(reagents.total_volume >= 5)
+ if(digest_mode == DM_DIGEST && M.digestable)
+ reagents.trans_to(M, reagents.total_volume * 0.1, 1 / max(LAZYLEN(contents), 1), FALSE)
+ to_chat(M, span_vwarning(span_bold("You splash into a pool of [reagent_name]!")))
+ if(!isliving(thing) && count_items_for_sprite) // If this is enabled also update fullness for non-living things
+ owner.handle_belly_update() // This is run whenever a belly's contents are changed.
// Called whenever an atom leaves this belly
/obj/belly/Exited(atom/movable/thing, atom/OldLoc)
. = ..()
- if(isliving(thing) && !isbelly(thing.loc))
+ if(QDELETED(owner))
+ return
+ thing.exit_belly(src) // atom movable proc, does nothing by default. Overridden in children for special behavior.
+ if(isbelly(thing.loc))
+ var/obj/belly/NB = thing.loc
+ if(count_items_for_sprite && !NB.count_items_for_sprite)
+ owner.handle_belly_update()
+ return
+
+ // Remove vorefx from all those indirectly viewing as well
+ var/list/endfx = list()
+ if(isliving(thing))
var/mob/living/L = thing
- L.clear_fullscreen("belly")
- L.clear_fullscreen("belly2")
- L.clear_fullscreen("belly3")
- L.clear_fullscreen("belly4")
- if(L.hud_used)
- if(!L.hud_used.hud_shown)
- L.toggle_hud_vis()
- if((L.stat != DEAD) && L.ai_holder)
- L.ai_holder.go_wake()
- owner.handle_belly_update()
- return
+ endfx.Add(L)
+ endfx.Add(get_belly_surrounding(L.contents))
+ owner.handle_belly_update() // This is run whenever a belly's contents are changed.
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ endfx.Add(get_belly_surrounding(I.contents))
+ if(!isbelly(thing.loc))
+ for(var/mob/living/L in endfx)
+ if(L.surrounding_belly()) continue
+ L.clear_fullscreen("belly")
+ if(L.hud_used)
+ if(!L.hud_used.hud_shown)
+ L.toggle_hud_vis()
+ if((L.stat != DEAD) && L.ai_holder)
+ L.ai_holder.go_wake()
+ L.stop_sound_channel(CHANNEL_PREYLOOP) // This was on release_specific_contents proc, why is it not here on belly exit?
+ // End of indirect vorefx changes
+ if(isitem(thing) && !isbelly(thing.loc)) // Digest stage effects. Don't bother adding overlays to stuff that won't make it back out.
+ if(count_items_for_sprite) // If this is enabled also update fullness for non-living things
+ owner.handle_belly_update() // This is run whenever a belly's contents are changed.
+ var/obj/item/I = thing
+ if(I.gurgled)
+ I.cut_overlay(gurgled_overlays[I.gurgled_color]) //No double-overlay for worn items.
+ I.add_overlay(gurgled_overlays[I.gurgled_color])
+ if(I.d_mult < 1)
+ if(I.d_stage_overlay)
+ I.cut_overlay(I.d_stage_overlay)
+ var/image/temp = new /image(gurgled_overlays[I.gurgled_color ? I.gurgled_color : "green"])
+ temp.filters += filter(type = "alpha", icon = icon(I.icon, I.icon_state))
+ I.d_stage_overlay = temp
+ for(var/count in I.d_mult to 1 step 0.25)
+ I.add_overlay(I.d_stage_overlay, TRUE)
-
-
-/obj/belly/proc/vore_fx(mob/living/L)
+// SEND_SIGNAL(COMSIG_BELLY_UPDATE_VORE_FX) is sometimes used when calling vore_fx() to send belly visuals
+// to certain non-belly atoms. Not called here as vore_fx() is usually only called if a mob is in the belly.
+// Don't forget it if you need to rework vore_fx().
+/obj/belly/proc/vore_fx(mob/living/L, var/update, var/severity = 0)
if(!istype(L))
return
if(!L.client)
return
+ if(L.previewing_belly && L.previewing_belly != src)
+ return
+ if(L.previewing_belly == src && L.vore_selected != src)
+ L.previewing_belly = null
+ return
if(!L.show_vore_fx)
L.clear_fullscreen("belly")
+ L.previewing_belly = null
return
-
+ if(update)
+ L.clear_fullscreen("belly")
if(belly_fullscreen)
if(colorization_enabled)
- var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly/colorized)
- F.icon_state = belly_fullscreen
- F.color = belly_fullscreen_color
- if("[belly_fullscreen]_l1" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F2 = L.overlay_fullscreen("belly2", /obj/screen/fullscreen/belly/colorized/overlay)
- F2.icon_state = "[belly_fullscreen]_l1"
- F2.color = belly_fullscreen_color_secondary
- else
- L.clear_fullscreen("belly2")
- if("[belly_fullscreen]_l2" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F3 = L.overlay_fullscreen("belly3", /obj/screen/fullscreen/belly/colorized/overlay)
- F3.icon_state = "[belly_fullscreen]_l2"
- F3.color = belly_fullscreen_color_trinary
- else
- L.clear_fullscreen("belly3")
- if("[belly_fullscreen]_nc" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F4 = L.overlay_fullscreen("belly4", /obj/screen/fullscreen/belly/colorized/overlay)
- F4.icon_state = "[belly_fullscreen]_nc"
- else
- L.clear_fullscreen("belly4")
+ var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly, severity) // preserving save data
+ var/datum/belly_overlays/lookup_belly_path = text2path("/datum/belly_overlays/[lowertext(belly_fullscreen)]")
+ if(!lookup_belly_path)
+ CRASH("Icon datum was not defined for [belly_fullscreen]")
+ F.icon = initial(lookup_belly_path.belly_icon)
+ F.cut_overlays()
+ var/image/I = image(F.icon, belly_fullscreen) //Would be cool if I could just include color and alpha in the image define so we don't have to copy paste
+ I.color = belly_fullscreen_color
+ I.alpha = belly_fullscreen_alpha
+ F.add_overlay(I)
+ I = image(F.icon, belly_fullscreen+"-2")
+ I.color = belly_fullscreen_color2
+ I.alpha = belly_fullscreen_alpha
+ F.add_overlay(I)
+ I = image(F.icon, belly_fullscreen+"-3")
+ I.color = belly_fullscreen_color3
+ I.alpha = belly_fullscreen_alpha
+ F.add_overlay(I)
+ I = image(F.icon, belly_fullscreen+"-4")
+ I.color = belly_fullscreen_color4
+ I.alpha = belly_fullscreen_alpha
+ F.add_overlay(I)
+ var/extra_mush = 0
+ var/extra_mush_color = mush_color
+ if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0)
+ var/mob/living/carbon/human/H = owner
+ var/datum/reagents/metabolism/ingested = H.ingested
+ if(ingested && ingested.total_volume > 0)
+ if(custom_ingested_color)
+ extra_mush_color = custom_ingested_color
+ else
+ extra_mush_color = ingested.get_color()
+ extra_mush = ingested.total_volume * metabolism_mush_ratio
+ if(!mush_overlay)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = extra_mush_color
+ I.alpha = custom_ingested_alpha
+ I.pixel_y = -450 + ((450 / max(max_ingested, 1)) * min(max_ingested, ingested.total_volume))
+ F.add_overlay(I)
+ if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0))
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = mush_color
+ I.alpha = mush_alpha
+ var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush
+ I.pixel_y = -450 + (450 / max(max_mush, 1) * max(min(max_mush, total_mush_content), 1))
+ if(I.pixel_y < -450 + (450 / 100 * min_mush))
+ I.pixel_y = -450 + (450 / 100 * min_mush)
+ var/stored_y = I.pixel_y
+ F.add_overlay(I)
+ if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = extra_mush_color
+ I.alpha = min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha)
+ I.pixel_y = stored_y
+ F.add_overlay(I)
+ if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume)
+ if(digest_mode == DM_HOLD && item_digest_mode == IM_HOLD)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "calm")
+ else
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "bubbles")
+ if(custom_reagentcolor)
+ I.color = custom_reagentcolor
+ else
+ I.color = reagentcolor
+ if(custom_reagentalpha)
+ I.alpha = custom_reagentalpha
+ else
+ I.alpha = max(150, min(custom_max_volume, 255)) - (255 - belly_fullscreen_alpha)
+ I.pixel_y = -450 + min((450 / custom_max_volume * reagents.total_volume), 450 / 100 * max_liquid_level)
+ F.add_overlay(I)
+ F.update_for_view(L.client.view)
else
- var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly)
- F.icon_state = belly_fullscreen
+ var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly/fixed, severity) //preserving save data
+ F.icon = 'icons/mob/screen_full_vore.dmi'
+ F.cut_overlays()
+ F.add_overlay(image(F.icon, belly_fullscreen))
+ F.add_overlay(image(F.icon, belly_fullscreen+"-2"))
+ F.add_overlay(image(F.icon, belly_fullscreen+"-3"))
+ F.add_overlay(image(F.icon, belly_fullscreen+"-4"))
+ var/image/I
+ var/extra_mush = 0
+ var/extra_mush_color = mush_color
+ if(L.liquidbelly_visuals && ishuman(owner) && metabolism_overlay && metabolism_mush_ratio > 0)
+ var/mob/living/carbon/human/H = owner
+ var/datum/reagents/metabolism/ingested = H.ingested
+ if(ingested && ingested.total_volume > 0)
+ if(custom_ingested_color)
+ extra_mush_color = custom_ingested_color
+ else
+ extra_mush_color = ingested.get_color()
+ extra_mush = ingested.total_volume * metabolism_mush_ratio
+ if(!mush_overlay)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = extra_mush_color
+ I.alpha = custom_ingested_alpha
+ I.pixel_y = -450 + (450 / max(max_ingested, 1) * max(min(max_ingested, ingested.total_volume), 1))
+ F.add_overlay(I)
+ if(show_liquids && L.liquidbelly_visuals && mush_overlay && (owner.nutrition > 0 || max_mush == 0 || min_mush > 0 || (LAZYLEN(contents) * item_mush_val) > 0))
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = mush_color
+ I.alpha = mush_alpha
+ var/total_mush_content = owner.nutrition + LAZYLEN(contents) * item_mush_val + extra_mush
+ I.pixel_y = -450 + (450 / max(max_mush, 1) * max(min(max_mush, total_mush_content), 1))
+ if(I.pixel_y < -450 + (450 / 100 * min_mush))
+ I.pixel_y = -450 + (450 / 100 * min_mush)
+ var/stored_y = I.pixel_y
+ F.add_overlay(I)
+ if(metabolism_overlay && metabolism_mush_ratio > 0 && extra_mush > 0)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "mush")
+ I.color = extra_mush_color
+ I.alpha = min(mush_alpha, (extra_mush / max(total_mush_content, 1)) * mush_alpha)
+ I.pixel_y = stored_y
+ F.add_overlay(I)
+ if(show_liquids && L.liquidbelly_visuals && liquid_overlay && reagents.total_volume)
+ if(digest_mode == DM_HOLD && item_digest_mode == IM_HOLD)
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "calm")
+ else
+ I = image('icons/mob/vore_fullscreens/bubbles.dmi', "bubbles")
+ if(custom_reagentcolor)
+ I.color = custom_reagentcolor
+ else
+ I.color = reagentcolor
+ if(custom_reagentalpha)
+ I.alpha = custom_reagentalpha
+ else
+ I.alpha = max(150, min(custom_max_volume, 255)) - (255 - belly_fullscreen_alpha)
+ I.pixel_y = -450 + min((450 / custom_max_volume * reagents.total_volume), 450 / 100 * max_liquid_level)
+ F.add_overlay(I)
+ F.update_for_view(L.client.view)
else
L.clear_fullscreen("belly")
- L.clear_fullscreen("belly2")
- L.clear_fullscreen("belly3")
- L.clear_fullscreen("belly4")
- if(disable_hud)
+ if(disable_hud && L != owner)
if(L?.hud_used?.hud_shown)
to_chat(L, span_vnotice("((Your pred has disabled huds in their belly. Turn off vore FX and hit F12 to get it back; or relax, and enjoy the serenity.))"))
L.toggle_hud_vis(TRUE)
/obj/belly/proc/vore_preview(mob/living/L)
- if(!istype(L))
+ if(!istype(L) || !L.client)
+ L.previewing_belly = null
return
- if(!L.client)
- return
-
- if(belly_fullscreen)
- if(colorization_enabled)
- var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly/colorized)
- F.icon_state = belly_fullscreen
- F.color = belly_fullscreen_color
- if("[belly_fullscreen]_l1" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F2 = L.overlay_fullscreen("belly2", /obj/screen/fullscreen/belly/colorized/overlay)
- F2.icon_state = "[belly_fullscreen]_l1"
- F2.color = belly_fullscreen_color_secondary
- if("[belly_fullscreen]_l2" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F3 = L.overlay_fullscreen("belly3", /obj/screen/fullscreen/belly/colorized/overlay)
- F3.icon_state = "[belly_fullscreen]_l2"
- F3.color = belly_fullscreen_color_trinary
- if("[belly_fullscreen]_nc" in icon_states('icons/mob/screen_full_colorized_vore_overlays.dmi'))
- var/obj/screen/fullscreen/F4 = L.overlay_fullscreen("belly4", /obj/screen/fullscreen/belly/colorized/overlay)
- F4.icon_state = "[belly_fullscreen]_nc"
- else
- var/obj/screen/fullscreen/F = L.overlay_fullscreen("belly", /obj/screen/fullscreen/belly)
- F.icon_state = belly_fullscreen
- else
- L.clear_fullscreen("belly")
- L.clear_fullscreen("belly2")
- L.clear_fullscreen("belly3")
- L.clear_fullscreen("belly4")
+ L.previewing_belly = src
+ vore_fx(L)
/obj/belly/proc/clear_preview(mob/living/L)
+ L.previewing_belly = null
L.clear_fullscreen("belly")
- L.clear_fullscreen("belly2")
- L.clear_fullscreen("belly3")
- L.clear_fullscreen("belly4")
@@ -446,15 +824,15 @@
//Determines privacy
var/privacy_range = world.view
- var/privacy_volume = 100
+ //var/privacy_volume = 100
switch(eating_privacy_local) //Third case of if("loud") not defined, as it'd just leave privacy_range and volume untouched
if("default")
if(owner.eating_privacy_global)
privacy_range = 1
- privacy_volume = 25
+ //privacy_volume = 25
if("subtle")
privacy_range = 1
- privacy_volume = 25
+ //privacy_volume = 25
//Print notifications/sound if necessary
if(!silent && count)
@@ -465,7 +843,7 @@
else
soundfile = fancy_release_sounds[release_sound]
if(soundfile)
- playsound(src, soundfile, vol = privacy_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ playsound(src, soundfile, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
return count
@@ -529,18 +907,20 @@
//Determines privacy
var/privacy_range = world.view
- var/privacy_volume = 100
+ //var/privacy_volume = 100
switch(eating_privacy_local) //Third case of if("loud") not defined, as it'd just leave privacy_range and volume untouched
if("default")
if(owner.eating_privacy_global)
privacy_range = 1
- privacy_volume = 25
+ //privacy_volume = 25
if("subtle")
privacy_range = 1
- privacy_volume = 25
+ //privacy_volume = 25
//Print notifications/sound if necessary
- if(!silent && !isobserver(M))
+ if(istype(M, /mob/observer))
+ silent = TRUE
+ if(!silent)
owner.visible_message(span_vnotice(span_green(span_bold("[owner] [release_verb] [M] from their [lowertext(name)]!"))),range = privacy_range)
var/soundfile
if(!fancy_vore)
@@ -548,7 +928,7 @@
else
soundfile = fancy_release_sounds[release_sound]
if(soundfile)
- playsound(src, soundfile, vol = privacy_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ playsound(src, soundfile, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
//Should fix your view not following you out of mobs sometimes!
if(ismob(M))
var/mob/ourmob = M
@@ -582,6 +962,23 @@
if(owner.mind)
owner.mind.vore_prey_eaten++
+// new procs for handling digestion damage as a total rather than per-type
+// Returns the current total digestion damage per tick of a belly.
+/obj/belly/proc/get_total_digestion_damage()
+ return (digest_brute + digest_burn + digest_oxy + digest_tox + digest_clone)
+
+// Returns the remaining 'budget' of digestion damage between the current and the maximum.
+/obj/belly/proc/get_unused_digestion_damage()
+ return max(digest_max - get_total_digestion_damage(), 0)
+
+/obj/belly/proc/set_zero_digestion_damage()
+ digest_brute = 0
+ digest_burn = 0
+ digest_oxy = 0
+ digest_tox = 0
+ digest_clone = 0
+ return
+
// Handle the death of a mob via digestion.
// Called from the process_Life() methods of bellies that digest prey.
// Default implementation calls M.death() and removes from internal contents.
@@ -590,10 +987,30 @@
digested_prey_count++
add_attack_logs(owner, M, "Digested in [lowertext(name)]")
+ // Reverts TF on death. This fixes a bug with posibrains or similar, and also makes reforming easier.
+ if(M.tf_mob_holder && M.tf_mob_holder.loc == M)
+ M.tf_mob_holder.ckey = M.ckey
+ M.tf_mob_holder.enabled = TRUE
+ M.tf_mob_holder.loc = M.loc
+ M.tf_mob_holder.forceMove(M.loc)
+ QDEL_LIST_NULL(M.tf_mob_holder.vore_organs)
+ M.tf_mob_holder.vore_organs = list()
+ for(var/obj/belly/B as anything in M.vore_organs)
+ B.loc = M.tf_mob_holder
+ B.forceMove(M.tf_mob_holder)
+ B.owner = M.tf_mob_holder
+ M.tf_mob_holder.vore_organs |= B
+ M.vore_organs -= B
+
+ if(M.tf_mob_holder)
+ M.tf_mob_holder = null
+
// If digested prey is also a pred... anyone inside their bellies gets moved up.
if(is_vore_predator(M))
M.release_vore_contents(include_absorbed = TRUE, silent = TRUE)
+ var/obj/item/mmi/hasMMI // Adjust how MMI's are handled
+
//Drop all items into the belly.
if(CONFIG_GET(flag/items_survive_digestion))
for(var/obj/item/W in M)
@@ -602,6 +1019,7 @@
var/obj/item/mmi/brainbox = MMI.removed()
if(brainbox)
items_preserved += brainbox
+ hasMMI = brainbox // Adjust how MMI's are handled
for(var/slot in slots)
var/obj/item/I = M.get_equipped_item(slot = slot)
if(I)
@@ -619,19 +1037,70 @@
if(ishuman(M))
var/mob/living/carbon/human/Prey = M
Prey.bloodstr.del_reagent(REAGENT_ID_NUMBENZYME)
- Prey.bloodstr.trans_to_holder(Pred.bloodstr, Prey.bloodstr.total_volume, 0.5, TRUE) // Copy=TRUE because we're deleted anyway
- Prey.ingested.trans_to_holder(Pred.bloodstr, Prey.ingested.total_volume, 0.5, TRUE) // Therefore don't bother spending cpu
- Prey.touching.trans_to_holder(Pred.bloodstr, Prey.touching.total_volume, 0.5, TRUE) // On updating the prey's reagents
+ Prey.bloodstr.trans_to_holder(Pred.ingested, Prey.bloodstr.total_volume, 0.5, TRUE) // Copy=TRUE because we're deleted anyway
+ Prey.ingested.trans_to_holder(Pred.ingested, Prey.ingested.total_volume, 0.5, TRUE) // Therefore don't bother spending cpu
+ //Don't need this stuff in our bloodstream.
+ Prey.touching.del_reagent(REAGENT_ID_STOMACID)
+ Prey.touching.del_reagent(REAGENT_ID_DIETSTOMACID)
+ Prey.touching.del_reagent(REAGENT_ID_PACID)
+ Prey.touching.del_reagent(REAGENT_ID_SACID)
+ Prey.touching.del_reagent(REAGENT_ID_CLEANER)
+ Prey.touching.del_reagent(REAGENT_ID_CONCENTRATEDRADIUM)
+ Prey.touching.del_reagent(REAGENT_ID_TRICORDRAZINE)
+ Prey.touching.trans_to_holder(Pred.ingested, Prey.touching.total_volume, 0.5, TRUE) // On updating the prey's reagents
else if(M.reagents)
- M.reagents.trans_to_holder(Pred.bloodstr, M.reagents.total_volume, 0.5, TRUE)
+ //Don't need this stuff in our bloodstream.
+ M.reagents.del_reagent(REAGENT_ID_STOMACID)
+ M.reagents.del_reagent(REAGENT_ID_DIETSTOMACID)
+ M.reagents.del_reagent(REAGENT_ID_PACID)
+ M.reagents.del_reagent(REAGENT_ID_SACID)
+ M.reagents.del_reagent(REAGENT_ID_CLEANER)
+ M.reagents.del_reagent(REAGENT_ID_CONCENTRATEDRADIUM)
+ M.reagents.del_reagent(REAGENT_ID_TRICORDRAZINE)
+ M.reagents.trans_to_holder(Pred.ingested, M.reagents.total_volume, 0.5, TRUE)
+
+ owner.handle_belly_update()
//Incase they have the loop going, let's double check to stop it.
M.stop_sound_channel(CHANNEL_PREYLOOP)
// Delete the digested mob
- var/mob/observer/G = M.ghostize() //Ports CHOMPStation PR#3074 Make sure they're out, so we can copy attack logs and such.
- if(G)
- G.forceMove(src)
- qdel(M)
+ // Changed qdel to a forceMove to allow reforming, and... handled robots special.
+ if(isrobot(M))
+ var/mob/living/silicon/robot/R = M
+ if(R.mmi && R.mind && R.mmi.brainmob)
+ if((R.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE) && owner.soulgem && owner.soulgem.flag_check(SOULGEM_ACTIVE | NIF_SC_CATCHING_OTHERS, TRUE))
+ owner.soulgem.catch_mob(R, R.name)
+ else
+ R.mmi.loc = src
+ items_preserved += R.mmi
+ var/obj/item/robot_module/MB = locate() in R.contents
+ if(MB)
+ R.mmi.brainmob.languages = MB.original_languages
+ else
+ R.mmi.brainmob.languages = R.languages
+ R.mmi.brainmob.remove_language("Robot Talk")
+ hasMMI = R.mmi
+ M.mind.transfer_to(hasMMI.brainmob)
+ R.mmi = null
+ else if(!R.shell) // Shells don't have brainmobs in their MMIs.
+ to_chat(R, span_danger("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug."))
+ if(R.shell) // Let the standard procedure for shells handle this.
+ qdel(R)
+ return
+
+ if(istype(hasMMI))
+ hasMMI.body_backup = M
+ M.enabled = FALSE
+ M.forceMove(hasMMI)
+ else
+ var/mob/observer/G = M.ghostize(FALSE) // Make sure they're out, so we can copy attack logs and such.
+ if(G)
+ G.forceMove(src)
+ G.body_backup = M
+ M.enabled = FALSE
+ M.forceMove(G)
+ else
+ qdel(M)
owner.handle_belly_update()
// Handle a mob being absorbed
@@ -652,6 +1121,11 @@
//Reagent sharing for absorbed with pred - Copy so both pred and prey have these reagents.
Prey.bloodstr.trans_to_holder(Pred.ingested, Prey.bloodstr.total_volume, copy = TRUE)
Prey.ingested.trans_to_holder(Pred.ingested, Prey.ingested.total_volume, copy = TRUE)
+ Prey.touching.del_reagent(REAGENT_ID_STOMACID) //Don't need this stuff in our bloodstream.
+ Prey.touching.del_reagent(REAGENT_ID_DIETSTOMACID) //Don't need this stuff in our bloodstream.
+ Prey.touching.del_reagent(REAGENT_ID_PACID) //Don't need this stuff in our bloodstream.
+ Prey.touching.del_reagent(REAGENT_ID_SACID) //Don't need this stuff in our bloodstream.
+ Prey.touching.del_reagent(REAGENT_ID_CLEANER) //Don't need this stuff in our bloodstream.
Prey.touching.trans_to_holder(Pred.ingested, Prey.touching.total_volume, copy = TRUE)
// TODO - Find a way to make the absorbed prey share the effects with the pred.
// Currently this is infeasible because reagent containers are designed to have a single my_atom, and we get
@@ -719,15 +1193,13 @@
//Digest a single item
//Receives a return value from digest_act that's how much nutrition
//the item should be worth
-/obj/belly/proc/digest_item(obj/item/item)
- var/digested = item.digest_act(src, owner)
- if(!digested)
+/obj/belly/proc/digest_item(obj/item/item, touchable_amount)
+ var/digested = item.digest_act(src, touchable_amount)
+ if(digested == FALSE)
items_preserved |= item
else
- owner.adjust_nutrition((nutrition_percent / 100) * 5 * digested)
- if(isrobot(owner))
- var/mob/living/silicon/robot/R = owner
- R.cell.charge += ((nutrition_percent / 100) * 50 * digested)
+ owner_adjust_nutrition((nutrition_percent / 100) * 5 * digested)
+ digested = TRUE
return digested
//Determine where items should fall out of us into.
@@ -787,24 +1259,29 @@
var/struggle_outer_message = span_valert(belly_format_string(struggle_messages_outside, R))
var/struggle_user_message = span_valert(belly_format_string(struggle_messages_inside, R))
- for(var/mob/M in hearers(4, owner))
- M.show_message(struggle_outer_message, 2) // hearable
+ if(private_struggle)
+ to_chat(owner, struggle_outer_message)
+ else
+ for(var/mob/M in hearers(4, owner))
+ M.show_message(struggle_outer_message, 2) // hearable
var/sound/struggle_snuggle
var/sound/struggle_rustle = sound(get_sfx("rustle"))
- if((vore_sprite_flags & DM_FLAG_VORESPRITE_BELLY) && (owner.vore_capacity_ex[belly_sprite_to_affect] >= 1) /*&& !private_struggle*/ && resist_triggers_animation && affects_vore_sprites)
+ if((vore_sprite_flags & DM_FLAG_VORESPRITE_BELLY) && (owner.vore_capacity_ex[belly_sprite_to_affect] >= 1) && !private_struggle && resist_triggers_animation && affects_vore_sprites)
owner.vs_animate(belly_sprite_to_affect)
- if(is_wet)
- if(!fancy_vore)
- struggle_snuggle = sound(get_sfx("classic_struggle_sounds"))
+ if(!private_struggle)
+ if(is_wet)
+ if(!fancy_vore)
+ struggle_snuggle = sound(get_sfx("classic_struggle_sounds"))
+ else
+ struggle_snuggle = sound(get_sfx("fancy_prey_struggle"))
+ playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
else
- struggle_snuggle = sound(get_sfx("fancy_prey_struggle"))
- playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
- else
- playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
-
+ playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ if(prob(belchchance))//Unsure if this should go in escapable or not, leaving it here for now.
+ owner.emote("belch")
if(escapable) //If the stomach has escapable enabled.
if(prob(escapechance)) //Let's have it check to see if the prey escapes first.
to_chat(R, escape_attempt_prey_message)
@@ -818,8 +1295,9 @@
release_specific_contents(C)
to_chat(R, escape_item_prey_message)
to_chat(owner, escape_item_owner_message)
- for(var/mob/M in hearers(4, owner))
- M.show_message(escape_item_outside_message, 2)
+ if(!private_struggle)
+ for(var/mob/M in hearers(4, owner))
+ M.show_message(escape_item_outside_message, 2)
return
if(escapable && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled?
var/escape_owner_message = span_vwarning(belly_format_string(escape_messages_owner, R))
@@ -829,8 +1307,9 @@
release_specific_contents(R)
to_chat(R, escape_prey_message)
to_chat(owner, escape_owner_message)
- for(var/mob/M in hearers(4, owner))
- M.show_message(escape_outside_message, 2)
+ if(!private_struggle)
+ for(var/mob/M in hearers(4, owner))
+ M.show_message(escape_outside_message, 2)
return
else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail.
return
@@ -926,20 +1405,24 @@
var/struggle_outer_message = span_valert(belly_format_string(absorbed_struggle_messages_outside, R, use_absorbed_count = TRUE))
var/struggle_user_message = span_valert(belly_format_string(absorbed_struggle_messages_inside, R, use_absorbed_count = TRUE))
- for(var/mob/M in hearers(4, owner))
- M.show_message(struggle_outer_message, 2) // hearable
+ if(private_struggle)
+ to_chat(owner, struggle_outer_message)
+ else
+ for(var/mob/M in hearers(4, owner))
+ M.show_message(struggle_outer_message, 2) // hearable
var/sound/struggle_snuggle
var/sound/struggle_rustle = sound(get_sfx("rustle"))
- if(is_wet)
- if(!fancy_vore)
- struggle_snuggle = sound(get_sfx("classic_struggle_sounds"))
+ if(!private_struggle)
+ if(is_wet)
+ if(!fancy_vore)
+ struggle_snuggle = sound(get_sfx("classic_struggle_sounds"))
+ else
+ struggle_snuggle = sound(get_sfx("fancy_prey_struggle"))
+ playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
else
- struggle_snuggle = sound(get_sfx("fancy_prey_struggle"))
- playsound(src, struggle_snuggle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
- else
- playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ playsound(src, struggle_rustle, vary = 1, vol = 75, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/digestion_noises, volume_channel = VOLUME_CHANNEL_VORE)
//absorb resists
if(escapable || owner.stat) //If the stomach has escapable enabled or the owner is dead/unconscious
@@ -958,8 +1441,9 @@
release_specific_contents(R)
to_chat(R, escape_absorbed_prey_message)
to_chat(owner, escape_absorbed_owner_message)
- for(var/mob/M in hearers(4, owner))
- M.show_message(escape_absorbed_outside_message, 2)
+ if(!private_struggle)
+ for(var/mob/M in hearers(4, owner))
+ M.show_message(escape_absorbed_outside_message, 2)
return
else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail.
return
@@ -989,6 +1473,7 @@
/obj/belly/proc/transfer_contents(atom/movable/content, obj/belly/target, silent = 0)
if(!(content in src) || !istype(target))
return
+ content.belly_cycles = 0
content.forceMove(target)
if(ismob(content) && !isobserver(content))
var/mob/ourmob = content
@@ -1007,20 +1492,157 @@
owner.handle_belly_update()
//Autotransfer callback
-/obj/belly/proc/check_autotransfer(var/prey, var/autotransferlocation)
- if(autotransferlocation && (autotransferchance > 0) && (prey in contents))
- if(prob(autotransferchance))
- var/obj/belly/dest_belly
- for(var/obj/belly/B in owner.vore_organs)
- if(B.name == autotransferlocation)
- dest_belly = B
- break
- if(dest_belly)
- transfer_contents(prey, dest_belly)
+/obj/belly/proc/check_autotransfer(var/atom/movable/prey)
+ if(!(prey in contents) || !prey.autotransferable) return
+ var/dest_belly_name
+ if(autotransferlocation_secondary && prob(autotransferchance_secondary))
+ if(ismob(prey) && autotransfer_filter(prey, autotransfer_secondary_whitelist, autotransfer_secondary_blacklist))
+ dest_belly_name = pick(autotransferextralocation_secondary + autotransferlocation_secondary)
+ if(isitem(prey) && autotransfer_filter(prey, autotransfer_secondary_whitelist_items, autotransfer_secondary_blacklist_items))
+ dest_belly_name = pick(autotransferextralocation_secondary + autotransferlocation_secondary)
+ if(autotransferlocation && prob(autotransferchance))
+ if(ismob(prey) && autotransfer_filter(prey, autotransfer_whitelist, autotransfer_blacklist))
+ dest_belly_name = pick(autotransferextralocation + autotransferlocation)
+ if(isitem(prey) && autotransfer_filter(prey, autotransfer_whitelist_items, autotransfer_blacklist_items))
+ dest_belly_name = pick(autotransferextralocation + autotransferlocation)
+ if(!dest_belly_name) // Didn't transfer, so wait before retrying
+ prey.belly_cycles = 0
+ return
+ var/obj/belly/dest_belly
+ for(var/obj/belly/B in owner.vore_organs)
+ if(B.name == dest_belly_name)
+ dest_belly = B
+ break
+ if(!dest_belly) return
+ if(ismob(prey))
+ var/autotransfer_owner_message
+ var/autotransfer_prey_message
+ if(dest_belly_name == autotransferlocation)
+ autotransfer_owner_message = span_vwarning(belly_format_string(primary_autotransfer_messages_owner, prey, dest = dest_belly_name))
+ autotransfer_prey_message = span_vwarning(belly_format_string(primary_autotransfer_messages_prey, prey, dest = dest_belly_name))
else
- // Didn't transfer, so wait before retrying
- // I feel like there's a way to make this timer looping using the normal looping thing, but pass in the ID and cancel it if we aren't looping again
- addtimer(CALLBACK(src, PROC_REF(check_autotransfer), prey, autotransferlocation), autotransferwait)
+ autotransfer_owner_message = span_vwarning(belly_format_string(secondary_autotransfer_messages_owner, prey, dest = dest_belly_name))
+ autotransfer_prey_message = span_vwarning(belly_format_string(secondary_autotransfer_messages_prey, prey, dest = dest_belly_name))
+
+ to_chat(prey, autotransfer_prey_message)
+ if(entrance_logs)
+ to_chat(owner, autotransfer_owner_message)
+
+ transfer_contents(prey, dest_belly)
+ return TRUE
+
+//Autotransfer filter
+/obj/belly/proc/autotransfer_filter(var/atom/movable/prey, var/whitelist, var/blacklist)
+ if(ismob(prey))
+ if(blacklist & autotransfer_flags_list["Absorbed"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.absorbed) return FALSE
+ if(blacklist != 2) // Default is 2 for Absorbed, if it's not 2, check everything else
+ if(blacklist & autotransfer_flags_list["Creatures"])
+ if(isliving(prey)) return FALSE
+ if(blacklist & autotransfer_flags_list["Carbon"])
+ if(iscarbon(prey)) return FALSE
+ if(blacklist & autotransfer_flags_list["Silicon"])
+ if(issilicon(prey)) return FALSE
+ if(blacklist & autotransfer_flags_list["Mobs"])
+ if(istype(prey, /mob/living/simple_mob)) return FALSE
+ if(blacklist & autotransfer_flags_list["Animals"])
+ if(istype(prey, /mob/living/simple_mob/animal)) return FALSE
+ if(blacklist & autotransfer_flags_list["Mice"])
+ if(ismouse(prey)) return FALSE
+ if(blacklist & autotransfer_flags_list["Dead"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.stat == DEAD) return FALSE
+ if(blacklist & autotransfer_flags_list["Digestable Creatures"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.digestable) return FALSE
+ if(blacklist & autotransfer_flags_list["Absorbable Creatures"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.absorbable) return FALSE
+ if(blacklist & autotransfer_flags_list["Full Health"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if((L.getOxyLoss() + L.getToxLoss() + L.getFireLoss() + L.getBruteLoss() + L.getCloneLoss()) == 0) return FALSE
+ if(whitelist == 0) return TRUE
+ if(whitelist & autotransfer_flags_list["Creatures"])
+ if(isliving(prey)) return TRUE
+ if(whitelist & autotransfer_flags_list["Absorbed"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.absorbed) return TRUE
+ if(whitelist & autotransfer_flags_list["Carbon"])
+ if(iscarbon(prey)) return TRUE
+ if(whitelist & autotransfer_flags_list["Silicon"])
+ if(issilicon(prey)) return TRUE
+ if(whitelist & autotransfer_flags_list["Mobs"])
+ if(istype(prey, /mob/living/simple_mob)) return TRUE
+ if(whitelist & autotransfer_flags_list["Animals"])
+ if(istype(prey, /mob/living/simple_mob/animal)) return TRUE
+ if(whitelist & autotransfer_flags_list["Mice"])
+ if(ismouse(prey)) return TRUE
+ if(whitelist & autotransfer_flags_list["Dead"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.stat == DEAD) return TRUE
+ if(whitelist & autotransfer_flags_list["Digestable Creatures"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.digestable) return TRUE
+ if(whitelist & autotransfer_flags_list["Absorbable Creatures"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if(L.absorbable) return TRUE
+ if(whitelist & autotransfer_flags_list["Full Health"])
+ if(isliving(prey))
+ var/mob/living/L = prey
+ if((L.getOxyLoss() + L.getToxLoss() + L.getFireLoss() + L.getBruteLoss() + L.getCloneLoss()) == 0) return TRUE
+ else
+ if(blacklist & autotransfer_flags_list_items["Items"])
+ if(isitem(prey)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Trash"])
+ if(istype(prey, /obj/item/trash)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Eggs"])
+ if(istype(prey, /obj/item/storage/vore_egg)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Remains"])
+ if(istype(prey, /obj/item/digestion_remains)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Indigestible Items"])
+ if(prey in items_preserved) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Recyclable Items"])
+ if(isitem(prey))
+ var/obj/item/I = prey
+ if(I.matter) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Ores"])
+ if(istype(prey, /obj/item/ore)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Clothes and Bags"])
+ if(istype(prey, /obj/item/clothing) || istype(prey, /obj/item/storage)) return FALSE
+ if(blacklist & autotransfer_flags_list_items["Food"])
+ if(istype(prey, /obj/item/reagent_containers/food)) return FALSE
+ if(whitelist == 0) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Items"])
+ if(isitem(prey)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Trash"])
+ if(istype(prey, /obj/item/trash)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Eggs"])
+ if(istype(prey, /obj/item/storage/vore_egg)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Remains"])
+ if(istype(prey, /obj/item/digestion_remains)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Indigestible Items"])
+ if(prey in items_preserved) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Recyclable Items"])
+ if(isitem(prey))
+ var/obj/item/I = prey
+ if(I.matter) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Ores"])
+ if(istype(prey, /obj/item/ore)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Clothes and Bags"])
+ if(istype(prey, /obj/item/clothing) || istype(prey, /obj/item/storage)) return TRUE
+ if(whitelist & autotransfer_flags_list_items["Food"])
+ if(istype(prey, /obj/item/reagent_containers/food)) return TRUE
+ return FALSE
// Belly copies and then returns the copy
// Needs to be updated for any var changes
@@ -1067,11 +1689,79 @@
dupe.fancy_vore = fancy_vore
dupe.is_wet = is_wet
dupe.wet_loop = wet_loop
+ dupe.reagent_mode_flags = reagent_mode_flags
+ dupe.belly_fullscreen_color = belly_fullscreen_color
+ dupe.belly_fullscreen_color2 = belly_fullscreen_color2
+ dupe.belly_fullscreen_color3 = belly_fullscreen_color3
+ dupe.belly_fullscreen_color4 = belly_fullscreen_color4
+ dupe.belly_fullscreen_alpha = belly_fullscreen_alpha
+ dupe.show_liquids = show_liquids
+ dupe.reagentbellymode = reagentbellymode
+ dupe.vorefootsteps_sounds = vorefootsteps_sounds
+ 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.reagentid = reagentid
+ dupe.reagentcolor = reagentcolor
+ dupe.liquid_overlay = liquid_overlay
+ dupe.max_liquid_level = max_liquid_level
+ dupe.reagent_touches = reagent_touches
+ dupe.mush_overlay = mush_overlay
+ dupe.mush_color = mush_color
+ dupe.mush_alpha = mush_alpha
+ dupe.max_mush = max_mush
+ dupe.min_mush = min_mush
+ dupe.item_mush_val = item_mush_val
+ dupe.custom_reagentcolor = custom_reagentcolor
+ dupe.custom_reagentalpha = custom_reagentalpha
+ dupe.metabolism_overlay = metabolism_overlay
+ dupe.metabolism_mush_ratio = metabolism_mush_ratio
+ dupe.max_ingested = max_ingested
+ dupe.custom_ingested_color = custom_ingested_color
+ dupe.custom_ingested_alpha = custom_ingested_alpha
+ dupe.gen_cost = gen_cost
+ dupe.gen_amount = gen_amount
+ dupe.gen_time = gen_time
+ dupe.gen_time_display = gen_time_display
+ dupe.reagent_transfer_verb = reagent_transfer_verb
+ dupe.custom_max_volume = custom_max_volume
+ dupe.vorespawn_blacklist = vorespawn_blacklist
+ dupe.vorespawn_whitelist = vorespawn_whitelist
+ dupe.vorespawn_absorbed = vorespawn_absorbed
+ dupe.absorbed_multiplier = absorbed_multiplier
+ dupe.count_liquid_for_sprite = count_liquid_for_sprite
+ dupe.liquid_multiplier = liquid_multiplier
+ dupe.undergarment_chosen = undergarment_chosen
+ dupe.undergarment_if_none = undergarment_if_none
+ dupe.undergarment_color = undergarment_color
+ dupe.autotransferchance = autotransferchance
+ dupe.autotransferwait = autotransferwait
+ dupe.autotransferlocation = autotransferlocation
+ dupe.autotransfer_enabled = autotransfer_enabled
+ dupe.autotransferchance_secondary = autotransferchance_secondary
+ dupe.autotransferlocation_secondary = autotransferlocation_secondary
+ dupe.autotransfer_min_amount = autotransfer_min_amount
+ dupe.autotransfer_max_amount = autotransfer_max_amount
+ dupe.slow_digestion = slow_digestion
+ dupe.slow_brutal = slow_brutal
+ dupe.sound_volume = sound_volume
+ dupe.egg_name = egg_name
+ dupe.egg_size = egg_size
+ dupe.recycling = recycling
+ dupe.storing_nutrition = storing_nutrition
+ dupe.is_feedable = is_feedable
+ dupe.entrance_logs = entrance_logs
+ dupe.noise_freq = noise_freq
+ dupe.item_digest_logs = item_digest_logs
+ dupe.show_fullness_messages = show_fullness_messages
+ dupe.belchchance = belchchance
+ dupe.digest_max = digest_max
dupe.belly_fullscreen = belly_fullscreen
dupe.disable_hud = disable_hud
- dupe.belly_fullscreen_color = belly_fullscreen_color
- dupe.belly_fullscreen_color_secondary = belly_fullscreen_color_secondary
- dupe.belly_fullscreen_color_trinary = belly_fullscreen_color_trinary
dupe.colorization_enabled = colorization_enabled
dupe.egg_type = egg_type
dupe.emote_time = emote_time
@@ -1277,6 +1967,36 @@
for(var/I in examine_messages)
dupe.examine_messages += I
+ //generated_reagents - strings
+ dupe.generated_reagents.Cut()
+ for(var/I in generated_reagents)
+ dupe.generated_reagents += I
+
+ //fullness1_messages - strings
+ dupe.fullness1_messages.Cut()
+ for(var/I in fullness1_messages)
+ dupe.fullness1_messages += I
+
+ //fullness2_messages - strings
+ dupe.fullness2_messages.Cut()
+ for(var/I in fullness2_messages)
+ dupe.fullness2_messages += I
+
+ //fullness3_messages - strings
+ dupe.fullness3_messages.Cut()
+ for(var/I in fullness3_messages)
+ dupe.fullness3_messages += I
+
+ //fullness4_messages - strings
+ dupe.fullness4_messages.Cut()
+ for(var/I in fullness4_messages)
+ dupe.fullness4_messages += I
+
+ //generated_reagents - strings
+ dupe.fullness5_messages.Cut()
+ for(var/I in fullness5_messages)
+ dupe.fullness5_messages += I
+
//examine_messages_absorbed - strings
dupe.examine_messages_absorbed.Cut()
for(var/I in examine_messages_absorbed)
@@ -1311,8 +2031,8 @@
fullness_to_add *= M.health / M.getMaxHealth()
if(fullness_to_add > 0)
belly_fullness += fullness_to_add
- /*if(count_liquid_for_sprite)
- belly_fullness += (reagents.total_volume / 100) * liquid_multiplier*/// Not yet implemented here
+ if(count_liquid_for_sprite)
+ belly_fullness += (reagents.total_volume / 100) * liquid_multiplier
if(count_items_for_sprite)
for(var/obj/item/I in src)
var/fullness_to_add = 0
@@ -1332,3 +2052,112 @@
belly_fullness += fullness_to_add * item_multiplier
belly_fullness *= size_factor_for_sprite
return belly_fullness
+
+/obj/item/debris_pack/digested
+ name = "digested material"
+ desc = "Some thoroughly digested mass of ... something. Might be useful for recycling."
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "matdust"
+ color = "#664330"
+ w_class = ITEMSIZE_SMALL
+
+/obj/belly/proc/recycle(var/obj/item/O)
+ if(!recycling || (!LAZYLEN(O.matter) && !istype(O, /obj/item/ore)))
+ return FALSE
+ if(istype(O, /obj/item/ore))
+ var/obj/item/ore/ore = O
+ for(var/obj/item/ore_chunk/C in contents)
+ if(istype(C))
+ C.stored_ore[ore.material]++
+ return TRUE
+ var/obj/item/ore_chunk/newchunk = new /obj/item/ore_chunk(src)
+ newchunk.stored_ore[ore.material]++
+ return TRUE
+ else
+ var/list/modified_mats = list()
+ var/trash = 1
+ if(istype(O,/obj/item/trash))
+ trash = 5
+ if(istype(O,/obj/item/stack))
+ var/obj/item/stack/S = O
+ trash = S.amount
+ for(var/mat in O.matter)
+ modified_mats[mat] = O.matter[mat] * trash
+ for(var/obj/item/debris_pack/digested/D in contents)
+ if(istype(D))
+ for(var/mat in modified_mats)
+ D.matter[mat] += modified_mats[mat]
+ if(O.w_class > D.w_class)
+ D.w_class = O.w_class
+ if(O.possessed_voice && O.possessed_voice.len)
+ for(var/mob/living/voice/V in O.possessed_voice)
+ D.inhabit_item(V, null, V.tf_mob_holder)
+ qdel(V)
+ O.possessed_voice = list()
+ return TRUE
+ var/obj/item/debris_pack/digested/D = new /obj/item/debris_pack/digested(src, modified_mats)
+ if(O.possessed_voice && O.possessed_voice.len)
+ for(var/mob/living/voice/V in O.possessed_voice)
+ D.inhabit_item(V, null, V.tf_mob_holder)
+ qdel(V)
+ O.possessed_voice = list()
+ return TRUE
+
+/obj/belly/proc/owner_adjust_nutrition(var/amount = 0)
+ if(storing_nutrition && amount > 0)
+ for(var/obj/item/reagent_containers/food/rawnutrition/R in contents)
+ if(istype(R))
+ R.stored_nutrition += amount
+ return
+ var/obj/item/reagent_containers/food/rawnutrition/NR = new /obj/item/reagent_containers/food/rawnutrition(src)
+ NR.stored_nutrition += amount
+ return
+ else
+ owner.adjust_nutrition(amount)
+
+/obj/item/reagent_containers/food/rawnutrition
+ name = "raw nutrition"
+ desc = "A nutritious pile of converted mass ready for consumption."
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "matdust"
+ color = "#664330"
+ w_class = ITEMSIZE_SMALL
+ var/stored_nutrition = 0
+
+/obj/item/reagent_containers/food/rawnutrition/standard_feed_mob(var/mob/user, var/mob/target)
+ if(isliving(target))
+ var/mob/living/L = target
+ L.nutrition += stored_nutrition
+ stored_nutrition = 0
+ qdel(src)
+ return
+ .=..()
+
+// Updates the belly_surrounding list variable. Called in bellymodes_vr.dm
+/obj/belly/proc/update_belly_surrounding()
+ if(!contents.len && !LAZYLEN(owner.soulgem?.brainmobs))
+ belly_surrounding = list()
+ return
+ belly_surrounding = get_belly_surrounding(contents)
+ if(owner.soulgem?.linked_belly == src)
+ belly_surrounding += owner.soulgem.brainmobs
+
+// Recursive proc that returns all living mobs directly and indirectly inside a belly
+// This can also be called more generically to get all living mobs not in bellies within any contents list
+/obj/belly/proc/get_belly_surrounding(var/list/C)
+ var/list/surrounding = list()
+ for(var/thing in C)
+ if(istype(thing,/mob/living))
+ var/mob/living/L = thing
+ surrounding.Add(L)
+ surrounding.Add(get_belly_surrounding(L.contents))
+ if(istype(thing,/obj/item))
+ var/obj/item/I = thing
+ surrounding.Add(get_belly_surrounding(I.contents))
+ return surrounding
+
+/obj/belly/proc/effective_emote_hearers()
+ . = list(loc)
+ for(var/atom/movable/AM as anything in contents)
+ //if(AM.atom_flags & ATOM_HEAR)
+ . += AM
diff --git a/code/modules/vore/eating/bellymodes_datum_vr.dm b/code/modules/vore/eating/bellymodes_datum_vr.dm
index ba26215ca37..d3cab78929d 100644
--- a/code/modules/vore/eating/bellymodes_datum_vr.dm
+++ b/code/modules/vore/eating/bellymodes_datum_vr.dm
@@ -29,17 +29,35 @@ GLOBAL_LIST_INIT(digest_modes, list())
//Person just died in guts!
if(L.stat == DEAD)
- if(L.check_sound_preference(/datum/preference/toggle/digestion_noises))
+ if(!L.digestion_in_progress)
+ if(L.check_sound_preference(/datum/preference/toggle/digestion_noises))
+ if(!B.fancy_vore)
+ SEND_SOUND(L, sound(get_sfx("classic_death_sounds")))
+ else
+ SEND_SOUND(L, sound(get_sfx("fancy_death_prey")))
+ B.handle_digestion_death(L)
if(!B.fancy_vore)
- SEND_SOUND(L, sound(get_sfx("classic_death_sounds")))
- else
- SEND_SOUND(L, sound(get_sfx("fancy_death_prey")))
- B.handle_digestion_death(L)
+ return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("classic_death_sounds")))
+ return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("fancy_death_pred")))
+ else
+ B.handle_digestion_death(L)
if(!L)
B.owner.handle_belly_update()
- if(!B.fancy_vore)
- return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("classic_death_sounds")))
- return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("fancy_death_pred")))
+ return list("to_update" = TRUE)
+ if(!L)
+ return
+
+ //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
+ B.owner.adjust_nutrition(-paratox)
+ L.adjust_nutrition(paratox)
+ L.adjustBruteLoss(-paratox*2) //Should automaticaly clamp to 0
+ L.adjustFireLoss(-paratox*2) //Should automaticaly clamp to 0
+ if(B.health_impacts_size) //Health probably changed so...
+ B.owner.handle_belly_update() //This is run whenever a belly's contents are changed.
+ return
// Deal digestion damage (and feed the pred)
var/old_health = L.health
@@ -53,13 +71,17 @@ GLOBAL_LIST_INIT(digest_modes, list())
L.adjustOxyLoss(B.digest_oxy)
L.adjustToxLoss(B.digest_tox)
L.adjustCloneLoss(B.digest_clone)
+ // Send a message when a prey-thing enters hard crit.
+ if(iscarbon(L) && old_health > 0 && L.health <= 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_clone = L.getCloneLoss() - old_clone
var/damage_gain = (actual_brute + actual_burn + actual_oxy/2 + actual_tox + 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
var/difference = B.owner.size_multiplier / L.size_multiplier
@@ -67,14 +89,15 @@ GLOBAL_LIST_INIT(digest_modes, list())
B.owner.handle_belly_update()
consider_healthbar(L, old_health, B.owner)
-
- if(isrobot(B.owner))
- var/mob/living/silicon/robot/R = B.owner
- R.cell.charge += 25 * damage_gain
- if(offset) // If any different than default weight, multiply the % of offset.
- B.owner.adjust_nutrition(offset*(4.5 * (damage_gain) / difference)*L.get_digestion_nutrition_modifier()*B.owner.get_digestion_efficiency_modifier()) //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(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
+ 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()
+ else
+ B.owner_adjust_nutrition(offset * (4.5 * damage_gain / difference) * L.get_digestion_nutrition_modifier() * B.owner.get_digestion_efficiency_modifier()) //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
- B.owner.adjust_nutrition((4.5 * (damage_gain) / difference)*L.get_digestion_nutrition_modifier()*B.owner.get_digestion_efficiency_modifier())
+ B.owner_adjust_nutrition(offset * (4.5 * damage_gain / difference) * L.get_digestion_nutrition_modifier() * B.owner.get_digestion_efficiency_modifier())
if(L.stat != oldstat)
return list("to_update" = TRUE)
@@ -90,6 +113,8 @@ 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
+ 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)
else
@@ -155,7 +180,7 @@ GLOBAL_LIST_INIT(digest_modes, list())
/datum/digest_mode/heal/process_mob(obj/belly/B, mob/living/L)
var/oldstat = L.stat
- if(L.stat == DEAD)
+ 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 && H.isSynthetic())
@@ -200,9 +225,23 @@ GLOBAL_LIST_INIT(digest_modes, list())
B.put_in_egg(H, 1)*/
/datum/digest_mode/egg/handle_atoms(obj/belly/B, list/touchable_atoms)
+ if(B.egg_cycles < 10)
+ B.egg_cycles ++
+ return
+ B.egg_cycles = 0
var/list/egg_contents = list()
for(var/E in touchable_atoms)
+ if(istype(E, /mob/observer))
+ continue
if(istype(E, /obj/item/storage/vore_egg)) // Don't egg other eggs.
+ var/obj/item/storage/vore_egg/EG = E
+ if(EG.egg_name != B.egg_name)
+ if(!B.egg_name)
+ EG.egg_name = null
+ EG.name = initial(EG.name)
+ else
+ EG.egg_name = B.egg_name
+ EG.name = B.egg_name
continue
if(isliving(E))
var/mob/living/L = E
@@ -216,44 +255,58 @@ GLOBAL_LIST_INIT(digest_modes, list())
if(B.egg_type in tf_vore_egg_types)
B.egg_path = tf_vore_egg_types[B.egg_type]
B.ownegg = new B.egg_path(B)
+ if(B.ownegg && B.egg_name)
+ B.ownegg.egg_name = B.egg_name
+ B.ownegg.name = B.egg_name
+ var/scale_clamp = 1
for(var/atom/movable/C in egg_contents)
if(isitem(C) && egg_contents.len == 1) //Only egging one item
var/obj/item/I = C
B.ownegg.w_class = I.w_class
B.ownegg.max_storage_space = B.ownegg.w_class
I.forceMove(B.ownegg)
- B.ownegg.icon_scale_x = 0.2 * B.ownegg.w_class
- B.ownegg.icon_scale_y = 0.2 * B.ownegg.w_class
+ if(B.egg_size)
+ B.ownegg.icon_scale_x = B.egg_size
+ B.ownegg.icon_scale_y = B.egg_size
+ else
+ B.ownegg.icon_scale_x = 0.2 * B.ownegg.w_class
+ B.ownegg.icon_scale_y = 0.2 * B.ownegg.w_class
B.ownegg.update_transform()
egg_contents -= I
B.ownegg = null
return list("to_update" = TRUE)
- if(isliving(C))
- var/mob/living/M = C
- var/mob_holder_type = M.holder_type || /obj/item/holder
- B.ownegg.w_class = M.size_multiplier * 4 //Egg size and weight scaled to match occupant.
- var/obj/item/holder/H = new mob_holder_type(B.ownegg, M)
- B.ownegg.max_storage_space = H.w_class
- B.ownegg.icon_scale_x = 0.25 * B.ownegg.w_class
- B.ownegg.icon_scale_y = 0.25 * B.ownegg.w_class
- B.ownegg.update_transform()
- egg_contents -= M
- if(B.ownegg.w_class > 4)
- B.ownegg.slowdown = B.ownegg.w_class - 4
- B.ownegg = null
- return list("to_update" = TRUE)
- C.forceMove(B.ownegg)
if(isitem(C))
var/obj/item/I = C
B.ownegg.w_class += I.w_class //Let's assume a regular outfit can reach total w_class of 16.
+ I.forceMove(B.ownegg)
+ if(isliving(C))
+ var/mob/living/M = C
+ var/mob_holder_type = M.holder_type || /obj/item/holder
+ B.ownegg.w_class += M.size_multiplier * 4 //Egg size and weight scaled to match occupant.
+ if(M.size_multiplier > scale_clamp)
+ scale_clamp = M.size_multiplier
+ var/obj/item/holder/H = new mob_holder_type(B.ownegg, M)
+ B.ownegg.max_storage_space = H.w_class
+ //B.ownegg.icon_scale_x = 0.25 * B.ownegg.w_class
+ //B.ownegg.icon_scale_y = 0.25 * B.ownegg.w_class
+ //B.ownegg.update_transform()
+ egg_contents -= M
+ //if(B.ownegg.w_class > 4)
+ // B.ownegg.slowdown = B.ownegg.w_class - 4
+ //B.ownegg = null
+ //return list("to_update" = TRUE)
B.ownegg.calibrate_size()
B.ownegg.orient2hud()
B.ownegg.w_class = clamp(B.ownegg.w_class * 0.25, 1, 8) //A total w_class of 16 will result in a backpack sized egg.
- B.ownegg.icon_scale_x = clamp(0.25 * B.ownegg.w_class, 0.25, 1)
- B.ownegg.icon_scale_y = clamp(0.25 * B.ownegg.w_class, 0.25, 1)
+ if(B.egg_size)
+ B.ownegg.icon_scale_x = B.egg_size
+ B.ownegg.icon_scale_y = B.egg_size
+ else
+ B.ownegg.icon_scale_x = clamp(0.25 * B.ownegg.w_class, 0.25, scale_clamp)
+ B.ownegg.icon_scale_y = clamp(0.25 * B.ownegg.w_class, 0.25, scale_clamp)
B.ownegg.update_transform()
if(B.ownegg.w_class > 4)
- B.ownegg.slowdown = B.ownegg.w_class - 4
+ B.ownegg.slowdown = 4
B.ownegg = null
return list("to_update" = TRUE)
return
@@ -262,6 +315,7 @@ GLOBAL_LIST_INIT(digest_modes, list())
id = DM_SELECT
noise_chance = 50
+
/datum/digest_mode/selective/process_mob(obj/belly/B, mob/living/L)
var/datum/digest_mode/tempmode = GLOB.digest_modes[DM_HOLD] // Default to Hold in case of big oof fallback
//if not absorbed, see if they're food
diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm
index 491b8fdb625..f758e603257 100644
--- a/code/modules/vore/eating/bellymodes_vr.dm
+++ b/code/modules/vore/eating/bellymodes_vr.dm
@@ -1,6 +1,7 @@
// Process the predator's effects upon the contents of its belly (i.e digestion/transformation etc)
/obj/belly/process(wait) //Passed by controller
recent_sound = FALSE
+ cycle_sloshed = FALSE
if(loc != owner)
if(istype(owner))
@@ -9,16 +10,50 @@
qdel(src)
return
+ HandleBellyReagents() // reagent belly stuff, here to jam it into subsystems and avoid too much cpu usage
+ update_belly_surrounding() // Updates belly_surrounding list for indirect vore usage
// VERY early exit
if(!contents.len)
+ if(owner.previewing_belly == src)
+ HandleBellyReagentEffects()
return
+ // Autotransfer count moved here.
+ if(autotransfer_enabled)
+ var/list/autotransferables = list()
+ for(var/atom/movable/M in contents)
+ if(!M || !M.autotransferable) continue
+ // If the prey can't pass the filter of at least one transfer location, skip it
+ if(ismob(M) && !(autotransfer_filter(M, autotransfer_secondary_whitelist, autotransfer_secondary_blacklist) || autotransfer_filter(M, autotransfer_whitelist, autotransfer_blacklist))) continue
+ if(isitem(M) && !(autotransfer_filter(M, autotransfer_secondary_whitelist_items, autotransfer_secondary_blacklist_items) || autotransfer_filter(M, autotransfer_whitelist_items, autotransfer_blacklist_items))) continue
+ M.belly_cycles++
+ if(M.belly_cycles < autotransferwait / 60) continue
+ autotransferables += M
+ if(LAZYLEN(autotransferables) >= autotransfer_min_amount)
+ var/tally = 0
+ for(var/atom/movable/M in autotransferables)
+ if(check_autotransfer(M))
+ tally++
+ if(autotransfer_max_amount > 0 && tally >= autotransfer_max_amount) break
+
var/play_sound //Potential sound to play at the end to avoid code duplication.
var/to_update = FALSE //Did anything update worthy happen?
+ SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_PREY_LOOP) // signals listening atoms to update prey_loop. May be cancelled by early exit otherwise.
/////////////////////////// Exit Early ////////////////////////////
var/list/touchable_atoms = contents - items_preserved
- if(!length(touchable_atoms))
+ for(var/mob/observer/G in touchable_atoms) // don't bother trying to process ghosts.
+ touchable_atoms -= G
+ var/datum/digest_mode/DM = GLOB.digest_modes["[digest_mode]"]
+ if(!DM)
+ log_debug("Digest mode [digest_mode] didn't exist in the digest_modes list!!")
+ return FALSE
+ if(digest_mode == DM_EGG)
+ prey_loop() //Apparently on Egg mode the sound loop never played before? Just slapping this here to fix that
+ if(DM.handle_atoms(src, contents))
+ updateVRPanels()
+ return
+ if(!length(touchable_atoms) && !belly_surrounding.len) // Needed to not exit early for indirect vorefx
return
/////////////////////////// Sound Selections ///////////////////////////
@@ -34,10 +69,6 @@
///////////////////// Early Non-Mode Handling /////////////////////
- var/datum/digest_mode/DM = GLOB.digest_modes["[digest_mode]"]
- if(!DM)
- log_debug("Digest mode [digest_mode] didn't exist in the digest_modes list!!")
- return FALSE
if(DM.handle_atoms(src, touchable_atoms))
updateVRPanels()
return
@@ -56,6 +87,9 @@
if(!digestion_noise_chance)
digestion_noise_chance = DM.noise_chance
+ touchable_atoms -= items_preserved
+ HandleBellyReagentEffects(touchable_atoms)
+
/////////////////////////// Make any noise ///////////////////////////
if(digestion_noise_chance && prob(digestion_noise_chance))
for(var/mob/M in contents)
@@ -63,7 +97,7 @@
SEND_SOUND(M, prey_digest)
play_sound = pred_digest
- if(!LAZYLEN(touchable_mobs))
+ if(!LAZYLEN(belly_surrounding)) //Changed to belly_surrounding from touchable_mobs so indirect vore viewers get this too
if(to_update)
updateVRPanels()
if(play_sound)
@@ -72,9 +106,9 @@
continue
if(isturf(M.loc) || (M.loc != src)) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
if(fancy_vore)
- M.playsound_local(get_turf(owner), play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
+ M.playsound_local(get_turf(owner), play_sound, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq)
else
- M.playsound_local(get_turf(owner), play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
+ M.playsound_local(get_turf(owner), play_sound, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq)
//these are all external sound triggers now, so it's ok.
return
@@ -99,13 +133,17 @@
continue
if(isturf(M.loc) || (M.loc != src)) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
if(fancy_vore)
- M.playsound_local(get_turf(owner), play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
+ M.playsound_local(get_turf(owner), play_sound, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq)
else
- M.playsound_local(get_turf(owner), play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
+ M.playsound_local(get_turf(owner), play_sound, vol = sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq)
//these are all external sound triggers now, so it's ok.
if(emote_active)
- var/list/EL = emote_lists[digest_mode]
+ // emote_lists can be = ""
+ var/list/EL
+ if(islist(emote_lists))
+ EL = emote_lists[digest_mode]
+
if((LAZYLEN(EL) || LAZYLEN(emote_lists[DM_HOLD_ABSORBED]) || (digest_mode == DM_DIGEST && LAZYLEN(emote_lists[DM_HOLD])) || (digest_mode == DM_SELECT && (LAZYLEN(emote_lists[DM_HOLD])||LAZYLEN(emote_lists[DM_DIGEST])||LAZYLEN(emote_lists[DM_ABSORB])) )) && next_emote <= world.time)
next_emote = world.time + (emote_time SECONDS)
for(var/mob/living/M in contents)
@@ -134,30 +172,14 @@
var/list/touchable_mobs = list()
for(var/A in touchable_atoms)
- //Handle stray items
- if(isitem(A) && !did_an_item)
- did_an_item = handle_digesting_item(A)
- if(did_an_item)
- to_update = TRUE
-
- //Less often than with normal digestion
- if((item_digest_mode == IM_DIGEST_FOOD || item_digest_mode == IM_DIGEST) && prob(25))
- // This is a little weird, but the point of it is that we don't want to repeat code
- // but we also want the prob(25) chance to run for -every- item we look at, not just once
- // More gurgles the better~
- digestion_noise_chance = 25
-
//Handle eaten mobs
- else if(isliving(A))
+ if(isliving(A))
var/mob/living/L = A
touchable_mobs += L
if(L.absorbed && !issilicon(L))
L.Weaken(5)
- // Fullscreen overlays
- vore_fx(L)
-
//Handle 'human'
if(ishuman(L))
var/mob/living/carbon/human/H = L
@@ -170,23 +192,26 @@
//Thickbelly flag
if((mode_flags & DM_FLAG_THICKBELLY) && !H.muffled)
H.muffled = TRUE
+ //Fix muffled sometimes being sticky.
+ else if(!(mode_flags & DM_FLAG_THICKBELLY) && H.muffled)
+ H.muffled = FALSE
//Force psay
if((mode_flags & DM_FLAG_FORCEPSAY) && !H.forced_psay && H.absorbed)
H.forced_psay = TRUE
+ //Fix forcepsay sometimes being sticky.
+ else if(!(mode_flags & DM_FLAG_FORCEPSAY) && H.forced_psay)
+ H.forced_psay = FALSE
//Worn items flag
if(mode_flags & DM_FLAG_AFFECTWORN)
for(var/slot in slots)
var/obj/item/I = H.get_equipped_item(slot = slot)
if(I && I.canremove)
- if(handle_digesting_item(I))
- digestion_noise_chance = 25
- to_update = TRUE
- break
+ touchable_atoms |= I
//Stripping flag
- if(mode_flags & DM_FLAG_STRIPPING)
+ if((mode_flags & DM_FLAG_STRIPPING) && H.strip_pref) //Stripping pref check
for(var/slot in slots)
var/obj/item/I = H.get_equipped_item(slot = slot)
if(I && H.unEquip(I, force = FALSE))
@@ -195,6 +220,25 @@
to_update = TRUE
break // Digest off one by one, not all at once
+ for(var/A in touchable_atoms) //List updated for worn items.
+ //Handle stray items
+ if(isitem(A))
+ if(item_digest_mode == IM_DIGEST_PARALLEL)
+ var/touchable_amount = touchable_atoms.len
+ did_an_item = handle_digesting_item(A, touchable_amount)
+ else if(!did_an_item)
+ did_an_item = handle_digesting_item(A, 1)
+ if(did_an_item)
+ to_update = TRUE
+
+ //Less often than with normal digestion
+ if((item_digest_mode == IM_DIGEST_FOOD || item_digest_mode == IM_DIGEST || item_digest_mode == IM_DIGEST_PARALLEL) && prob(25))
+ // This is a little weird, but the point of it is that we don't want to repeat code
+ // but we also want the prob(25) chance to run for -every- item we look at, not just once
+ // More gurgles the better~
+ digestion_noise_chance = 25
+ continue
+
//get rid of things like blood drops and gibs that end up in there
else if(istype(A, /obj/effect/decal/cleanable))
qdel(A)
@@ -202,7 +246,7 @@
return list("to_update" = to_update, "touchable_mobs" = touchable_mobs, "digestion_noise_chance" = digestion_noise_chance)
/obj/belly/proc/prey_loop()
- for(var/mob/living/M in contents)
+ for(var/mob/living/M in belly_surrounding) //contents changed to belly_surrounding to loop sound for indirect viewers too
//We don't bother executing any other code if the prey doesn't want to hear the noises.
if(!M.check_sound_preference(/datum/preference/toggle/digestion_noises))
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
@@ -211,13 +255,13 @@
// We don't want the sounds to overlap, but we do want them to steadily replay.
// We also don't want the sounds to play if the pred hasn't marked this belly as fleshy, or doesn't
// have the right sounds to play.
- if(isbelly(M.loc) && is_wet && wet_loop && (world.time > M.next_preyloop))
+ if(is_wet && wet_loop && (world.time > M.next_preyloop)) //Removed isbelly(M.loc) as some viewers might be indirectly in the belly
M.stop_sound_channel(CHANNEL_PREYLOOP)
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
- M.playsound_local(get_turf(src), preyloop, 80, 0, channel = CHANNEL_PREYLOOP)
+ M.playsound_local(get_turf(src), preyloop, 80, 0, channel = CHANNEL_PREYLOOP, frequency = noise_freq)
M.next_preyloop = (world.time + (52 SECONDS))
-/obj/belly/proc/handle_digesting_item(obj/item/I)
+/obj/belly/proc/handle_digesting_item(obj/item/I, touchable_amount)
var/did_an_item = FALSE
// We always contaminate IDs.
if(contaminates || istype(I, /obj/item/card/id))
@@ -232,14 +276,43 @@
if(istype(R) && R.robotic >= ORGAN_ROBOT)
items_preserved |= I
else
- did_an_item = digest_item(I)
+ did_an_item = digest_item(I, touchable_amount)
else
items_preserved |= I
- if(IM_DIGEST)
- did_an_item = digest_item(I)
+ if(IM_DIGEST,IM_DIGEST_PARALLEL)
+ did_an_item = digest_item(I, touchable_amount)
return did_an_item
-/obj/belly/proc/handle_digestion_death(mob/living/M)
+/obj/belly/proc/handle_digestion_death(mob/living/M, instant = FALSE)
+ if(!instant && slow_digestion) // Gradual corpse digestion
+ if(!M.digestion_in_progress)
+ M.digestion_in_progress = TRUE
+ if(M.health > -36 || (ishuman(M) && M.health > -136))
+ to_chat(M, span_vnotice("(Your predator has enabled gradual body digestion. Stick around for a second round of churning to reach the true finisher.)"))
+ if(M.health < M.maxHealth * -1) //Siplemobs etc
+ if(ishuman(M))
+ if(M.health < (M.maxHealth * -1) -100) //Spacemans can go much deeper. Jank but maxHealth*-2 doesn't work with flat standard -100hp death threshold.
+ if(slow_brutal)
+ var/mob/living/carbon/human/P = M
+ var/vitals_only = TRUE
+ for(var/obj/item/organ/external/E in P.organs)
+ if(!E.vital)
+ vitals_only = FALSE
+ if(!LAZYLEN(E.children))
+ for(var/obj/item/implant/I as anything in E.implants)
+ qdel(I)
+ E.droplimb(TRUE, DROPLIMB_EDGE)
+ qdel(E)
+ break
+ continue
+ if(vitals_only)
+ M.digestion_in_progress = FALSE
+ else
+ M.digestion_in_progress = FALSE
+ else
+ M.digestion_in_progress = FALSE
+ if(M.digestion_in_progress)
+ return
var/digest_alert_owner = span_vnotice(belly_format_string(digest_messages_owner, M))
var/digest_alert_prey = span_vnotice(belly_format_string(digest_messages_prey, M))
var/compensation = M.maxHealth / 5 //Dead body bonus.
@@ -253,6 +326,9 @@
if(M.ckey)
GLOB.prey_digested_roundstat++
+ owner.churn_count++
+ owner.handle_special_unlocks()
+
var/personal_nutrition_modifier = M.get_digestion_nutrition_modifier()
var/pred_digestion_efficiency = owner.get_digestion_efficiency_modifier()
@@ -266,13 +342,11 @@
if((mode_flags & DM_FLAG_LEAVEREMAINS) && M.digest_leave_remains)
handle_remains_leaving(M)
digestion_death(M)
- if(!ishuman(owner))
- owner.update_icons()
- if(isrobot(owner))
- var/mob/living/silicon/robot/R = owner
- R.cell.charge += (nutrition_percent / 100) * compensation * 25 * personal_nutrition_modifier
+ if(show_liquids && reagent_mode_flags & DM_FLAG_REAGENTSDIGEST && reagents.total_volume < reagents.maximum_volume) // digestion producing reagents
+ owner_adjust_nutrition((nutrition_percent / 100) * compensation * 3 * personal_nutrition_modifier)
+ GenerateBellyReagents_digested()
else
- owner.adjust_nutrition((nutrition_percent / 100) * compensation * 4.5 * personal_nutrition_modifier * pred_digestion_efficiency)
+ owner_adjust_nutrition((nutrition_percent / 100) * compensation * 4.5 * personal_nutrition_modifier * pred_digestion_efficiency)
/obj/belly/proc/steal_nutrition(mob/living/L)
if(L.nutrition <= 110)
@@ -292,10 +366,14 @@
if(L.nutrition >= 100)
var/oldnutrition = (L.nutrition * 0.05)
L.nutrition = (L.nutrition * 0.95)
- owner.adjust_nutrition(oldnutrition)
+ 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
+ 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
+ owner_adjust_nutrition(oldnutrition)
/obj/belly/proc/updateVRPanels()
- for(var/mob/living/M in contents)
+ for(var/mob/living/M in belly_surrounding) //Changed to belly_surrounding from contents so updates happen for indirect viewers too
if(M.client)
M.updateVRPanel()
if(owner.client)
diff --git a/code/modules/vore/eating/contaminate_vr.dm b/code/modules/vore/eating/contaminate_vr.dm
index 39cc0c60949..27b0f8e6f2f 100644
--- a/code/modules/vore/eating/contaminate_vr.dm
+++ b/code/modules/vore/eating/contaminate_vr.dm
@@ -18,6 +18,7 @@ var/list/gurgled_overlays = list(
/obj/item
var/gurgled = FALSE
+ var/oldname
var/cleanname
var/cleandesc
var/gurgled_color
@@ -32,7 +33,8 @@ var/list/gurgled_overlays = list(
if(!gurgled)
gurgled = TRUE
gurgled_color = contamination_color
- add_overlay(gurgled_overlays[gurgled_color])
+ if(!isbelly(src.loc)) //Moved non-worn overlay stuff to belly_obj_vr.dm Exited proc. No need to add overlays to things that won't make it out.
+ add_overlay(gurgled_overlays[gurgled_color])
var/list/pickfrom = contamination_flavors[contamination_flavor]
var/gurgleflavor = pick(pickfrom)
cleanname = src.name
diff --git a/code/modules/vore/eating/digest_act_vr.dm b/code/modules/vore/eating/digest_act_vr.dm
index 65980b0cebf..bd0912ed497 100644
--- a/code/modules/vore/eating/digest_act_vr.dm
+++ b/code/modules/vore/eating/digest_act_vr.dm
@@ -3,7 +3,9 @@
//return non-negative integer: Amount of nutrition/charge gained (scaled to nutrition, other end can multiply for charge scale).
// Ye default implementation.
-/obj/item/proc/digest_act(atom/movable/item_storage = null)
+/obj/item/proc/digest_act(atom/movable/item_storage = null, touchable_amount, splashing = 0)
+ if(!digestable)
+ return FALSE
if(istype(item_storage, /obj/item/dogborg/sleeper))
if(istype(src, /obj/item/pda))
var/obj/item/pda/P = src
@@ -11,6 +13,9 @@
P.id = null
for(var/mob/living/voice/V in possessed_voice) // Delete voices.
+ V.ghostize(0) // Prevent Reenter Corpse sending observers to the shadow realm
+ V.stat = DEAD // Helps with autosleeving
+ if(V.mind) V.mind.vore_death = 1 // Digested item TFs get vore_death timer
qdel(V)
for(var/mob/living/M in contents)//Drop mobs from objects(shoes) before deletion
M.forceMove(item_storage)
@@ -30,23 +35,55 @@
if(digest_stage == null)
digest_stage = w_class
+ var/obj/belly/B
if(isbelly(item_storage))
- var/obj/belly/B = item_storage
- g_damage = 0.25 * (B.digest_brute + B.digest_burn)
-
+ B = item_storage
+ if(!touchable_amount)
+ touchable_amount = 1
+ if(splashing > 0)
+ g_damage = 0.25 * splashing
+ else if(istype(B))
+ g_damage = 0.25 * (B.digest_brute + B.digest_burn) / touchable_amount
+ if(g_damage <= 0)
+ return FALSE
+ if(g_damage > digest_stage)
+ g_damage = digest_stage
+ digest_stage = 0 //Don't bother with further math for 1 hit kills.
if(digest_stage > 0)
if(g_damage > digest_stage)
g_damage = digest_stage
digest_stage -= g_damage
+ d_mult = round(1 / w_class * digest_stage, 0.25)
+ if(d_mult < d_mult_old)
+ d_mult_old = d_mult
+ var/d_stage_name
+ switch(d_mult)
+ if(0.75)
+ d_stage_name = "blemished"
+ if(0.5)
+ d_stage_name = "disfigured"
+ if(0.25)
+ d_stage_name = "deteriorating"
+ if(0)
+ d_stage_name = "ruined"
+ if(d_stage_name)
+ if(!oldname)
+ oldname = cleanname ? cleanname : name
+ cleanname = "[d_stage_name] [oldname]"
+ decontaminate()
+ if(istype(B))
+ gurgled_color = B.contamination_color //Apply the correct color setting so uncontaminable things can still have the right overlay.
+ gurgle_contaminate(B, B.contamination_flavor, B.contamination_color)
if(digest_stage <= 0)
if(istype(src, /obj/item/pda))
var/obj/item/pda/P = src
if(P.id)
P.id = null
- for(var/mob/living/voice/V in possessed_voice) // Delete voices.
- qdel(V)
for(var/mob/living/M in contents)//Drop mobs from objects(shoes) before deletion
- M.forceMove(item_storage)
+ if(item_storage)
+ M.forceMove(item_storage)
+ else
+ M.forceMove(src.loc)
for(var/obj/item/O in contents)
if(istype(O,/obj/item/storage/internal)) //Dump contents from dummy pockets.
for(var/obj/item/SO in O)
@@ -55,7 +92,36 @@
qdel(O)
else if(item_storage)
O.forceMove(item_storage)
- if(istype(src,/obj/item/stack))
+ else
+ O.forceMove(src.loc)
+ GLOB.items_digested_roundstat++
+ var/g_sound_volume = 100
+ var/noise_freq = 42500
+ if(istype(B))
+ g_sound_volume = B.sound_volume
+ noise_freq = B.noise_freq
+ var/soundfile
+ if(w_class >= 4)
+ soundfile = pick('sound/vore/shortgurgles/gurgle_L1.ogg', 'sound/vore/shortgurgles/gurgle_L2.ogg', 'sound/vore/shortgurgles/gurgle_L3.ogg')
+ else if(w_class >= 3)
+ soundfile = pick('sound/vore/shortgurgles/gurgle_M1.ogg', 'sound/vore/shortgurgles/gurgle_M2.ogg', 'sound/vore/shortgurgles/gurgle_M3.ogg')
+ else
+ soundfile = pick('sound/vore/shortgurgles/gurgle_S1.ogg', 'sound/vore/shortgurgles/gurgle_S2.ogg', 'sound/vore/shortgurgles/gurgle_S3.ogg')
+ playsound(src, soundfile, vol = g_sound_volume, vary = 1, falloff = VORE_SOUND_FALLOFF, frequency = noise_freq, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE)
+ //Allow those turned into items to become the recycled item
+ var/recycled = B?.recycle(src)
+ if(!recycled)
+ for(var/mob/living/voice/V in possessed_voice) // Delete voices.
+ V.ghostize(0) //Prevent Reenter Corpse sending observers to the shadow realm
+ V.stat = DEAD //Helps with autosleeving
+ if(V.mind) V.mind.vore_death = 1 //Digested item TFs get vore_death timer
+ qdel(V) //Destroy the voice.
+ if(istype(B) && recycled)
+ g_damage = w_class / 2
+ if(B.item_digest_logs)
+ to_chat(B.owner,span_notice("[src] was digested inside your [lowertext(B.name)]."))
+ qdel(src)
+ else if(istype(src,/obj/item/stack))
var/obj/item/stack/S = src
if(S.get_amount() <= 1)
qdel(src)
@@ -63,7 +129,21 @@
S.use(1)
digest_stage = w_class
else
- GLOB.items_digested_roundstat++
+ if(istype(src, /obj/item/reagent_containers/food))
+ if(ishuman(B.owner) && reagents)
+ var/mob/living/carbon/human/H = B.owner
+ reagents.trans_to_holder(H.ingested, (reagents.total_volume), B.nutrition_percent / 100, 0)
+ else if(isliving(B.owner))
+ B.owner.nutrition += 15 * w_class * B.nutrition_percent / 100
+ if(istype(src,/obj/item/reagent_containers/food/snacks))
+ var/obj/item/reagent_containers/food/snacks/goodmeal = src //What a typecast
+ //Drop the leftover garbage when the food melts
+ if(goodmeal.package_trash)
+ new goodmeal.package_trash(src)
+ if(goodmeal.trash)
+ new goodmeal.trash(src)
+ if(B.item_digest_logs)
+ to_chat(B.owner,span_notice("[src] was digested inside your [lowertext(B.name)]."))
qdel(src)
if(g_damage > w_class)
return w_class
@@ -106,19 +186,6 @@
update_icon()
return FALSE
-/obj/item/reagent_containers/food/digest_act(atom/movable/item_storage = null)
- if(isbelly(item_storage))
- var/obj/belly/B = item_storage
- if(ishuman(B.owner))
- var/mob/living/carbon/human/H = B.owner
- reagents.trans_to_holder(H.ingested, (reagents.total_volume * 0.5), 1, 0)
- else if(isrobot(B.owner))
- var/mob/living/silicon/robot/R = B.owner
- R.cell.charge += 150
- qdel(src)
- return w_class
- . = ..()
-
/obj/item/holder/digest_act(atom/movable/item_storage = null)
for(var/mob/living/M in contents)
if(item_storage)
@@ -140,6 +207,32 @@
. = ..()
+/obj/item/debris_pack/digested/digest_act(atom/movable/item_storage = null)
+ if(isbelly(item_storage))
+ var/obj/belly/B = item_storage
+ if(istype(B) && B.recycling)
+ return FALSE
+ . = ..()
+
+/obj/item/ore_chunk/digest_act(atom/movable/item_storage = null)
+ if(isbelly(item_storage))
+ var/obj/belly/B = item_storage
+ if(istype(B) && B.recycling)
+ return FALSE
+ . = ..()
+
+/obj/item/reagent_containers/food/rawnutrition/digest_act(atom/movable/item_storage = null)
+ if(isbelly(item_storage))
+ var/obj/belly/B = item_storage
+ if(istype(B) && B.storing_nutrition)
+ return FALSE
+ else if(isliving(B.owner))
+ B.owner.nutrition += stored_nutrition * (B.nutrition_percent / 100)
+ stored_nutrition = 0
+ qdel(src)
+ return w_class
+ . = ..()
+
/////////////
// Some more complicated stuff
/////////////
@@ -147,10 +240,11 @@
//Replace this with a VORE setting so all types of posibrains can/can't be digested on a whim
return FALSE
-/obj/item/organ/internal/nano/digest_act(atom/movable/item_storage = null)
- //Make proteans recoverable too
- return FALSE
+//moved prot organ digest to their appropriate file
// Gradual damage measurement
/obj/item
var/digest_stage = null
+ var/d_mult_old = 1 //digest stage descriptions
+ var/d_mult = 1 //digest stage descriptions
+ var/d_stage_overlay //digest stage effects
diff --git a/code/modules/vore/eating/exportpanel_vr.dm b/code/modules/vore/eating/exportpanel_vr.dm
index 718e3c9e057..1959f78e572 100644
--- a/code/modules/vore/eating/exportpanel_vr.dm
+++ b/code/modules/vore/eating/exportpanel_vr.dm
@@ -154,7 +154,6 @@
for(var/msg in B.secondary_transfer_messages_prey)
belly_data["secondary_transfer_messages_prey"] += msg
- /* Not yet implemented on virgo
belly_data["primary_autotransfer_messages_owner"] = list()
for(var/msg in B.primary_autotransfer_messages_owner)
belly_data["primary_autotransfer_messages_owner"] += msg
@@ -170,7 +169,6 @@
belly_data["secondary_autotransfer_messages_prey"] = list()
for(var/msg in B.secondary_autotransfer_messages_prey)
belly_data["secondary_autotransfer_messages_prey"] += msg
- */
belly_data["digest_chance_messages_owner"] = list()
for(var/msg in B.digest_chance_messages_owner)
@@ -280,7 +278,7 @@
belly_data["digest_clone"] = B.digest_clone
belly_data["can_taste"] = B.can_taste
- // belly_data["is_feedable"] = B.is_feedable // Not yet implemented on virgo
+ belly_data["is_feedable"] = B.is_feedable
belly_data["contaminates"] = B.contaminates
belly_data["contamination_flavor"] = B.contamination_flavor
belly_data["contamination_color"] = B.contamination_color
@@ -291,25 +289,19 @@
belly_data["emote_active"] = B.emote_active
belly_data["emote_time"] = B.emote_time
belly_data["shrink_grow_size"] = B.shrink_grow_size
- /* Not yet implemented on virgo
belly_data["vorespawn_blacklist"] = B.vorespawn_blacklist
belly_data["vorespawn_whitelist"] = B.vorespawn_whitelist
belly_data["vorespawn_absorbed"] = B.vorespawn_absorbed
- */
belly_data["egg_type"] = B.egg_type
- /* Not yet implemented on virgo
belly_data["egg_name"] = B.egg_name
belly_data["egg_size"] = B.egg_size
- */
belly_data["selective_preference"] = B.selective_preference
- /* Not yet implemented on virgo
belly_data["recycling"] = B.recycling
belly_data["storing_nutrition"] = B.storing_nutrition
belly_data["entrance_logs"] = B.entrance_logs
belly_data["item_digest_logs"] = B.item_digest_logs
belly_data["eating_privacy_local"] = B.eating_privacy_local
belly_data["private_struggle"] = B.private_struggle
- */
// Sounds
belly_data["is_wet"] = B.is_wet
@@ -317,10 +309,8 @@
belly_data["fancy_vore"] = B.fancy_vore
belly_data["vore_sound"] = B.vore_sound
belly_data["release_sound"] = B.release_sound
- /* Not yet implemented on virgo
belly_data["sound_volume"] = B.sound_volume
belly_data["noise_freq"] = B.noise_freq
- */
// Visuals
belly_data["affects_vore_sprites"] = B.affects_vore_sprites
@@ -331,8 +321,8 @@
belly_data["vore_sprite_flags"] = sprite_flags
belly_data["count_absorbed_prey_for_sprite"] = B.count_absorbed_prey_for_sprite
belly_data["absorbed_multiplier"] = B.absorbed_multiplier
- // belly_data["count_liquid_for_sprite"] = B.count_liquid_for_sprite // Not yet implemented on virgo
- // belly_data["liquid_multiplier"] = B.liquid_multiplier // Not yet implemented on virgo
+ belly_data["count_liquid_for_sprite"] = B.count_liquid_for_sprite
+ belly_data["liquid_multiplier"] = B.liquid_multiplier
belly_data["count_items_for_sprite"] = B.count_items_for_sprite
belly_data["item_multiplier"] = B.item_multiplier
belly_data["health_impacts_size"] = B.health_impacts_size
@@ -348,18 +338,16 @@
//belly_data["tail_extra_overlay2"] = B.tail_extra_overlay2
// Visuals (Belly Fullscreens Preview and Coloring)
- /* Not yet implemented on virgo
belly_data["belly_fullscreen_color"] = B.belly_fullscreen_color
belly_data["belly_fullscreen_color2"] = B.belly_fullscreen_color2
belly_data["belly_fullscreen_color3"] = B.belly_fullscreen_color3
belly_data["belly_fullscreen_color4"] = B.belly_fullscreen_color4
belly_data["belly_fullscreen_alpha"] = B.belly_fullscreen_alpha
belly_data["colorization_enabled"] = B.colorization_enabled
- */
// Visuals (Vore FX)
belly_data["disable_hud"] = B.disable_hud
- // belly_data["belly_fullscreen"] = B.belly_fullscreen // Not yet implemented on virgo
+ belly_data["belly_fullscreen"] = B.belly_fullscreen
// Interactions
belly_data["escapable"] = B.escapable
@@ -368,7 +356,7 @@
belly_data["escapechance_absorbed"] = B.escapechance_absorbed
belly_data["escapetime"] = B.escapetime/10
- // belly_data["belchchance"] = B.belchchance // Not yet implemented on virgo
+ belly_data["belchchance"] = B.belchchance
belly_data["transferchance"] = B.transferchance
belly_data["transferlocation"] = B.transferlocation
@@ -380,7 +368,6 @@
belly_data["digestchance"] = B.digestchance
// Interactions (Auto-Transfer)
- /* Not yet implemented on virgo
belly_data["autotransferchance"] = B.autotransferchance
belly_data["autotransferwait"] = B.autotransferwait/10
belly_data["autotransferlocation"] = B.autotransferlocation
@@ -463,12 +450,10 @@
if(B.reagent_mode_flags & B.reagent_mode_flag_list[flag_name])
reagent_flags.Add(flag_name)
belly_data["reagent_mode_flag_list"] = reagent_flags
- */
data["bellies"] += list(belly_data)
// Liquid Messages
- /* Not yet implemented on virgo
belly_data["show_fullness_messages"] = B.show_fullness_messages
belly_data["liquid_fullness1_messages"] = B.liquid_fullness1_messages
belly_data["liquid_fullness2_messages"] = B.liquid_fullness2_messages
@@ -495,6 +480,5 @@
belly_data["fullness5_messages"] = list()
for(var/msg in B.fullness5_messages)
belly_data["fullness5_messages"] += msg
- */
return data
diff --git a/code/modules/vore/eating/inbelly_spawn.dm b/code/modules/vore/eating/inbelly_spawn.dm
index 74d3f75f6e8..1971d4ad9ca 100644
--- a/code/modules/vore/eating/inbelly_spawn.dm
+++ b/code/modules/vore/eating/inbelly_spawn.dm
@@ -27,7 +27,7 @@ Please do not abuse this ability.
continue
if(ishuman(pred))
var/mob/living/carbon/human/H = pred
- if(!H.allow_inbelly_spawning)
+ if(!H.latejoin_vore)
continue
eligible_targets += H
continue
@@ -35,7 +35,7 @@ Please do not abuse this ability.
var/mob/living/silicon/S = pred
if(isAI(S))
continue // Sorry, AI buddies. Your vore works too differently.
- if(!S.allow_inbelly_spawning)
+ if(!S.latejoin_vore)
continue
eligible_targets += S
continue
@@ -43,7 +43,7 @@ Please do not abuse this ability.
var/mob/living/simple_mob/SM = pred
if(!SM.vore_active) // No vore, no bellies, no inbelly spawning
continue
- if(!SM.allow_inbelly_spawning)
+ if(!SM.latejoin_vore)
continue
eligible_targets += SM
continue
diff --git a/code/modules/vore/eating/leave_remains_vr.dm b/code/modules/vore/eating/leave_remains_vr.dm
index 626804165de..5d39e212cdb 100644
--- a/code/modules/vore/eating/leave_remains_vr.dm
+++ b/code/modules/vore/eating/leave_remains_vr.dm
@@ -24,6 +24,22 @@
skull_type = /obj/item/digestion_remains/skull/teshari
/datum/species/vox
skull_type = /obj/item/digestion_remains/skull/vox
+/datum/species/monkey
+ skull_type = /obj/item/digestion_remains/skull
+/datum/species/monkey/tajaran
+ skull_type = /obj/item/digestion_remains/skull/tajaran
+/datum/species/monkey/unathi
+ skull_type = /obj/item/digestion_remains/skull/unathi
+/datum/species/monkey/skrell
+ skull_type = /obj/item/digestion_remains/skull/skrell
+/datum/species/monkey/shark
+ skull_type = /obj/item/digestion_remains/skull/akula
+/datum/species/monkey/sparra
+ skull_type = /obj/item/digestion_remains/skull/rapala
+/datum/species/monkey/vulpkanin
+ skull_type = /obj/item/digestion_remains/skull/vulpkanin
+/datum/species/monkey/sergal
+ skull_type = /obj/item/digestion_remains/skull/sergal
/obj/belly/proc/handle_remains_leaving(var/mob/living/M)
if(!ishuman(M) && !isrobot(M)) //Are we even humanoid or a borg?
@@ -73,18 +89,18 @@
return // TODO: add synth skulls and remove this.
var/skull_amount = 1
if(H.species.skull_type)
- new H.species.skull_type(src, owner)
+ new H.species.skull_type(src, owner, H)
skull_amount--
if(skull_amount && H.species.selects_bodytype)
// We still haven't found correct skull...
if(H.species.base_species == SPECIES_HUMAN)
- new /obj/item/digestion_remains/skull/unknown(src,owner)
+ new /obj/item/digestion_remains/skull/unknown(src, owner, H)
else
- new /obj/item/digestion_remains/skull/unknown/anthro(src,owner)
+ new /obj/item/digestion_remains/skull/unknown/anthro(src, owner, H)
else if(skull_amount)
// Something entirely different...
- new /obj/item/digestion_remains/skull/unknown(src,owner)
+ new /obj/item/digestion_remains/skull/unknown(src, owner, H)
/obj/item/digestion_remains
@@ -108,11 +124,15 @@
drop_sound = 'sound/items/drop/device.ogg' //not organic bones, so they get different sounds
pickup_sound = 'sound/items/pickup/device.ogg'
-/obj/item/digestion_remains/Initialize(mapload, var/mob/living/pred)
+/obj/item/digestion_remains/Initialize(mapload, var/mob/living/pred, var/mob/living/prey)
. = ..()
if(!mapload)
pred_ckey = pred?.ckey
pred_name = pred?.name
+ if(prey && isliving(prey) && prey.size_multiplier != 1)
+ icon_scale_x = prey.size_multiplier
+ icon_scale_y = prey.size_multiplier
+ update_transform()
/obj/item/digestion_remains/attack_self(var/mob/user)
if(user.a_intent == I_HURT)
diff --git a/code/modules/vore/eating/living_bellies.dm b/code/modules/vore/eating/living_bellies.dm
index b02c991b5ac..e3595c03fa0 100644
--- a/code/modules/vore/eating/living_bellies.dm
+++ b/code/modules/vore/eating/living_bellies.dm
@@ -1,12 +1,7 @@
-/mob/proc/update_fullness(var/returning = FALSE)
- if(!returning)
- if(updating_fullness)
- return
- updating_fullness = TRUE
- spawn(2)
- updating_fullness = FALSE
- src.update_fullness(TRUE)
+/mob/proc/update_fullness()
+ if(updating_fullness)
return
+ updating_fullness = TRUE
var/list/new_fullness = list()
vore_fullness = 0
for(var/belly_class in vore_icon_bellies)
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index d0dd4795782..c96366e70ee 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -17,8 +17,6 @@
var/absorbing_prey = 0 // Determines if the person is using the succubus drain or not. See station_special_abilities_vr.
var/drain_finalized = 0 // Determines if the succubus drain will be KO'd/absorbed. Can be toggled on at any time.
var/fuzzy = 0 // Preference toggle for sharp/fuzzy icon.
- var/voice_freq = 0 // Preference for character voice frequency
- var/list/voice_sounds_list = list() // The sound list containing our voice sounds!
var/next_preyloop // For Fancy sound internal loop
var/stuffing_feeder = FALSE // Can feed foods to others whole, like trash eater can eat them on their own.
var/adminbus_trash = FALSE // For abusing trash eater for event shenanigans.
@@ -26,6 +24,7 @@
var/vis_height = 32 // Sprite height used for resize features.
var/appendage_color = "#e03997" //Default pink. Used for the 'long_vore' trait.
var/appendage_alt_setting = FALSE // Dictates if 'long_vore' user pulls prey to them or not. 1 = user thrown towards target.
+ var/digestion_in_progress = FALSE // Gradual corpse gurgles
var/regen_sounds = list(
'sound/effects/mob_effects/xenochimera/regen_1.ogg',
'sound/effects/mob_effects/xenochimera/regen_2.ogg',
@@ -39,10 +38,22 @@
var/trait_injection_amount = 5 //RSEdit: How much you're injecting with traits.
var/trait_injection_verb = "bites" //RSEdit: Which fluffy manner you're doing the injecting.
+ var/mute_entry = FALSE //Toggleable vorgan entry logs.
+ var/parasitic = FALSE //Digestion immunity and nutrition leeching variable
+ var/liquidbelly_visuals = TRUE //Toggle for liquidbelly level visuals.
+ var/churn_count = 0 //Counter for digested livings
+
+ var/passtable_reset // For crawling
+ var/passtable_crawl_checked = FALSE
+
+/mob/living/proc/handle_special_unlocks()
+ return
+
//
// Hook for generic creation of stuff on new creatures
//
/hook/living_new/proc/vore_setup(mob/living/M)
+
//Tries to load prefs if a client is present otherwise gives freebie stomach
spawn(2 SECONDS)
if(!QDELETED(M))
@@ -53,7 +64,11 @@
/mob/proc/init_vore()
//Something else made organs, meanwhile.
+ if(!isnewplayer(src))
+ AddElement(/datum/element/slosh)
if(LAZYLEN(vore_organs))
+ if(!soulgem)
+ soulgem = new(src)
return TRUE
//We'll load our client's organs if we have one
@@ -78,6 +93,8 @@
var/mob/living/carbon/human/H = src
if(istype(H.species,/datum/species/monkey))
allow_spontaneous_tf = TRUE
+ if(!soulgem)
+ soulgem = new(src)
return TRUE
/mob/living/init_vore()
@@ -248,7 +265,6 @@
P.show_vore_fx = src.show_vore_fx
P.can_be_drop_prey = src.can_be_drop_prey
P.can_be_drop_pred = src.can_be_drop_pred
- P.allow_inbelly_spawning = src.allow_inbelly_spawning
P.allow_spontaneous_tf = src.allow_spontaneous_tf
P.step_mechanics_pref = src.step_mechanics_pref
P.pickup_pref = src.pickup_pref
@@ -256,6 +272,7 @@
P.slip_vore = src.slip_vore
P.throw_vore = src.throw_vore
P.food_vore = src.food_vore
+ P.consume_liquid_belly = src.consume_liquid_belly
P.digest_pain = src.digest_pain
P.stumble_vore = src.stumble_vore
P.eating_privacy_global = src.eating_privacy_global
@@ -265,9 +282,27 @@
P.nutrition_messages = src.nutrition_messages
P.weight_message_visible = src.weight_message_visible
P.weight_messages = src.weight_messages
+ P.vore_sprite_color = src.vore_sprite_color
P.allow_mind_transfer = src.allow_mind_transfer
- P.vore_sprite_color = ishuman(src) ? src:vore_sprite_color : null
+ P.phase_vore = src.phase_vore
+ P.noisy_full = src.noisy_full
+ P.latejoin_vore = src.latejoin_vore
+ P.latejoin_prey = src.latejoin_prey
+ P.receive_reagents = src.receive_reagents
+ P.give_reagents = src.give_reagents
+ P.apply_reagents = src.apply_reagents
+ P.autotransferable = src.autotransferable
+ P.strip_pref = src.strip_pref
+ P.vore_sprite_multiply = src.vore_sprite_multiply
+ P.no_latejoin_vore_warning = src.no_latejoin_vore_warning
+ P.no_latejoin_prey_warning = src.no_latejoin_prey_warning
+ P.no_latejoin_vore_warning_time = src.no_latejoin_vore_warning_time
+ P.no_latejoin_prey_warning_time = src.no_latejoin_prey_warning_time
+ P.no_latejoin_vore_warning_persists = src.no_latejoin_vore_warning_persists
+ P.no_latejoin_prey_warning_persists = src.no_latejoin_prey_warning_persists
+ P.belly_rub_target = src.belly_rub_target
+ P.soulcatcher_pref_flags = src.soulcatcher_pref_flags
var/list/serialized = list()
for(var/obj/belly/B as anything in src.vore_organs)
@@ -275,12 +310,13 @@
P.belly_prefs = serialized
+ P.soulcatcher_prefs = src.soulgem.serialize()
return TRUE
//
// Proc for applying vore preferences, given bellies
//
-/mob/proc/copy_from_prefs_vr(var/bellies = TRUE)
+/mob/proc/copy_from_prefs_vr(var/bellies = TRUE, var/full_vorgans = FALSE) // full_vorgans var to bypass 1-belly load optimization.
if(!client || !client.prefs_vr)
to_chat(src,span_warning("You attempted to apply your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev."))
return FALSE
@@ -302,7 +338,6 @@
show_vore_fx = P.show_vore_fx
can_be_drop_prey = P.can_be_drop_prey
can_be_drop_pred = P.can_be_drop_pred
- allow_inbelly_spawning = P.allow_inbelly_spawning
allow_spontaneous_tf = P.allow_spontaneous_tf
step_mechanics_pref = P.step_mechanics_pref
pickup_pref = P.pickup_pref
@@ -311,6 +346,7 @@
throw_vore = P.throw_vore
stumble_vore = P.stumble_vore
food_vore = P.food_vore
+ consume_liquid_belly = P.consume_liquid_belly
digest_pain = P.digest_pain
eating_privacy_global = P.eating_privacy_global
allow_mimicry = P.allow_mimicry
@@ -322,11 +358,30 @@
vore_sprite_color = P.vore_sprite_color
allow_mind_transfer = P.allow_mind_transfer
+ phase_vore = P.phase_vore
+ noisy_full = P.noisy_full
+ latejoin_vore = P.latejoin_vore
+ latejoin_prey = P.latejoin_prey
+ receive_reagents = P.receive_reagents
+ give_reagents = P.give_reagents
+ apply_reagents = P.apply_reagents
+ autotransferable = P.autotransferable
+ strip_pref = P.strip_pref
+ vore_sprite_multiply = P.vore_sprite_multiply
+ no_latejoin_vore_warning = P.no_latejoin_vore_warning
+ no_latejoin_prey_warning = P.no_latejoin_prey_warning
+ no_latejoin_vore_warning_time = P.no_latejoin_vore_warning_time
+ no_latejoin_prey_warning_time = P.no_latejoin_prey_warning_time
+ no_latejoin_vore_warning_persists = P.no_latejoin_vore_warning_persists
+ no_latejoin_prey_warning_persists = P.no_latejoin_prey_warning_persists
+ belly_rub_target = P.belly_rub_target
+ soulcatcher_pref_flags = P.soulcatcher_pref_flags
+
if(bellies)
if(isliving(src))
var/mob/living/L = src
L.release_vore_contents(silent = TRUE)
- vore_organs.Cut()
+ QDEL_LIST(vore_organs)
for(var/entry in P.belly_prefs)
list_to_object(entry,src)
if(!vore_organs.len)
@@ -339,6 +394,14 @@
else
vore_selected = vore_organs[1]
+ if(soulgem)
+ src.soulgem.release_mobs()
+ QDEL_NULL(soulgem)
+ if(P.soulcatcher_prefs.len)
+ soulgem = list_to_object(P.soulcatcher_prefs, src)
+ else
+ soulgem = new(src)
+
return TRUE
/mob/proc/load_vore_prefs_from_slot()
@@ -463,12 +526,17 @@
if(!istype(tasted))
return
- if(!checkClickCooldown() || incapacitated(INCAPACITATION_ALL))
+ if(!checkClickCooldown() || incapacitated(INCAPACITATION_KNOCKOUT))
return
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(tasted == src)
+ visible_message(span_vwarning("[src] licks themself!"),span_notice("You lick yourself. You taste rather like [tasted.get_taste_message()]."),span_infoplain(span_bold("Slurp!")))
+ //balloon_alert_visible("licks themself!", "tastes like [tasted.get_taste_message()]")
+ else
+ visible_message(span_vwarning("[src] licks [tasted]!"),span_notice("You lick [tasted]. They taste rather like [tasted.get_taste_message()]."),span_infoplain(span_bold("Slurp!")))
+ //balloon_alert_visible("licks [tasted]!", "tastes like [tasted.get_taste_message()]")
- visible_message(span_vwarning("[src] licks [tasted]!"),span_vnotice("You lick [tasted]. They taste rather like [tasted.get_taste_message()]."),span_infoplain(span_bold("Slurp!")))
/mob/living/proc/get_taste_message(allow_generic = 1)
@@ -495,7 +563,7 @@
//This is just the above proc but switched about.
-/mob/living/proc/smell(mob/living/smelled in living_mobs(1))
+/mob/living/proc/smell(mob/living/smelled in living_mobs(1, TRUE))
set name = "Smell"
set category = "IC.Game"
set desc = "Smell someone nearby!"
@@ -503,11 +571,17 @@
if(!istype(smelled))
return
- if(!checkClickCooldown() || incapacitated(INCAPACITATION_ALL))
+ if(!checkClickCooldown() || incapacitated(INCAPACITATION_KNOCKOUT))
return
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- visible_message(span_vwarning("[src] smells [smelled]!"),span_vnotice("You smell [smelled]. They smell like [smelled.get_smell_message()]."),span_infoplain(span_bold("Sniff!")))
+ if(smelled == src)
+ visible_message(span_vwarning("[src] smells themself!"),span_notice("You smell yourself. You smell like [smelled.get_smell_message()]."),span_infoplain(span_bold("Sniff!")))
+ //balloon_alert_visible("smells themself!", "smells like [smelled.get_smell_message()]")
+ else
+ visible_message(span_vwarning("[src] smells [smelled]!"),span_notice("You smell [smelled]. They smell like [smelled.get_smell_message()]."),span_infoplain(span_bold("Sniff!")))
+ //balloon_alert_visible("smells [smelled]!", "smells like [smelled.get_smell_message()]")
+
/mob/living/proc/get_smell_message(allow_generic = 1)
if(!vore_smell && !allow_generic)
@@ -555,8 +629,7 @@
LAZYSET(SA.prey_excludes, src, world.time)
log_and_message_admins("used the OOC escape button to get out of [key_name(B.owner)] ([B.owner ? "JMP" : "null"])", src)
- if(!ishuman(B.owner))
- B.owner.update_icons()
+ B.owner.handle_belly_update() //This is run whenever a belly's contents are changed.
//You're in a dogborg!
else if(istype(loc, /obj/item/dogborg/sleeper))
@@ -582,11 +655,27 @@
crystal.unleash()
crystal.bound_mob = null
crystal.bound_mob = capture_crystal = 0
+ clear_fullscreen(ATOM_BELLY_FULLSCREEN)
log_and_message_admins("used the OOC escape button to get out of [crystal] owned by [crystal.owner]. [ADMIN_FLW(src)]", src)
//You've been turned into an item!
else if(tf_mob_holder && isvoice(src) && istype(src.loc, /obj/item))
var/obj/item/item_to_destroy = src.loc //If so, let's destroy the item they just TF'd out of.
+ //If tf_mob_holder is not located in src, then it's a Mind Binder OOC Escape
+ var/mob/living/ourmob = tf_mob_holder
+ if(ourmob.loc != src)
+ if(isnull(ourmob.loc))
+ to_chat(src,span_notice("You have no body."))
+ src.tf_mob_holder = null
+ return
+ if(ourmob.ckey)
+ to_chat(src,span_notice("Your body appears to be in someone else's control."))
+ return
+ src.mind.transfer_to(ourmob)
+ item_to_destroy.possessed_voice -= src
+ qdel(src)
+ log_and_message_admins("[key_name(src)] used the OOC escape button to revert back to their original form from being TFed into an object.")
+ return
if(istype(src.loc, /obj/item/clothing)) //Are they in clothes? Delete the item then revert them.
qdel(item_to_destroy)
log_and_message_admins("used the OOC escape button to revert back to their original form from being TFed into an object.", src)
@@ -612,6 +701,12 @@
qdel(G)
log_and_message_admins("used the OOC escape button to revert back from being petrified.", src)
+ //In-shoe OOC escape. Checking voices as precaution if something akin to obj TF or possession happens
+ else if(!istype(src, /mob/living/voice) && istype(src.loc, /obj/item/clothing/shoes))
+ var/obj/item/clothing/shoes/S = src.loc
+ forceMove(get_turf(src))
+ log_and_message_admins("[key_name(src)] used the OOC escape button to escape from of a pair of shoes. [ADMIN_FLW(src)] - Shoes [ADMIN_VV(S)]")
+
//You are in food and for some reason can't resist out
else if(istype(loc, /obj/item/reagent_containers/food))
var/obj/item/reagent_containers/food/F = src.loc
@@ -633,6 +728,14 @@
//
// Eating procs depending on who clicked what
//
+
+/mob/living/proc/feedable_bellies()
+ var/list/bellies = list()
+ for(var/obj/belly/Y in src.vore_organs)
+ if(Y.is_feedable)
+ bellies += Y
+ return bellies
+
/mob/living/proc/feed_grabbed_to_self(mob/living/user, mob/living/prey)
var/belly = user.vore_selected
return perform_the_nom(user, prey, user, belly)
@@ -640,17 +743,17 @@
/mob/living/proc/eat_held_mob(mob/living/user, mob/living/prey, mob/living/pred)
var/belly
if(user != pred)
- belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.vore_organs)
+ belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.feedable_bellies())
else
belly = pred.vore_selected
return perform_the_nom(user, prey, pred, belly)
/mob/living/proc/feed_self_to_grabbed(mob/living/user, mob/living/pred)
- var/belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.vore_organs)
+ var/belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.feedable_bellies())
return perform_the_nom(user, user, pred, belly)
/mob/living/proc/feed_grabbed_to_other(mob/living/user, mob/living/prey, mob/living/pred)
- var/belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.vore_organs)
+ var/belly = tgui_input_list(user, "Choose Belly", "Belly Choice", pred.feedable_bellies())
return perform_the_nom(user, prey, pred, belly)
//
@@ -727,6 +830,8 @@
prey.ai_holder?.react_to_attack(user)
//Timer and progress bar
+ if(!user.client && prey.weakened > 0) // stop crwaling instantly break swallow attempt for mobvore
+ prey.Stun(min(prey.weakened, 2)) // stop crwaling instantly break swallow attempt for mobvore
if(!do_after(user, swallow_time, prey, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Prey escpaed (or user disabled) before timer expired.
@@ -773,7 +878,6 @@
var/air_type = /datum/gas_mixture/belly_air
if(istype(lifeform)) // If this doesn't succeed, then 'lifeform' is actually a bag or capture crystal with someone inside
air_type = lifeform.get_perfect_belly_air_type() // Without any overrides/changes, its gonna be /datum/gas_mixture/belly_air
-
var/air = new air_type(1000)
return air
@@ -827,6 +931,15 @@
gas = list(
GAS_N2 = 100)
+/datum/gas_mixture/belly_air/carbon_dioxide_breather
+ volume = 2500
+ temperature = 293.150
+ total_moles = 104
+
+/datum/gas_mixture/carbon_dioxide_breather/New()
+ . = ..()
+ gas = list(
+ GAS_CO2 = 100)
/mob/living/proc/feed_grabbed_to_self_falling_nom(var/mob/living/user, var/mob/living/prey)
if(user.is_incorporeal())
@@ -887,7 +1000,7 @@
to_chat(src, span_notice("You are not holding anything."))
return
- if(is_type_in_list(I,edible_trash) || adminbus_trash)
+ if(is_type_in_list(I,edible_trash) || adminbus_trash || is_type_in_list(I,edible_tech) && isSynthetic()) // adds edible tech for synth
if(!I.on_trash_eaten(src)) // shows object's rejection message itself
return
drop_item()
@@ -895,9 +1008,9 @@
updateVRPanel()
log_admin("VORE: [src] used Eat Trash to swallow [I].")
I.after_trash_eaten(src)
- visible_message(span_warning("[src] demonstrates their voracious capabilities by swallowing [I] whole!"))
+ visible_message(span_vwarning("[src] demonstrates the voracious capabilities of their [lowertext(vore_selected.name)] by making [I] disappear!"))
return
- to_chat(src, span_notice("This item is not appropriate for ethical consumption."))
+ to_chat(src, span_notice("This snack is too powerful to go down that easily."))
return
/mob/living/proc/toggle_trash_catching() //Ported from chompstation
@@ -905,7 +1018,7 @@
set category = "Abilities.Vore"
set desc = "Toggle Trash Eater throw vore abilities."
trash_catching = !trash_catching
- to_chat(src, span_warning("Trash catching [trash_catching ? "enabled" : "disabled"]."))
+ to_chat(src, span_vwarning("Trash catching [trash_catching ? "enabled" : "disabled"]."))
/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"
@@ -1087,6 +1200,16 @@
save_ooc_panel(usr)
if(href_list["print_ooc_notes_chat"])
print_ooc_notes_chat(usr)
+ /* Not implemented on virgo
+ if(href_list["edit_ooc_note_favs"])
+ if(usr == src)
+ set_metainfo_favs(usr)
+ if(href_list["edit_ooc_note_maybes"])
+ if(usr == src)
+ set_metainfo_maybes(usr)
+ if(href_list["set_metainfo_ooc_style"])
+ set_metainfo_ooc_style(usr)
+ */
if(href_list["save_private_notes"])
if(usr == src)
save_private_notes(usr)
@@ -1103,45 +1226,57 @@
dat += span_red(span_bold("OOC DISABLED")) + "
"
if(!client?.prefs?.read_preference(/datum/preference/toggle/show_looc))
dat += span_red(span_bold("LOOC DISABLED")) + "
"
- dat += span_bold("Digestable:") + " [digestable ? span_green("Enabled") : span_red("Disabled")]
"
dat += span_bold("Devourable:") + " [devourable ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Feedable:") + " [feeding ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Absorption Permission:") + " [absorbable ? span_green("Allowed") : span_red("Disallowed")]
"
- dat += span_bold("Leaves Remains:") + " [digest_leave_remains ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Mob Vore:") + " [allowmobvore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Healbelly permission:") + " [permit_healbelly ? span_green("Allowed") : span_red("Disallowed")]
"
- dat += span_bold("Selective Mode Pref:") + " [src.selective_preference]
"
+ if(devourable)
+ dat += span_bold("Healbelly permission:") + " [permit_healbelly ? span_green("Allowed") : span_red("Disallowed")]
"
+ dat += span_bold("Digestable:") + " [digestable ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Absorption Permission:") + " [absorbable ? span_green("Allowed") : span_red("Disallowed")]
"
+ dat += span_bold("Selective Mode Pref:") + " [src.selective_preference]
"
+ dat += span_bold("Mob Vore:") + " [allowmobvore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Autotransferable:") + " [autotransferable ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Can be stripped:") + " [strip_pref ? span_green("Allowed") : span_red("Disallowed")]
"
+ dat += span_bold("Applying reagents:") + " [apply_reagents ? span_green("Allowed") : span_red("Disallowed")]
"
+ dat += span_bold("Leaves Remains:") + " [digest_leave_remains ? span_green("Enabled") : span_red("Disabled")]
"
dat += span_bold("Spontaneous vore prey:") + " [can_be_drop_prey ? span_green("Enabled") : span_red("Disabled")]
"
dat += span_bold("Spontaneous vore pred:") + " [can_be_drop_pred ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Drop Vore:") + " [drop_vore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Slip Vore:") + " [slip_vore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Throw vore:") + " [throw_vore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Stumble Vore:") + " [stumble_vore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Food Vore:") + " [food_vore ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Inbelly Spawning:") + " [allow_inbelly_spawning ? span_green("Allowed") : span_red("Disallowed")]
"
- dat += span_bold("Spontaneous transformation:") + " [allow_spontaneous_tf ? span_green("Enabled") : span_red("Disabled")]
"
- dat += span_bold("Mind transfer:") + " [allow_mind_transfer ? span_green("Allowed") : span_red("Disallowed")]
"
+ if(can_be_drop_prey || can_be_drop_pred)
+ dat += span_bold("Drop Vore:") + " [drop_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Slip Vore:") + " [slip_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Stumble Vore:") + " [stumble_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Throw vore:") + " [throw_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Food Vore:") + " [food_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Phase Vore:") + " [phase_vore ? span_green("Enabled") : span_red("Disabled")]
"
dat += span_bold("Can be stepped on/over:") + " [step_mechanics_pref ? span_green("Allowed") : span_red("Disallowed")]
"
dat += span_bold("Can be picked up:") + " [pickup_pref ? span_green("Allowed") : span_red("Disallowed")]
"
- dat += span_bold("Global Vore Privacy is:") + " [eating_privacy_global ? "Subtle" : "Loud"]
"
+ dat += span_bold("Can be resized:") + " [resizable ? span_green("Allowed") : span_red("Disallowed")]
"
+ dat += span_bold("Spontaneous transformation:") + " [allow_spontaneous_tf ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Mind transfer:") + " [allow_mind_transfer ? span_green("Allowed") : span_red("Disallowed")]
"
dat += span_bold("Allow Mimicry:") + " [allow_mimicry ? span_green("Yes") : span_red("No")]
"
- dat = "[dat]"
-
- var/datum/browser/popup = new(user, "[name]mvp", "Vore Prefs: [src]", 300, 400, src)
+ dat += span_bold("Feedable:") + " [feeding ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Receiving liquids:") + " [receive_reagents ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Giving liquids:") + " [give_reagents ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Consuming liquids:") + " [consume_liquid_belly ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Late join spawn point belly:") + " [latejoin_vore ? span_green("Enabled") : span_red("Disabled")]
"
+ if(latejoin_vore)
+ dat += span_bold("Late join spawn auto accept:") + " [no_latejoin_vore_warning ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Can be late join prey:") + " [latejoin_prey ? span_green("Enabled") : span_red("Disabled")]
"
+ if(latejoin_prey)
+ dat += span_bold("Late join prey auto accept:") + " [no_latejoin_prey_warning ? span_green("Enabled") : span_red("Disabled")]
"
+ dat += span_bold("Global Vore Privacy is:") + " [eating_privacy_global ? span_green("Subtle") : span_red("Loud")]
"
+ dat += span_bold("Current active belly:") + " [vore_selected ? vore_selected.name : "None"]
"
+ dat += span_bold("Belly rub target:") + " [belly_rub_target ? belly_rub_target : (vore_selected ? vore_selected.name : "None")]
"
+ var/datum/browser/popup = new(user, "[name]mvp", "Vore Prefs: [src]", 300, 700, src)
popup.set_content(dat)
popup.open()
// Full screen belly overlays!
/obj/screen/fullscreen/belly
+ icon = 'icons/mob/vore_fullscreens/screen_full_vore_list.dmi'
+
+/obj/screen/fullscreen/belly/fixed
icon = 'icons/mob/screen_full_vore.dmi'
icon_state = ""
-/obj/screen/fullscreen/belly/colorized
- icon = 'icons/mob/screen_full_colorized_vore.dmi'
-
-/obj/screen/fullscreen/belly/colorized/overlay
- icon = 'icons/mob/screen_full_colorized_vore_overlays.dmi'
-
/mob/living/proc/vorebelly_printout() //Spew the vorepanel belly messages into chat window for copypasting.
set name = "X-Print Vorebelly Settings"
set category = "Preferences.Vore"
@@ -1308,7 +1443,8 @@
if(owner.client)
create_mob_button(parent)
add_verb(owner, /mob/proc/insidePanel)
- owner.vorePanel = new(owner)
+ if(!owner.vorePanel)
+ owner.vorePanel = new(owner)
/datum/component/vore_panel/UnregisterFromParent()
. = ..()
@@ -1339,8 +1475,7 @@
/datum/component/vore_panel/proc/vore_panel_click(source, location, control, params, user)
var/mob/living/owner = user
if(istype(owner) && owner.vorePanel)
- INVOKE_ASYNC(owner.vorePanel, PROC_REF(tgui_interact), user)
-
+ INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob/living, insidePanel), owner)
/**
* Screen object for vore panel
*/
@@ -1349,3 +1484,287 @@
icon = 'icons/mob/screen/midnight.dmi'
icon_state = "vore"
screen_loc = ui_smallquad
+
+
+
+//
+// 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
+
+ var/fill_percentage = B.reagents.maximum_volume > 0 ? B.reagents.total_volume / B.reagents.maximum_volume : 0
+
+ if(0 <= fill_percentage && fill_percentage <= 0.2 && B.show_fullness_messages)
+ message += B.get_reagent_examine_msg1()
+ if(0.2 < fill_percentage && fill_percentage <= 0.4 && B.show_fullness_messages)
+ message += B.get_reagent_examine_msg2()
+ if(0.4 < fill_percentage && fill_percentage <= 0.6 && B.show_fullness_messages)
+ message += B.get_reagent_examine_msg3()
+ if(0.6 < fill_percentage && fill_percentage <= 0.8 && B.show_fullness_messages)
+ message += B.get_reagent_examine_msg4()
+ if(0.8 < fill_percentage && fill_percentage <= 1 && B.show_fullness_messages)
+ message += B.get_reagent_examine_msg5()
+
+ return message
+
+/mob/living/proc/vore_check_reagents()
+ set name = "Check Belly Liquid (Vore)"
+ set category = "Abilities.Vore"
+ set desc = "Check the amount of liquid in your belly."
+
+ var/obj/belly/RTB = tgui_input_list(src, "Choose which vore belly to check", "Select Belly", vore_organs)
+ if(!RTB)
+ return FALSE
+
+ to_chat(src, span_vnotice("[RTB] has [RTB.reagents.total_volume] units of liquid."))
+
+/mob/living/proc/vore_transfer_reagents()
+ set name = "Transfer Liquid (Vore)"
+ set category = "Abilities.Vore"
+ set desc = "Transfer liquid from an organ to another or stomach, or into another person or container."
+ set popup_menu = FALSE
+
+ if(!checkClickCooldown() || incapacitated(INCAPACITATION_KNOCKOUT))
+ return FALSE
+
+ var/mob/living/user = src
+
+ var/mob/living/TG = tgui_input_list(user, "Choose who to transfer from", "Transfer From", mobs_in_view(1,user))
+ if(!TG)
+ 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, span_vwarning("This person's prefs dont allow that!"))
+ return FALSE
+
+ var/obj/belly/RTB = tgui_input_list(user, "Choose which vore belly to transfer from", "Select Belly", vore_organs)
+ if(!RTB)
+ return FALSE
+
+ var/transfer_amount = tgui_input_list(user, "How much to transfer?", "Transfer Amount", list(5,10,25,50,100))
+ if(!transfer_amount)
+ return FALSE
+
+ switch(tgui_input_list(user,"Choose what to transfer to","Select Target", list("Vore belly", "Stomach", "Container", "Floor", "Cancel")))
+ if("Cancel")
+ return FALSE
+ if("Vore belly")
+ var/mob/living/TR = tgui_input_list(user,"Choose who to transfer to","Select Target", mobs_in_view(1,user))
+ if(!TR) return FALSE
+
+ if(TR == user) //Proceed, we dont need to have prefs enabled for transfer within user
+ var/obj/belly/TB = tgui_input_list(user, "Choose which organ to transfer to", "Select Belly", user.vore_organs)
+ if(!TB)
+ return FALSE
+ if(!Adjacent(TR) || !Adjacent(TG))
+ return //No long distance transfer
+ if(!TB.reagents?.get_free_space())
+ to_chat(user, span_vnotice("[TB] is full!"))
+ return FALSE
+
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from their [lowertext(RTB.name)] into their [lowertext(TB.name)]."))
+ else
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from [TG]'s [lowertext(RTB.name)] into their [lowertext(TB.name)]."))
+ add_attack_logs(user,TR,"Transfered [RTB.reagent_name] from [TG]'s [RTB] to [TR]'s [TB]") //Bonus for staff so they can see if people have abused transfer and done pref breaks
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_VORE, 1, 0, TB)
+ if(RTB.count_liquid_for_sprite || TB.count_liquid_for_sprite)
+ handle_belly_update()
+
+ else if(TR.receive_reagents == FALSE)
+ to_chat(user, span_vwarning("This person's prefs dont allow that!"))
+ return FALSE
+
+ else
+ var/obj/belly/TB = tgui_input_list(user, "Choose which organ to transfer to", "Select Belly", TR.vore_organs)
+ if(!TB)
+ return FALSE
+ if(!Adjacent(TR) || !Adjacent(TG))
+ return //No long distance transfer
+ if(!TB.reagents?.get_free_space())
+ to_chat(user, span_vnotice("[TR]'s [lowertext(TB.name)] is full!"))
+ return FALSE
+
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from their [lowertext(RTB.name)] into [TR]'s [lowertext(TB.name)]."))
+ else
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from [TG]s [lowertext(RTB.name)] into [TR]'s [lowertext(TB.name)]."))
+
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_VORE, 1, 0, TB)
+ 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(RTB.count_liquid_for_sprite)
+ handle_belly_update()
+ if(TB.count_liquid_for_sprite)
+ TR.handle_belly_update()
+
+
+ if("Stomach")
+ var/mob/living/TR = tgui_input_list(user,"Choose who to transfer to","Select Target", mobs_in_view(1,user))
+ if(!TR) return
+ if(!Adjacent(TR) || !Adjacent(TG))
+ return //No long distance transfer
+
+ if(TR == user) //Proceed, we dont need to have prefs enabled for transfer within user
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from their [lowertext(RTB.name)] into their stomach."))
+ else
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from [TG]'s [lowertext(RTB.name)] into their stomach."))
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_INGEST, 1, 0, null)
+ add_attack_logs(user,TR,"Transfered [RTB.reagent_name] from [TG]'s [RTB] to [TR]'s Stomach")
+ if(RTB.count_liquid_for_sprite)
+ handle_belly_update()
+
+ else if(TR.receive_reagents == FALSE)
+ to_chat(user, span_vwarning("This person's prefs dont allow that!"))
+ return FALSE
+
+ else
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from their [lowertext(RTB.name)] into [TR]'s stomach."))
+ else
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from [TG]'s [lowertext(RTB.name)] into [TR]'s stomach."))
+
+ RTB.reagents.vore_trans_to_mob(TR, transfer_amount, CHEM_INGEST, 1, 0, null)
+ add_attack_logs(user,TR,"Transfered [RTB.reagent_name] 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(RTB.count_liquid_for_sprite)
+ handle_belly_update()
+
+ if("Container")
+ if(RTB.reagentid == REAGENT_ID_STOMACID)
+ return
+ var/list/choices = list()
+ for(var/obj/item/reagent_containers/rc in view(1,user.loc))
+ choices += rc
+ var/obj/item/reagent_containers/arc = user.get_active_hand()
+ if(istype(arc,/obj/item/reagent_containers))
+ choices += arc
+ var/obj/item/reagent_containers/irc = user.get_inactive_hand()
+ if(istype(irc,/obj/item/reagent_containers))
+ choices += irc
+
+ var/obj/item/reagent_containers/T = tgui_input_list(user,"Choose what to transfer to","Select Target", choices)
+ if(!T)
+ return FALSE
+ if(!Adjacent(T) || !Adjacent(TG))
+ return //No long distance transfer
+
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from their [lowertext(RTB.name)] into [T]."))
+ else
+ user.custom_emote_vr(1, span_vnotice("[RTB.reagent_transfer_verb] [RTB.reagent_name] from [TG]'s [lowertext(RTB.name)] into [T]."))
+
+ RTB.reagents.vore_trans_to_con(T, transfer_amount, 1, 0)
+ add_attack_logs(user, T,"Transfered [RTB.reagent_name] from [TG]'s [RTB] to a [T]") //Bonus for staff so they can see if people have abused transfer and done pref breaks
+ if(RTB.count_liquid_for_sprite)
+ handle_belly_update()
+ if("Floor")
+ if(RTB.reagentid == REAGENT_ID_WATER)
+ return
+ var/amount_removed = RTB.reagents.remove_any(transfer_amount)
+ if(RTB.count_liquid_for_sprite)
+ handle_belly_update()
+ var/puddle_amount = round(amount_removed/5)
+
+ if(puddle_amount == 0)
+ to_chat(user,span_vnotice("[RTB.reagent_name] dripples from the [lowertext(RTB.name)], not enough to form a puddle."))
+ return
+
+ if(TG == user)
+ user.custom_emote_vr(1, span_vnotice("spills [RTB.reagent_name] from their [lowertext(RTB.name)] onto the floor!"))
+ else
+ user.custom_emote_vr(1, span_vnotice("spills [RTB.reagent_name] from [TG]'s [lowertext(RTB.name)] onto the floor!"))
+
+ var/obj/effect/decal/cleanable/blood/reagent/puddle = null
+ if (RTB.custom_reagentcolor)
+ puddle = new /obj/effect/decal/cleanable/blood/reagent(RTB.reagent_name, RTB.custom_reagentcolor, RTB.reagentid, puddle_amount, user.ckey, TG.ckey)
+ else
+ puddle = new /obj/effect/decal/cleanable/blood/reagent(RTB.reagent_name, RTB.reagentcolor, RTB.reagentid, puddle_amount, user.ckey, TG.ckey)
+
+ puddle.loc = TG.loc
+
+ var/soundfile
+ if(!RTB.fancy_vore)
+ soundfile = classic_release_sounds[RTB.release_sound]
+ else
+ soundfile = fancy_release_sounds[RTB.release_sound]
+ if(soundfile)
+ playsound(src, soundfile, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/preference/toggle/eating_noises)
+
+/mob/living/proc/vore_bellyrub(var/mob/living/T in view(1,src))
+ set name = "Give Bellyrubs"
+ set category = "Abilities.General"
+ set desc = "Provide bellyrubs to either yourself or another mob with a belly."
+
+ if(!T)
+ T = tgui_input_list(src, "Choose whose belly to rub", "Rub Belly?", mobs_in_view(1,src))
+ if(!T)
+ return FALSE
+ if(!(T in view(1,src)))
+ return FALSE
+ if(T.vore_selected)
+ var/obj/belly/B = T.vore_selected
+ if(istype(B))
+ if(T == src)
+ custom_emote_vr(1, "rubs their [belly_rub_target ? belly_rub_target : lowertext(B.name)].")
+ else
+ custom_emote_vr(1, "gives some rubs over [T]'s [belly_rub_target ? belly_rub_target : lowertext(B.name)].")
+ B.quick_cycle()
+ return TRUE
+ to_chat(src, span_vwarning("There is no suitable belly for rubs."))
+ return FALSE
+
+/mob/living/proc/mute_entry()
+ set name = "Mute Vorgan Entrance"
+ set category = "Preferences.Vore"
+ set desc = "Mute the chatlog messages when something enters a vore belly."
+ mute_entry = !mute_entry
+ to_chat(src, span_vwarning("Entrance logs [mute_entry ? "disabled" : "enabled"]."))
+
+/mob/living/proc/restrict_trasheater()
+ set name = "Restrict Trash Eater"
+ set category = "Abilities.Vore"
+ set desc = "Toggle Trash Eater restriction level."
+ adminbus_trash = !adminbus_trash
+ to_chat(src, span_vwarning("Trash Eater restriction level set to [adminbus_trash ? "everything not blacklisted" : "only whitelisted items"]."))
+
+/mob/living/proc/liquidbelly_visuals()
+ set name = "Toggle Liquidbelly Visuals"
+ set category = "Preferences.Vore"
+ set desc = "Toggle liquidbelly fullscreen visual effect."
+ liquidbelly_visuals = !liquidbelly_visuals
+ to_chat(src, span_vwarning("Liquidbelly overlays [liquidbelly_visuals ? "enabled" : "disabled"]."))
+
+/mob/living/proc/fix_vore_effects()
+ set name = "Fix Vore Effects"
+ set category = "OOC.Debug"
+ set desc = "Fix certain vore effects lingering after you've exited a belly."
+
+ if(!isbelly(src.loc))
+ if(alert(src, "Only use this verb if you are affected by certain vore effects outside of a belly, such as muffling or a stuck belly fullscreen.", "Clear Vore Effects", "Continue", "Nevermind") != "Continue")
+ return
+
+ absorbed = FALSE
+ muffled = FALSE
+ clear_fullscreen("belly")
+ clear_fullscreen(ATOM_BELLY_FULLSCREEN)
+ stop_sound_channel(CHANNEL_PREYLOOP)
+
+/mob/living/verb/vore_check_nutrition()
+ set name = "Check Nutrition"
+ set category = "Abilities.Vore"
+ set desc = "Check your current nutrition level."
+ to_chat(src, span_vnotice("Current nutrition level: [nutrition]."))
+
+// This proc will either return the first belly the mob is in or return null if they're not in one
+/mob/living/proc/surrounding_belly()
+ var/atom/curloc = src.loc
+ while(curloc && !isbelly(curloc))
+ if(istype(curloc, /turf)) break
+ if(!curloc.loc || curloc == curloc.loc) break
+ curloc = curloc.loc
+ if(isbelly(curloc)) return curloc
diff --git a/code/modules/vore/eating/mob_vr.dm b/code/modules/vore/eating/mob_vr.dm
index b33c87db601..145ac4edaef 100644
--- a/code/modules/vore/eating/mob_vr.dm
+++ b/code/modules/vore/eating/mob_vr.dm
@@ -6,7 +6,6 @@
var/resizable = TRUE // Can other people resize you? (Usually ignored for self-resizes)
var/digest_leave_remains = FALSE // Will this mob leave bones/skull/etc after the melty demise?
var/allowmobvore = TRUE // Will simplemobs attempt to eat the mob?
- var/allow_inbelly_spawning = FALSE // Will we even bother with attempts of someone to spawn in in one of our bellies?
var/obj/belly/vore_selected // Default to no vore capability.
var/list/vore_organs = list() // List of vore containers inside a mob
var/absorbed = FALSE // If a mob is absorbed into another
@@ -19,6 +18,7 @@
var/drop_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway
var/throw_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway
var/food_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway
+ var/consume_liquid_belly = FALSE //starting off because if someone is into that, they'll toggle it first time they get the error. Otherway around would be more pref breaky.
var/digest_pain = TRUE
var/can_be_drop_prey = FALSE
var/can_be_drop_pred = FALSE
@@ -69,4 +69,27 @@
var/vore_icons = 0 // Bitfield for which fields we have vore icons for.
var/vore_eyes = FALSE // For mobs with fullness specific eye overlays.
- // var/obj/soulgem/soulgem // Soulcatcher. Needs to be up-ported sometime.
+ var/obj/soulgem/soulgem // Soulcatcher. Needs to be up-ported sometime.
+
+ 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.
+ var/apply_reagents = TRUE //Pref for people to avoid having stomach reagents applied to them
+ var/latejoin_vore = FALSE //If enabled, latejoiners can spawn into this, assuming they have a client
+ var/latejoin_prey = FALSE //If enabled, latejoiners can spawn ontop of and instantly eat the victim
+ var/noisy_full = FALSE //Enables belching when a mob has overeaten
+ var/phase_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway
+ var/strip_pref = TRUE //Enables the ability for worn items to be stripped
+ var/no_latejoin_vore_warning = FALSE //Auto accepts pred spwan notifications (roundbased / saveable)
+ var/no_latejoin_prey_warning = FALSE //Auto accepts prey spawn notifications (roundbased / saveable)
+ var/no_latejoin_vore_warning_time = 15 //Time until accepting prey
+ var/no_latejoin_prey_warning_time = 15 //Time until accepting pred
+ var/no_latejoin_vore_warning_persists = FALSE //Do we save it?
+ var/no_latejoin_prey_warning_persists = FALSE //Do we save it?
+ var/belly_rub_target = null
+ var/soulcatcher_pref_flags = 0 //Default disabled
+
+ var/voice_freq = 42500 // Preference for character voice frequency
+ var/list/voice_sounds_list = list() // The sound list containing our voice sounds!
+ var/enabled = TRUE //Pauses a mob if disabled (Prevents life ticks from happening)
+ var/died_in_vr = FALSE //For virtual reality sleepers
+ var/last_move_time = 0 //For movement smoothing
diff --git a/code/modules/vore/eating/simple_animal_vr.dm b/code/modules/vore/eating/simple_animal_vr.dm
index ea14e535a42..be978862882 100644
--- a/code/modules/vore/eating/simple_animal_vr.dm
+++ b/code/modules/vore/eating/simple_animal_vr.dm
@@ -27,11 +27,12 @@
if(istype(src, /mob/living/simple_mob/animal/passive/mouse) && !T.ckey)
// Mice can't eat logged out players!
return
- if(client && IsAdvancedToolUser())
+ /*if(client && IsAdvancedToolUser()) Mob QOL, not everything can be grabbed and nobody wants wiseguy gotchas for trying.
to_chat(src, span_warning("Put your hands to good use instead!"))
return
+ */
feed_grabbed_to_self(src,T)
- update_icon()
+ //update_icon() CHOMPEdit
/mob/living/simple_mob/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay)
if(vore_active && !voremob_loaded && pred == src) //Only init your own bellies.
@@ -56,9 +57,12 @@
if(!vore_selected)
to_chat(user, span_warning("[src] isn't planning on eating anything much less digesting it."))
return
+/*ChompStation edit: This prevented some flexibility with mob vore and the returned message was highly unprofessional.
+
if(ai_holder.retaliate || (ai_holder.hostile && faction != user.faction))
to_chat(user, span_warning("This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you."))
return
+*/
if(vore_selected.digest_mode == DM_HOLD)
var/confirm = tgui_alert(user, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will reset after 20 minutes.", "Enabling [name]'s Digestion", list("Enable", "Cancel"))
if(confirm == "Enable")
@@ -116,3 +120,43 @@
if(isweakref(target))
var/mob/living/L = target.resolve()
LAZYREMOVE(prey_excludes, L) // It's fine to remove a null from the list if we couldn't resolve L
+
+/mob/living/simple_mob/proc/nutrition_heal()
+ set name = "Nutrition Heal"
+ set category = "Abilities.Mob"
+ set desc = "Slowly regenerate health using nutrition."
+
+ if(nutrition < 10)
+ to_chat(src, span_warning("You are too hungry to regenerate health."))
+ return
+ var/heal_amount = tgui_input_number(src, "Input the amount of health to regenerate at the rate of 10 nutrition per second per hitpoint. Current health: [health] / [maxHealth]", "Regenerate health.", 1, min_value=1)
+ if(!heal_amount)
+ return
+ heal_amount = CLAMP(heal_amount, 1, maxHealth - health)
+ heal_amount = CLAMP(heal_amount, 1, nutrition / 10)
+ if(do_after (src, 10 * heal_amount))
+ nutrition -= 10 * heal_amount
+ if(heal_amount < getBruteLoss())
+ adjustBruteLoss(-heal_amount)
+ return
+ heal_amount = heal_amount - getBruteLoss()
+ adjustBruteLoss(-getBruteLoss())
+ if(heal_amount < getFireLoss())
+ adjustFireLoss(-heal_amount)
+ return
+ heal_amount = heal_amount - getFireLoss()
+ adjustFireLoss(-getFireLoss())
+ if(heal_amount < getOxyLoss())
+ adjustOxyLoss(-heal_amount)
+ return
+ heal_amount = heal_amount - getOxyLoss()
+ adjustOxyLoss(-getOxyLoss())
+ if(heal_amount < getToxLoss())
+ adjustToxLoss(-heal_amount)
+ return
+ heal_amount = heal_amount - getToxLoss()
+ adjustToxLoss(-getToxLoss())
+ if(heal_amount < getCloneLoss())
+ adjustCloneLoss(-heal_amount)
+ return
+ adjustCloneLoss(-getCloneLoss())
diff --git a/code/modules/vore/eating/soulcatcher.dm b/code/modules/vore/eating/soulcatcher.dm
new file mode 100644
index 00000000000..99065c7490a
--- /dev/null
+++ b/code/modules/vore/eating/soulcatcher.dm
@@ -0,0 +1,551 @@
+/obj/soulgem
+ name = "Mind imprintation matrix"
+ desc = "A mind storage and processing system capable of capturing and supporting human-level minds in a small VR space."
+ var/mob/living/owner
+ var/datum/own_mind
+ var/obj/belly/linked_belly
+ var/taken_over_name
+
+ var/setting_flags = (NIF_SC_ALLOW_EARS|NIF_SC_ALLOW_EYES|NIF_SC_BACKUPS|NIF_SC_PROJECTING)
+ var/mob/selected_soul = null
+ var/list/brainmobs = list()
+ var/inside_flavor = "A small completely white room with a couch, and a window to what seems to be the outside world. A small sign in the corner says 'Configure Me'."
+ var/capture_message = "Your vision fades in a haze of static, before returning.\nAround you, you see...\n"
+ var/transit_message = "Your surroundings change to..."
+ var/release_message = "Release Message"
+ var/transfer_message = "Transfer Message"
+ var/delete_message = "Delete Message"
+
+// Append the vars to save to our savefile list
+/obj/soulgem/vars_to_save()
+ var/list/saving = list (
+ "setting_flags",
+ "inside_flavor",
+ "capture_message",
+ "transit_message",
+ "release_message",
+ "transfer_message",
+ "delete_message",
+ "linked_belly"
+ )
+ return ..() + saving
+
+// Load the vars_to_save from the savefile
+/obj/soulgem/Initialize(mapload)
+ . = ..()
+ if(ismob(loc))
+ owner = loc
+ owner.recalculate_vis()
+
+// Store the vars_to_save into the save file
+/obj/soulgem/deserialize(list/data)
+ . = ..()
+ for(var/obj/belly in owner.vore_organs)
+ if(belly.name == data["linked_belly"])
+ update_linked_belly(belly, TRUE)
+ return
+ linked_belly = null
+
+// Allows to transfer the soulgem to the given mob
+/obj/soulgem/proc/transfer_self(var/mob/target)
+ QDEL_NULL(target.soulgem)
+ owner.soulgem = null
+ forceMove(target)
+ owner = target
+ target.soulgem = src
+
+// Cleaning up our refs before deletion
+/obj/soulgem/Destroy()
+ owner = null
+ selected_soul = null
+ own_mind = null
+ QDEL_LIST_NULL(brainmobs)
+ if(istype(linked_belly))
+ UnregisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX)
+ linked_belly = null
+ . = ..()
+
+// Sends messages to the owner of the soulcatcher
+/obj/soulgem/proc/notify_holder(var/message)
+ message = span_nif(span_bold("[name]") + " displays, \"" + span_notice("[message]") + "\"")
+ to_chat(owner, message)
+
+ for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
+ to_chat(CS, message)
+
+// Forwards the speech of captured souls
+/obj/soulgem/proc/use_speech(var/message, var/mob/living/sender, var/mob/eyeobj, var/whisper)
+ var/sender_name = eyeobj ? eyeobj.name : sender.name
+
+ //AR Projecting
+ if(eyeobj)
+ var/speak_verb = "says"
+ message = span_game(span_say(span_bold("[sender_name]") + " [speak_verb], \"[message]\""))
+ if(whisper)
+ speak_verb = "whispers"
+ sender.eyeobj.visible_message(span_italics(message), range = 1)
+ else
+ sender.eyeobj.visible_message(message)
+
+ //Not AR Projecting
+ else
+ var/speak_verb = "speaks"
+ message = span_nif(span_bold("\[SC\] [sender_name]") + " [speak_verb], \"[message]\"")
+ to_chat(owner, message)
+ if(whisper)
+ speak_verb = "whispers"
+ to_chat(sender, span_italics(message))
+ else
+ for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
+ to_chat(CS, message)
+
+ log_nsay(message, owner.real_name, sender)
+
+// Forwards the emotes of captured souls
+/obj/soulgem/proc/use_emote(var/message, var/mob/living/sender, var/mob/eyeobj, var/whisper)
+ var/sender_name = eyeobj ? eyeobj.name : sender.name
+
+ //AR Projecting
+ if(eyeobj)
+ message = span_emote("[sender_name] [message]")
+ if(whisper)
+ sender.eyeobj.visible_message(span_italics(message), range = 1)
+ else
+ sender.eyeobj.visible_message(message)
+ //Not AR Projecting
+ else
+ message = span_nif(span_bold("[sender_name]") + " [message]")
+ to_chat(owner, message)
+ if(whisper)
+ to_chat(sender, span_italics(message))
+ else
+ for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
+ to_chat(CS, message)
+
+ log_nme(message, owner.real_name,sender)
+
+// The capture function which transfers the given mob's mind into the soulcatcher
+/obj/soulgem/proc/catch_mob(var/mob/M, var/custom_name)
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE) && !isobserver(M)) return // Bypass pref check for observer join
+ if(!M.mind) return
+ if(isbrain(owner)) return
+ //Create a new brain mob
+ var/mob/living/carbon/brain/caught_soul/vore/brainmob = new(src)
+ brainmob.gem = src
+ brainmob.container = src
+ brainmob.stat = 0
+ brainmob.silent = FALSE
+ dead_mob_list -= brainmob
+ brainmob.ext_deaf = !flag_check(NIF_SC_ALLOW_EARS)
+ brainmob.ext_blind = !flag_check(NIF_SC_ALLOW_EYES)
+ brainmob.add_language(LANGUAGE_GALCOM)
+ brainmobs |= brainmob
+
+ //Put the mind and player into the mob
+ M.mind.transfer_to(brainmob)
+ brainmob.name = custom_name ? custom_name : brainmob.mind.name
+ brainmob.real_name = custom_name ? custom_name : brainmob.mind.name
+
+ //If we caught our owner, special settings.
+ if(M == owner && !own_mind) // Need some more sanity if we allow takeover
+ brainmob.ext_deaf = FALSE
+ brainmob.ext_blind = FALSE
+ brainmob.parent_mob = TRUE
+ own_mind = brainmob.mind
+ remove_verb(brainmob, /mob/proc/enter_soulcatcher) //No recursive self capturing...
+ add_verb(brainmob, /mob/living/carbon/brain/caught_soul/vore/proc/transfer_self)
+ add_verb(brainmob, /mob/living/carbon/brain/caught_soul/vore/proc/reenter_body)
+
+ //If they have these values, apply them
+ if(isliving(M))
+ var/mob/living/L = M
+ brainmob.dna = L.dna
+ brainmob.ooc_notes = L.ooc_notes
+ brainmob.ooc_notes_likes = L.ooc_notes_likes
+ brainmob.ooc_notes_dislikes = L.ooc_notes_dislikes
+ /* Not implemented on virgo
+ brainmob.ooc_notes_favs = L.ooc_notes_favs
+ brainmob.ooc_notes_maybes = L.ooc_notes_maybes
+ brainmob.ooc_notes_style = L.ooc_notes_style
+ */
+ brainmob.timeofhostdeath = L.timeofdeath
+ if(ishuman(L))
+ SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it.
+
+ //Else maybe they're a joining ghost
+ else if(isobserver(M))
+ brainmob.transient = TRUE
+ qdel(M) //Bye ghost
+
+ //Give them a flavortext message
+ var/message = span_notice("[capture_message][inside_flavor]")
+
+ to_chat(brainmob, message)
+
+ //Reminder on how this works to host
+ if(brainmobs.len == 1) //Only spam this on the first one
+ to_chat(owner, span_notice("Your occupant's messages/actions can only be seen by you, and you can \
+ send messages that only they can hear/see by using the NSay and NMe verbs (or the *nsay and *nme emotes)."))
+
+ //Announce to host and other minds
+ notify_holder("New mind loaded: [brainmob.name]")
+ show_vore_fx(brainmob, TRUE)
+ brainmob.copy_from_prefs_vr(bellies = FALSE)
+ return TRUE
+
+// Allows to adjust the interior of the soulcatcher
+/obj/soulgem/proc/adjust_interior(var/new_flavor)
+ new_flavor = sanitize(new_flavor, MAX_MESSAGE_LEN * 2)
+ inside_flavor = new_flavor
+ notify_holder("Updating environment...")
+ for(var/mob/living/carbon/brain/caught_soul/vore/CS as anything in brainmobs)
+ to_chat(CS, span_notice("[transit_message]") + "\n[inside_flavor]")
+
+// Allows to return to the body after being captured by one's own soulcatcher
+/obj/soulgem/proc/return_to_body(var/datum/mind)
+ if(own_mind != mind)
+ to_chat(src, span_warning("You aren't in your own soulcatcher!"))
+ return
+ var/mob/self = null
+ for(var/mob/mob in brainmobs)
+ if(mob.mind == mind)
+ self = mob
+ break
+ if(!self)
+ return
+ if(owner.mind)
+ catch_mob(owner, taken_over_name)
+ self.mind.transfer_to(owner)
+ own_mind = null
+ taken_over_name = null
+ qdel(self)
+
+// Sets the custom messages depending on the input
+/obj/soulgem/proc/set_custom_message(var/message, var/target)
+ message = sanitize(message, MAX_MESSAGE_LEN / 4)
+ switch(target)
+ if("capture")
+ capture_message = message
+ if("transit")
+ transit_message = message
+ if("release")
+ release_message = message
+ if("transfer")
+ transfer_message = message
+ if("delete")
+ delete_message = message
+
+// Allows to rename the soulgem
+/obj/soulgem/proc/rename(var/new_name)
+ if(length(new_name) < 3 || length(new_name) > 60)
+ to_chat(owner, span_warning("Your soulcatcher's name needs to be between 3 and 60 characters long!"))
+ return
+ new_name = sanitize(new_name, 60)
+ name = new_name
+
+// Toggles the given flag
+/obj/soulgem/proc/toggle_setting(var/flag)
+ setting_flags ^= flag
+ if(flag & SOULGEM_SHOW_VORE_SFX)
+ soulgem_show_vfx(TRUE)
+ soulgem_vfx()
+ if(flag & NIF_SC_BACKUPS)
+ soulgem_backup()
+ if(flag & NIF_SC_ALLOW_EARS)
+ soulgem_hear()
+ if(flag & NIF_SC_ALLOW_EYES)
+ soulgem_sight()
+ if(flag & NIF_SC_PROJECTING)
+ soulgem_projecting()
+ if(flag & SOULGEM_SEE_SR_SOULS)
+ owner.recalculate_vis()
+
+// Checks a single flag, or if all combined flags are true
+/obj/soulgem/proc/flag_check(var/flag, var/match_all = FALSE)
+ if(match_all)
+ return (setting_flags & flag) == flag
+ return setting_flags & flag
+
+// Updates the selected soul after an interaction which rleased, deleted or transferred the previous one
+/obj/soulgem/proc/update_selected_soul()
+ if(brainmobs.len > 1)
+ selected_soul = brainmobs[1]
+ else
+ selected_soul = null
+
+// Backup toggling
+/obj/soulgem/proc/soulgem_backup()
+ if(flag_check(NIF_SC_BACKUPS))
+ notify_holder("External backups enabled.")
+ else
+ notify_holder("External backups disabled.")
+
+// Deaf toggling
+/obj/soulgem/proc/soulgem_hear()
+ for(var/mob/living/carbon/brain/caught_soul/L in brainmobs)
+ L.ext_deaf = !flag_check(NIF_SC_ALLOW_EARS)
+ if(flag_check(NIF_SC_ALLOW_EARS))
+ notify_holder("External sounds enabled.")
+ else
+ notify_holder("External sounds disabled.")
+
+// Sight toggling
+/obj/soulgem/proc/soulgem_sight()
+ for(var/mob/living/carbon/brain/caught_soul/L in brainmobs)
+ L.ext_blind = !flag_check(NIF_SC_ALLOW_EYES)
+ if(flag_check(NIF_SC_ALLOW_EYES))
+ notify_holder("External vision enabled.")
+ else
+ notify_holder("External vision disabled.")
+
+// Projecting toggling
+/obj/soulgem/proc/soulgem_projecting()
+ if(flag_check(NIF_SC_PROJECTING))
+ notify_holder("AR projecting enabled.")
+ else
+ notify_holder("AR projecting disabled.")
+
+// VORE FX Section
+
+// Updates the vore FX signal links to the new given belly
+/obj/soulgem/proc/update_linked_belly(var/obj/belly, var/skip_unreg = FALSE)
+ if(!belly && linked_belly)
+ UnregisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX)
+ linked_belly = null
+ return
+ if(!isbelly(belly))
+ return
+ if(!linked_belly)
+ linked_belly = belly
+ RegisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX, PROC_REF(soulgem_show_vfx))
+ return
+ if(belly != linked_belly)
+ if(!skip_unreg)
+ UnregisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX)
+ linked_belly = belly
+ RegisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX, PROC_REF(soulgem_show_vfx))
+
+// Handles the vore fx updates for the captured souls
+/obj/soulgem/proc/soulgem_show_vfx(var/update, var/severity = 0)
+ if(linked_belly)
+ for(var/mob/living/L in brainmobs)
+ if(flag_check(SOULGEM_SHOW_VORE_SFX))
+ show_vore_fx(L, update, severity)
+ else
+ clear_vore_fx(L)
+
+// Function to show the vore fx overlay
+/obj/soulgem/proc/show_vore_fx(var/mob/living/L, var/update, var/severity = 0)
+ if(!linked_belly || !flag_check(SOULGEM_SHOW_VORE_SFX))
+ return
+ if(!istype(L) || L.eyeobj)
+ return
+ linked_belly.vore_fx(L, update, severity)
+
+// Function to clear the vore fx overlay
+/obj/soulgem/proc/clear_vore_fx(var/mob/M)
+ M.clear_fullscreen("belly")
+ if(M.hud_used && !M.hud_used.hud_shown)
+ M.toggle_hud_vis(TRUE)
+
+// VFX toggling
+/obj/soulgem/proc/soulgem_vfx()
+ if(flag_check(SOULGEM_SHOW_VORE_SFX))
+ notify_holder("Interior simulation enabled.")
+ else
+ notify_holder("Interior simulation disabled.")
+
+// Takeover section
+
+// Give control of the body to the current selected soul
+/obj/soulgem/proc/take_control_selected()
+ if(!selected_soul) return
+ take_control(selected_soul)
+ if(owner.mind == own_mind)
+ own_mind = null
+ taken_over_name = null
+
+// Give back control of the body to the owner
+/obj/soulgem/proc/take_control_owner()
+ var/mob/self = null
+ for(var/mob/mob in brainmobs)
+ if(mob.mind == own_mind)
+ self = mob
+ break
+ if(!self)
+ return
+ take_control(self)
+ own_mind = null
+ taken_over_name = null
+
+/obj/soulgem/proc/take_control(var/mob/M)
+ if(!(owner.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE) || !(owner.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TAKEOVER)) return
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE) || !(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TAKEOVER)) return
+ if(!own_mind)
+ if(issilicon(owner) || isanimal(owner))
+ taken_over_name = owner.name
+ catch_mob(owner, taken_over_name)
+ taken_over_name = M.name
+ M.mind.transfer_to(owner)
+ brainmobs -= M
+ if(M == selected_soul)
+ update_selected_soul()
+ qdel(M)
+
+// Funtion to test if the owner's body has been taken over
+/obj/soulgem/proc/is_taken_over()
+ return (own_mind && owner.mind && owner.mind != own_mind)
+
+// Transfer section to transfer captured souls
+
+// Returns nearby,valid transfer locations as a list
+/obj/soulgem/proc/find_transfer_objects()
+ var/list/valid_trasfer_objects = list(
+ /obj/item/sleevemate,
+ /obj/item/mmi
+ )
+ var/list/valid_objects = list()
+ if(isrobot(owner))
+ var/mob/living/silicon/robot/R = owner
+ if(istype(R.module_active, /obj/item/sleevemate))
+ valid_objects += R.module_active
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ if(is_type_in_list(H.get_left_hand(), valid_trasfer_objects))
+ valid_objects += H.get_left_hand()
+ if(is_type_in_list(H.get_right_hand(), valid_trasfer_objects))
+ valid_objects += H.get_right_hand()
+ for(var/obj/item/I in range(0, get_turf(owner)))
+ if(is_type_in_list(I, valid_trasfer_objects))
+ valid_objects += I
+ for(var/mob/M in range(1, get_turf(owner)))
+ if(M == owner)
+ continue
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TRANSFER))
+ continue
+ if(M.client && M.soulgem)
+ valid_objects += M.soulgem
+ if(!valid_objects.len)
+ to_chat(owner, span_warning("No valid objects found!"))
+ return
+ return valid_objects
+
+// Transfer the selected soul to either a valid object or another soulcatcher
+/obj/soulgem/proc/transfer_selected()
+ if(!selected_soul) return
+ if(!(selected_soul.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TRANSFER)) return
+ var/list/valid_objects = find_transfer_objects()
+ if(!valid_objects || !valid_objects.len)
+ return
+ var/obj/target = tgui_input_list(owner, "Select where you want to store the mind into.", "Mind Transfer Target", valid_objects)
+ transfer_mob_selector(selected_soul, target)
+
+// Transfer selector proc
+/obj/soulgem/proc/transfer_mob_selector(var/mob/M, var/obj/target)
+ if(!M || !target) return
+ if(istype(target, /obj/soulgem))
+ transfer_mob_soulcatcher(M, target)
+ return
+ transfer_mob(M, target)
+
+// Transfers a captured soul to a valid object (sleevemate, mmi)
+/obj/soulgem/proc/transfer_mob(var/mob/M, var/obj/target)
+ if(is_taken_over()) return
+ if(!M || !target) return
+ if(istype(target, /obj/item/sleevemate))
+ var/obj/item/sleevemate/mate = target
+ if(!mate.stored_mind)
+ to_chat(owner, span_notice("You scan yourself to transfer the soul into the [target]!"))
+ to_chat(M, span_notice("[transfer_message]"))
+ if(M.mind == own_mind)
+ own_mind = null
+ mate.get_mind(M)
+ else if(istype(target, /obj/item/mmi))
+ var/obj/item/mmi/mm = target
+ if(!mm.brainmob || !mm.brainmob.mind)
+ if(M.mind == own_mind)
+ own_mind = null
+ to_chat(owner, span_notice("You transfer the soul into the [target]!"))
+ to_chat(M, span_notice("[transfer_message]"))
+ mm.transfer_identity(M)
+ if(!mm.brainmob.mind && M.mind)
+ M.mind.transfer_to(mm.brainmob)
+ else
+ return
+ brainmobs -= M
+ if(M == selected_soul)
+ update_selected_soul()
+ qdel(M)
+
+// Transfers a captured soul to another soulcatcher
+/obj/soulgem/proc/transfer_mob_soulcatcher(var/mob/living/carbon/brain/caught_soul/vore/M, var/obj/soulgem/gem)
+ if(is_taken_over()) return
+ if(!istype(M) || !gem) return
+ if(!gem.owner) return
+ if((tgui_alert(gem.owner, "Do you want to allow [owner] to transfer [selected_soul] to your soulcatcher?", "Allow Transfer", list("No", "Yes")) != "Yes"))
+ return
+ if(!in_range(gem.owner, owner))
+ return
+ if(!(gem.owner.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TRANSFER))
+ return
+ if(M.mind == own_mind)
+ own_mind = null
+ brainmobs -= M
+ M.gem = gem
+ M.container = gem
+ gem.brainmobs += M
+ if(M == selected_soul)
+ update_selected_soul()
+
+// Release section
+
+// Release the selected soul as a ghost
+/obj/soulgem/proc/release_selected()
+ if(!selected_soul) return
+ if(release_mob(selected_soul))
+ update_selected_soul()
+
+// Release all captured souls as ghosts
+/obj/soulgem/proc/release_mobs()
+ selected_soul = null
+ if(!brainmobs.len) return
+ for(var/mob/M in brainmobs)
+ release_mob(M)
+
+// Proc to release the soul as ghost, returns TRUE on success
+/obj/soulgem/proc/release_mob(var/mob/M)
+ if(is_taken_over()) return FALSE
+ to_chat(M, span_notice("[release_message]"))
+ brainmobs -= M
+ M.ghostize(FALSE)
+ qdel(M)
+ return TRUE
+
+// Delete section to delete captured souls from the soulcatcher
+
+// Delete the selected mob
+/obj/soulgem/proc/delete_selected()
+ if(!selected_soul) return
+ if(delete_mob(selected_soul))
+ update_selected_soul()
+
+// Delete all captured mobs
+/obj/soulgem/proc/erase_mobs()
+ if(!brainmobs.len) return
+ for(var/mob/M in brainmobs)
+ delete_mob(M)
+
+// The function handling the actual delete, returns TRUE on success
+/obj/soulgem/proc/delete_mob(var/mob/M)
+ if(is_taken_over()) return FALSE
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_DELETION))
+ return release_mob(M)
+ if(!(M.soulcatcher_pref_flags & SOULCATCHER_ALLOW_DELETION_INSTANT))
+ if(tgui_alert(M, "Do you really want to allow [owner] to delete you? On decline, you'll be ghosted.", "Allow Deletion", list("No", "Yes"), timeout=1 MINUTES) != "Yes")
+ return release_mob(M)
+ to_chat(M, span_danger("[delete_message]"))
+ brainmobs -= M
+ var/mob/observer/dead/ghost = M.ghostize(FALSE)
+ ghost.abandon_mob()
+ qdel(M)
+ return TRUE
diff --git a/code/modules/vore/eating/soulcatcher_mob.dm b/code/modules/vore/eating/soulcatcher_mob.dm
new file mode 100644
index 00000000000..30bab937453
--- /dev/null
+++ b/code/modules/vore/eating/soulcatcher_mob.dm
@@ -0,0 +1,245 @@
+/mob/living/carbon/brain/caught_soul/vore
+ name = "stored soul"
+ desc = "A soul stored within the predator."
+
+ var/obj/soulgem/gem
+
+// Cleaning up the refs during deletion
+/mob/living/carbon/brain/caught_soul/vore/Destroy()
+ if(gem)
+ gem.notify_holder("Mind unloaded: [name]")
+ gem.brainmobs -= src
+ gem = null
+ if(eyeobj)
+ QDEL_NULL(eyeobj)
+ gem.notify_holder("[name] ended SR projection.")
+ container = null
+ return ..()
+
+// Handling the automatic transcore backups in a set interval
+/mob/living/carbon/brain/caught_soul/vore/Life()
+ . = ..()
+ if(QDELETED(src))
+ return
+
+ if(!parent_mob && !transient &&(life_tick % 150 == 0) && gem.setting_flags & NIF_SC_BACKUPS)
+ SStranscore.m_backup(mind,0) //Passed 0 means "Don't touch the nif fields on the mind record"
+
+ if(!client)
+ return
+
+ if(ext_blind)
+ eye_blind = 5
+ client.screen.Remove(global_hud.whitense)
+ overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
+ else
+ eye_blind = 0
+ clear_fullscreen("blind")
+ if(!gem.flag_check(SOULGEM_SHOW_VORE_SFX))
+ client.screen.Add(global_hud.whitense)
+ if(gem.flag_check(SOULGEM_SHOW_VORE_SFX))
+ client.screen.Remove(global_hud.whitense)
+
+// Say proc for captures souls
+/mob/living/carbon/brain/caught_soul/vore/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
+ if(silent) return FALSE
+ gem.use_speech(message, src, eyeobj)
+
+// Emote proc for captured souls
+/mob/living/carbon/brain/caught_soul/vore/custom_emote(var/m_type, var/message)
+ if(silent) return FALSE
+ gem.use_emote(message,src,eyeobj)
+
+/mob/living/carbon/brain/caught_soul/vore/me_verb_subtle(message as message)
+ if(silent) return FALSE
+ gem.use_emote(message,src,eyeobj,TRUE)
+
+/mob/living/carbon/brain/caught_soul/vore/whisper(message as text)
+ if(silent) return FALSE
+ gem.use_speech(message,src,eyeobj,TRUE)
+
+// Resist override, only returning a message that one is stuck for now
+/mob/living/carbon/brain/caught_soul/vore/resist()
+ set name = "Resist"
+ set category = "IC.Game"
+
+ to_chat(src, span_warning("There's no way out! You're stuck inside your predator."))
+
+// Allows the predator to enter their own soulcatcher
+/mob/proc/enter_soulcatcher()
+ set name = "Enter Soulcatcher"
+ set desc = "Enter your own Soulcatcher."
+ set category = "IC.Vore"
+
+ if(!soulgem) // Only sanity...
+ return
+ if(soulgem && soulgem.flag_check(SOULGEM_ACTIVE))
+ var/to_use_custom_name = null
+ if(issilicon(src) || isanimal(src))
+ to_use_custom_name = src.name
+ soulgem.catch_mob(src, to_use_custom_name)
+
+// Speak to the captured souls within the own soulcatcher
+/mob/proc/nsay_vore(message as message)
+ set name = "NSay Vore"
+ set desc = "Speak into your Soulcatcher."
+
+ src.nsay_vore_act(message)
+
+/mob/proc/nsay_vore_ch()
+ set name = "NSay Vore CH"
+ set desc = "Speak into your Soulcatcher."
+ set category = "IC.Vore"
+
+ src.nsay_vore_act()
+
+/mob/proc/nsay_vore_act(var/message)
+ if(stat != CONSCIOUS)
+ to_chat(src, span_warning("You can't use NSay Vore while unconscious."))
+ return
+ if(!soulgem) // Only sanity...
+ return
+ var/obj/soulgem/gem = soulgem
+ if(!gem.brainmobs.len)
+ to_chat(src, span_warning("You need a devoured soul to use NSay Vore."))
+ return
+
+ if(!message)
+ message = tgui_input_text(usr, "Type a message to say.","Speak into Soulcatcher", multiline=TRUE)
+ if(message)
+ var/sane_message = sanitize(message)
+ gem.use_speech(sane_message, src)
+
+// Emote to the captured souls within the soulcatcher
+/mob/proc/nme_vore(message as message)
+ set name = "NMe Vore"
+ set desc = "Emote into your Soulcatcher."
+
+ src.nme_vore_act(message)
+
+/mob/proc/nme_vore_ch()
+ set name = "NMe Vore CH"
+ set desc = "Emote into your Soulcatcher."
+ set category = "IC.Vore"
+
+ src.nme_vore_act()
+
+/mob/proc/nme_vore_act(var/message)
+ if(stat != CONSCIOUS)
+ to_chat(src, span_warning("You can't use NMe Vore while unconscious."))
+ return
+ if(!soulgem) // Only sanity...
+ return
+ var/obj/soulgem/gem = soulgem
+ if(!gem.brainmobs.len)
+ to_chat(src, span_warning("You need a devoured soul to use NMe Vore."))
+ return
+
+ if(!message)
+ message = tgui_input_text(usr, "Type an action to perform.","Emote into Soulcatcher", multiline=TRUE)
+ if(message)
+ var/sane_message = sanitize(message)
+ gem.use_emote(sane_message, src)
+
+// SR projecting mob
+/mob/observer/eye/ar_soul/vore
+ plane = PLANE_SOULCATCHER
+
+// SR project as captured soul
+/mob/living/carbon/brain/caught_soul/vore/ar_project()
+ set name = "AR/SR Project"
+ set desc = "Project your form into Augmented Reality for those around your predator with the appearance of your loaded character."
+ set category = "Soulcatcher"
+
+ if(eyeobj)
+ to_chat(src, span_warning("You're already projecting in SR!"))
+ return
+
+ if(!(gem.setting_flags & NIF_SC_PROJECTING))
+ to_chat(src, span_warning("Projecting from this NIF has been disabled!"))
+ return
+
+ if(!client || !client.prefs)
+ return //Um...
+
+ eyeobj = new/mob/observer/eye/ar_soul/vore(src, gem.owner)
+ gem.notify_holder("[src] now SR projecting.")
+ gem.clear_vore_fx(src)
+
+// Jump to the owner as SR projection
+/mob/living/carbon/brain/caught_soul/vore/jump_to_owner()
+ set name = "Jump to Owner"
+ set desc = "Jump your projection back to the owner of the soulcatcher you're inside."
+ set category = "Soulcatcher"
+
+ if(!eyeobj)
+ to_chat(src, span_warning("You're not projecting into SR!"))
+ return
+
+ eyeobj.forceMove(get_turf(gem))
+
+// End SR projecting and return to the soulcatcher containing the soul
+/mob/living/carbon/brain/caught_soul/vore/reenter_soulcatcher()
+ set name = "Re-enter Soulcatcher"
+ set desc = "Leave SR projection and drop back into the soulcatcher."
+ set category = "Soulcatcher"
+
+ if(!eyeobj)
+ to_chat(src, span_warning("You're not projecting into SR!"))
+ return
+
+ QDEL_NULL(eyeobj)
+ gem.notify_holder("[src] ended SR projection.")
+ gem.show_vore_fx(src, TRUE)
+
+/mob/living/carbon/brain/caught_soul/vore/nsay_brain()
+ set name = "NSay"
+ set desc = "Speak to your Soulcatcher (circumventing SR speaking)."
+ set category = "Soulcatcher"
+
+ var/message = tgui_input_text(usr, "Type a message to say.","Speak into Soulcatcher", multiline=TRUE)
+ if(message)
+ var/sane_message = sanitize(message)
+ gem.use_speech(sane_message, src)
+
+/mob/living/carbon/brain/caught_soul/vore/nme_brain()
+ set name = "NMe"
+ set desc = "Emote to your Soulcatcher (circumventing SR speaking)."
+ set category = "Soulcatcher"
+
+ var/message = tgui_input_text(usr, "Type an action to perform.","Emote into Soulcatcher", multiline=TRUE)
+ if(message)
+ var/sane_message = sanitize(message)
+ gem.use_emote(sane_message, src)
+
+// Allows the captured owner to transfer themselves to valid nearby objects
+/mob/living/carbon/brain/caught_soul/vore/proc/transfer_self()
+ set name = "Transfer Self"
+ set desc = "Transfer youself while being in your own soulcatcher into a nearby Sleevemate or MMI."
+ set category = "Soulcatcher"
+
+ if(eyeobj)
+ to_chat(src, span_warning("You can't do that while SR projecting!"))
+ return
+ if(gem.own_mind != mind)
+ to_chat(src, span_warning("You aren't in your own soulcatcher!"))
+ return
+
+ var/list/valid_objects = gem.find_transfer_objects()
+ if(!valid_objects || !valid_objects.len)
+ return
+
+ var/obj/target = tgui_input_list(src, "Select where you want to store your own mind into.", "Mind Transfer Target", valid_objects)
+
+ gem.transfer_mob_selector(src, target)
+
+// Allows the owner to reenter the body after being caught or having given away control
+/mob/living/carbon/brain/caught_soul/vore/proc/reenter_body()
+ set name = "Re-enter Body"
+ set desc = "Return to your body after self capturing."
+ set category = "Soulcatcher"
+
+ if(eyeobj)
+ to_chat(src, span_warning("You can't do that while SR projecting!"))
+ return
+ gem.return_to_body(mind)
diff --git a/code/modules/vore/eating/soulcatcher_observer.dm b/code/modules/vore/eating/soulcatcher_observer.dm
new file mode 100644
index 00000000000..6b0580ab40a
--- /dev/null
+++ b/code/modules/vore/eating/soulcatcher_observer.dm
@@ -0,0 +1,52 @@
+/mob/observer/dead/verb/soulcatcherjoin()
+ set category = "Ghost.Join"
+ set name = "Join Into Soulcatcher(Vore)"
+ set desc = "Select a player with enabled Soulcatcher to join."
+
+ var/list/valid_players = list()
+ for(var/mob/player in player_list)
+ if(player.soulgem?.flag_check(SOULGEM_ACTIVE | SOULGEM_CATCHING_GHOSTS, TRUE))
+ valid_players += player
+
+ if(!valid_players.len)
+ to_chat(src, span_warning("No valid players found."))
+ return
+
+ var/picked = tgui_input_list(usr, "Pick a friend with enabled Soulcatcher to join into. Harrass strangers, get banned.","Select a player", valid_players)
+
+ if(!picked)
+ return
+
+ if(!ismob(picked))
+ to_chat(src, span_warning("Target is no mob."))
+ return
+
+ var/mob/M = picked
+
+ var/obj/soulgem/gem = M.soulgem
+
+ if(!gem?.flag_check(SOULGEM_ACTIVE))
+ to_chat(src, span_warning("[M] has no enabled Soulcatcher."))
+ return
+
+ var/req_time = world.time
+ gem.notify_holder("Transient mindstate detected, analyzing...")
+ sleep(15) //So if they are typing they get interrupted by sound and message, and don't type over the box
+ if(tgui_alert(M,"[src.name] wants to join into your Soulcatcher.","Soulcatcher Request",list("Deny","Allow"), timeout=1 MINUTES) != "Allow")
+ to_chat(src, span_warning("[M] has denied your request."))
+ return
+
+ if((world.time - req_time) > 1 MINUTES)
+ to_chat(M, span_warning("The request had already expired. (1 minute waiting max)"))
+ return
+
+ //Final check since we waited for input a couple times.
+ if(M && src && src.key && !M.stat && gem?.flag_check(SOULGEM_ACTIVE | SOULGEM_CATCHING_GHOSTS, TRUE))
+ if(!mind) //No mind yet, aka haven't played in this round.
+ mind = new(key)
+
+ mind.name = name
+ mind.current = src
+ mind.active = TRUE
+
+ gem.catch_mob(src) //This will result in us being deleted so...
diff --git a/code/modules/vore/eating/stumblevore_vr.dm b/code/modules/vore/eating/stumblevore_vr.dm
index 6f52634fad7..67b8670db6e 100644
--- a/code/modules/vore/eating/stumblevore_vr.dm
+++ b/code/modules/vore/eating/stumblevore_vr.dm
@@ -38,21 +38,28 @@
if(CanStumbleVore(M))
visible_message(span_vwarning("[M] flops carelessly into [src]!"))
perform_the_nom(src,M,src,src.vore_selected,1)
- else if(M.CanStumbleVore(src))
+ return
+
+ if(M.CanStumbleVore(src))
visible_message(span_vwarning("[M] flops carelessly into [src]!"))
perform_the_nom(M,src,M,M.vore_selected,1)
- else if(istype(S) && S.species.lightweight == 1)
+ return
+
+ if(istype(S) && S.species.lightweight == 1)
visible_message(span_vwarning("[M] carelessly bowls [src] over!"))
M.forceMove(get_turf(src))
M.apply_damage(0.5, BRUTE)
Weaken(4)
stop_flying()
apply_damage(0.5, BRUTE)
- else if(round(weight) > 474)
+ return
+
+ if(round(weight) > 474)
var/throwtarget = get_edge_target_turf(M, reverse_direction(M.dir))
visible_message(span_vwarning("[M] bounces backwards off of [src]'s plush body!"))
M.throw_at(throwtarget, 2, 1)
- else
- visible_message(span_vwarning("[M] trips over [src]!"))
- M.forceMove(get_turf(src))
- M.apply_damage(1, BRUTE)
+ return
+
+ visible_message(span_vwarning("[M] trips over [src]!"))
+ M.forceMove(get_turf(src))
+ M.apply_damage(1, BRUTE)
diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm
index 9b6c979d3a2..b191271b493 100644
--- a/code/modules/vore/eating/vore_vr.dm
+++ b/code/modules/vore/eating/vore_vr.dm
@@ -47,7 +47,6 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
var/feeding = TRUE
var/can_be_drop_prey = FALSE
var/can_be_drop_pred = FALSE
- var/allow_inbelly_spawning = FALSE
var/allow_spontaneous_tf = FALSE
var/digest_leave_remains = FALSE
var/allowmobvore = TRUE
@@ -62,6 +61,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
var/slip_vore = TRUE
var/throw_vore = TRUE
var/food_vore = TRUE
+ var/consume_liquid_belly = FALSE //starting off because if someone is into that, they'll toggle it first time they get the error. Otherway around would be more pref breaky.
var/digest_pain = TRUE
@@ -69,11 +69,29 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
var/show_vore_fx = TRUE
var/step_mechanics_pref = FALSE
var/pickup_pref = TRUE
-
var/vore_sprite_color = list("stomach" = "#000", "taur belly" = "#000")
var/vore_sprite_multiply = list("stomach" = FALSE, "taur belly" = FALSE)
var/allow_mind_transfer = FALSE
+ var/phase_vore = TRUE
+ var/noisy_full = FALSE
+ var/receive_reagents = FALSE
+ var/give_reagents = FALSE
+ var/apply_reagents = TRUE
+ var/latejoin_vore = FALSE
+ var/latejoin_prey = FALSE
+ var/autotransferable = TRUE
+ var/strip_pref = FALSE
+ var/no_latejoin_vore_warning = FALSE // Only load, when... no_latejoin_vore_warning_persists
+ var/no_latejoin_prey_warning = FALSE // Only load, when... no_latejoin_vore_warning_persists
+ var/no_latejoin_vore_warning_time = 15 // Only load, when... no_latejoin_vore_warning_persists
+ var/no_latejoin_prey_warning_time = 15 // Only load, when... no_latejoin_vore_warning_persists
+ var/no_latejoin_vore_warning_persists = FALSE
+ var/no_latejoin_prey_warning_persists = FALSE
+ var/belly_rub_target = null
+ var/soulcatcher_pref_flags = 0
+ var/list/soulcatcher_prefs = list()
+
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
var/vore_smell = "nothing in particular"
@@ -187,7 +205,6 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
show_vore_fx = json_from_file["show_vore_fx"]
can_be_drop_prey = json_from_file["can_be_drop_prey"]
can_be_drop_pred = json_from_file["can_be_drop_pred"]
- allow_inbelly_spawning = json_from_file["allow_inbelly_spawning"]
allow_spontaneous_tf = json_from_file["allow_spontaneous_tf"]
step_mechanics_pref = json_from_file["step_mechanics_pref"]
pickup_pref = json_from_file["pickup_pref"]
@@ -196,6 +213,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
slip_vore = json_from_file["slip_vore"]
food_vore = json_from_file["food_vore"]
throw_vore = json_from_file["throw_vore"]
+ consume_liquid_belly = json_from_file["consume_liquid_belly"]
stumble_vore = json_from_file["stumble_vore"]
digest_pain = json_from_file["digest_pain"]
nutrition_message_visible = json_from_file["nutrition_message_visible"]
@@ -207,6 +225,29 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
vore_sprite_color = json_from_file["vore_sprite_color"]
allow_mind_transfer = json_from_file["allow_mind_transfer"]
+ phase_vore = json_from_file["phase_vore"]
+ latejoin_vore = json_from_file["latejoin_vore"]
+ latejoin_prey = json_from_file["latejoin_prey"]
+ receive_reagents = json_from_file["receive_reagents"]
+ noisy_full = json_from_file["noisy_full"]
+ give_reagents = json_from_file["give_reagents"]
+ apply_reagents = json_from_file["apply_reagents"]
+ autotransferable = json_from_file["autotransferable"]
+ vore_sprite_multiply = json_from_file["vore_sprite_multiply"]
+ strip_pref = json_from_file["strip_pref"]
+
+ no_latejoin_vore_warning_persists = json_from_file["no_latejoin_vore_warning_persists"]
+ if(no_latejoin_vore_warning_persists)
+ no_latejoin_vore_warning = json_from_file["no_latejoin_vore_warning"]
+ no_latejoin_vore_warning_time = json_from_file["no_latejoin_vore_warning_time"]
+ no_latejoin_prey_warning_persists = json_from_file["no_latejoin_prey_warning_persists"]
+ if(no_latejoin_prey_warning_persists)
+ no_latejoin_prey_warning = json_from_file["no_latejoin_prey_warning"]
+ no_latejoin_prey_warning_time = json_from_file["no_latejoin_prey_warning_time"]
+ belly_rub_target = json_from_file["belly_rub_target"]
+ soulcatcher_pref_flags = json_from_file["soulcatcher_pref_flags"]
+ soulcatcher_prefs = json_from_file["soulcatcher_prefs"]
+
//Quick sanitize
if(isnull(digestable))
digestable = TRUE
@@ -234,8 +275,6 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
can_be_drop_prey = FALSE
if(isnull(can_be_drop_pred))
can_be_drop_pred = FALSE
- if(isnull(allow_inbelly_spawning))
- allow_inbelly_spawning = FALSE
if(isnull(allow_spontaneous_tf))
allow_spontaneous_tf = FALSE
if(isnull(step_mechanics_pref))
@@ -254,6 +293,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
stumble_vore = TRUE
if(isnull(food_vore))
food_vore = TRUE
+ if(isnull(consume_liquid_belly))
+ consume_liquid_belly = FALSE
if(isnull(digest_pain))
digest_pain = TRUE
if(isnull(nutrition_message_visible))
@@ -298,6 +339,44 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
vore_sprite_color = list("stomach" = "#000", "taur belly" = "#000")
if(isnull(allow_mind_transfer))
allow_mind_transfer = FALSE
+
+ if(isnull(phase_vore))
+ phase_vore = TRUE
+ if(isnull(latejoin_vore))
+ latejoin_vore = FALSE
+ if(isnull(latejoin_prey))
+ latejoin_prey = FALSE
+ if(isnull(receive_reagents))
+ receive_reagents = FALSE
+ if(isnull(give_reagents))
+ give_reagents = FALSE
+ if(isnull(apply_reagents))
+ apply_reagents = TRUE
+ if(isnull(noisy_full))
+ noisy_full = FALSE
+ if(isnull(autotransferable))
+ autotransferable = TRUE
+ if(isnull(vore_sprite_multiply))
+ vore_sprite_multiply = list("stomach" = FALSE, "taur belly" = FALSE)
+ if(isnull(strip_pref))
+ strip_pref = TRUE
+ if(isnull(no_latejoin_vore_warning))
+ no_latejoin_vore_warning = FALSE
+ if(isnull(no_latejoin_prey_warning))
+ no_latejoin_prey_warning = FALSE
+ if(isnull(no_latejoin_vore_warning_time))
+ no_latejoin_vore_warning_time = 30
+ if(isnull(no_latejoin_prey_warning_time))
+ no_latejoin_prey_warning_time = 30
+ if(isnull(no_latejoin_vore_warning_persists))
+ no_latejoin_vore_warning_persists = FALSE
+ if(isnull(no_latejoin_prey_warning_persists))
+ no_latejoin_prey_warning_persists = FALSE
+ if(isnull(soulcatcher_pref_flags))
+ soulcatcher_pref_flags = 0
+ if(isnull(soulcatcher_prefs))
+ soulcatcher_prefs = list()
+
return TRUE
/datum/vore_preferences/proc/save_vore()
@@ -318,29 +397,47 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
"vore_smell" = vore_smell,
"permit_healbelly" = permit_healbelly,
"noisy" = noisy,
+ "noisy_full" = noisy_full,
"selective_preference" = selective_preference,
"show_vore_fx" = show_vore_fx,
"can_be_drop_prey" = can_be_drop_prey,
"can_be_drop_pred" = can_be_drop_pred,
- "allow_inbelly_spawning"= allow_inbelly_spawning,
+ "latejoin_vore" = latejoin_vore,
+ "latejoin_prey" = latejoin_prey,
"allow_spontaneous_tf" = allow_spontaneous_tf,
"step_mechanics_pref" = step_mechanics_pref,
"pickup_pref" = pickup_pref,
"belly_prefs" = belly_prefs,
+ "receive_reagents" = receive_reagents,
+ "give_reagents" = give_reagents,
+ "apply_reagents" = apply_reagents,
+ "autotransferable" = autotransferable,
"drop_vore" = drop_vore,
"slip_vore" = slip_vore,
"stumble_vore" = stumble_vore,
"throw_vore" = throw_vore,
"allow_mind_transfer" = allow_mind_transfer,
- "food_vore" = food_vore,
+ "phase_vore" = phase_vore,
+ "consume_liquid_belly" = consume_liquid_belly,
"digest_pain" = digest_pain,
"nutrition_message_visible" = nutrition_message_visible,
"nutrition_messages" = nutrition_messages,
"weight_message_visible" = weight_message_visible,
"weight_messages" = weight_messages,
"eating_privacy_global" = eating_privacy_global,
+ "vore_sprite_color" = vore_sprite_color,
"allow_mimicry" = allow_mimicry,
- "vore_sprite_color" = vore_sprite_color,
+ "vore_sprite_multiply" = vore_sprite_multiply,
+ "strip_pref" = strip_pref,
+ "no_latejoin_vore_warning" = no_latejoin_vore_warning,
+ "no_latejoin_prey_warning" = no_latejoin_prey_warning,
+ "no_latejoin_vore_warning_time" = no_latejoin_vore_warning_time,
+ "no_latejoin_prey_warning_time" = no_latejoin_prey_warning_time,
+ "no_latejoin_vore_warning_persists" = no_latejoin_vore_warning_persists,
+ "no_latejoin_prey_warning_persists" = no_latejoin_prey_warning_persists,
+ "belly_rub_target" = belly_rub_target,
+ "soulcatcher_pref_flags" = soulcatcher_pref_flags,
+ "soulcatcher_prefs" = soulcatcher_prefs
)
//List to JSON
diff --git a/code/modules/vore/eating/vorepanel_prefs.dm b/code/modules/vore/eating/vorepanel_prefs.dm
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm
index 9809b7842ff..054cc4a2a7f 100644
--- a/code/modules/vore/eating/vorepanel_vr.dm
+++ b/code/modules/vore/eating/vorepanel_vr.dm
@@ -2,20 +2,8 @@
// Vore management panel for players
//
-//INSERT COLORIZE-ONLY STOMACHS HERE
-var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
- "a_synth_flesh_mono_hole",
- "a_anim_belly",
- "multi_layer_test_tummy",
- "gematically_angular",
- "entrance_to_a_tumby",
- "passage_to_a_tumby",
- "destination_tumby",
- "destination_tumby_fluidless",
- "post_tumby_passage",
- "post_tumby_passage_fluidless",
- "not_quite_tumby",
- "could_it_be_a_tumby")
+#define VORE_RESIZE_COST 125
+#define STATION_PREF_NAME "Virgo"
/mob
var/datum/vore_look/vorePanel
@@ -48,6 +36,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
var/mob/host // Note, we do this in case we ever want to allow people to view others vore panels
var/unsaved_changes = FALSE
var/show_pictures = TRUE
+ var/icon_overflow = FALSE
+ var/max_icon_content = 21 //Contents above this disable icon mode. 21 for nice 3 rows to fill the default panel window.
/datum/vore_look/New(mob/new_host)
if(istype(new_host))
@@ -61,7 +51,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
/datum/vore_look/ui_assets(mob/user)
. = ..()
. += get_asset_datum(/datum/asset/spritesheet/vore)
- . += get_asset_datum(/datum/asset/spritesheet/vore_colorized) //Either this isn't working or my cache is corrupted and won't show them.
+ . += get_asset_datum(/datum/asset/spritesheet/vore_fixed) //Either this isn't working or my cache is corrupted and won't show them.
/datum/vore_look/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -89,7 +79,11 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
key = "[target.type]"
else if(ismob(target))
var/mob/M = target
- key = "\ref[target][M.real_name]"
+ if(istype(M,/mob/living/simple_mob)) //not generating unique icons for every simplemob(number)
+ var/mob/living/simple_mob/S = M
+ key = "[S.icon_living]"
+ else
+ key = "\ref[target][M.real_name]"
if(nom_icons[key])
. = nom_icons[key]
else
@@ -122,8 +116,14 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
data["unsaved_changes"] = unsaved_changes
data["show_pictures"] = show_pictures
+ data["icon_overflow"] = icon_overflow
var/atom/hostloc = host.loc
+ //Allow VorePanel to show pred belly details even while indirectly inside
+ if(istype(host, /mob/living))
+ var/mob/living/H = host
+ hostloc = H.surrounding_belly()
+ //End of indirect vorefx additions
var/list/inside = list()
if(isbelly(hostloc))
var/obj/belly/inside_belly = hostloc
@@ -145,6 +145,9 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"desc" = inside_desc,
"pred" = pred,
"ref" = "\ref[inside_belly]",
+ "liq_lvl" = inside_belly.reagents.total_volume,
+ "liq_reagent_type" = inside_belly.reagent_chosen,
+ "liuq_name" = inside_belly.reagent_name,
)
var/list/inside_contents = list()
@@ -159,8 +162,12 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"ref" = "\ref[O]",
"outside" = FALSE,
)
- if(show_pictures)
- info["icon"] = cached_nom_icon(O)
+ if(show_pictures) //disables icon mode
+ if(inside_belly.contents.len <= max_icon_content)
+ icon_overflow = FALSE
+ info["icon"] = cached_nom_icon(O)
+ else
+ icon_overflow = TRUE
if(isliving(O))
var/mob/living/M = O
info["stat"] = M.stat
@@ -211,7 +218,13 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"release_sound" = selected.release_sound,
// "messages" // TODO
"can_taste" = selected.can_taste,
+ "is_feedable" = selected.is_feedable,
"egg_type" = selected.egg_type,
+ "egg_name" = selected.egg_name,
+ "egg_size" = selected.egg_size,
+ "recycling" = selected.recycling,
+ "storing_nutrition" = selected.storing_nutrition,
+ "entrance_logs" = selected.entrance_logs,
"nutrition_percent" = selected.nutrition_percent,
"digest_brute" = selected.digest_brute,
"digest_burn" = selected.digest_burn,
@@ -228,10 +241,6 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"nutrition_ex" = host.nutrition_message_visible,
"weight_ex" = host.weight_message_visible,
"belly_fullscreen" = selected.belly_fullscreen,
- "belly_fullscreen_color" = selected.belly_fullscreen_color,
- "belly_fullscreen_color_secondary" = selected.belly_fullscreen_color_secondary,
- "belly_fullscreen_color_trinary" = selected.belly_fullscreen_color_trinary,
- "colorization_enabled" = selected.colorization_enabled,
"eating_privacy_local" = selected.eating_privacy_local,
"silicon_belly_overlay_preference" = selected.silicon_belly_overlay_preference,
"belly_mob_mult" = selected.belly_mob_mult,
@@ -257,7 +266,37 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"tail_extra_overlay2" = selected.tail_extra_overlay2,
"undergarment_chosen" = selected.undergarment_chosen,
"undergarment_if_none" = selected.undergarment_if_none || "None",
- "undergarment_color" = selected.undergarment_color
+ "undergarment_color" = selected.undergarment_color,
+ "belly_fullscreen_color" = selected.belly_fullscreen_color,
+ "belly_fullscreen_color2" = selected.belly_fullscreen_color2,
+ "belly_fullscreen_color3" = selected.belly_fullscreen_color3,
+ "belly_fullscreen_color4" = selected.belly_fullscreen_color4,
+ "belly_fullscreen_alpha" = selected.belly_fullscreen_alpha,
+ "colorization_enabled" = selected.colorization_enabled,
+ "custom_reagentcolor" = selected.custom_reagentcolor,
+ "custom_reagentalpha" = selected.custom_reagentalpha,
+ "liquid_overlay" = selected.liquid_overlay,
+ "max_liquid_level" = selected.max_liquid_level,
+ "reagent_touches" = selected.reagent_touches,
+ "mush_overlay" = selected.mush_overlay,
+ "mush_color" = selected.mush_color,
+ "mush_alpha" = selected.mush_alpha,
+ "max_mush" = selected.max_mush,
+ "min_mush" = selected.min_mush,
+ "item_mush_val" = selected.item_mush_val,
+ "metabolism_overlay" = selected.metabolism_overlay,
+ "metabolism_mush_ratio" = selected.metabolism_mush_ratio,
+ "max_ingested" = selected.max_ingested,
+ "custom_ingested_color" = selected.custom_ingested_color,
+ "custom_ingested_alpha" = selected.custom_ingested_alpha,
+ "vorespawn_blacklist" = selected.vorespawn_blacklist,
+ "vorespawn_whitelist" = selected.vorespawn_whitelist,
+ "vorespawn_absorbed" = (global_flag_check(selected.vorespawn_absorbed, VS_FLAG_ABSORB_YES) + global_flag_check(selected.vorespawn_absorbed, VS_FLAG_ABSORB_PREY)),
+ "sound_volume" = selected.sound_volume,
+ "noise_freq" = selected.noise_freq,
+ "item_digest_logs" = selected.item_digest_logs,
+ "private_struggle" = selected.private_struggle,
+ //"marking_to_add" = selected.marking_to_add
)
var/list/addons = list()
@@ -274,6 +313,11 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
selected_list["egg_type"] = selected.egg_type
+ selected_list["egg_name"] = selected.egg_name
+ selected_list["egg_size"] = selected.egg_size
+ selected_list["recycling"] = selected.recycling
+ selected_list["storing_nutrition"] = selected.storing_nutrition
+ selected_list["item_digest_logs"] = selected.item_digest_logs
selected_list["contaminates"] = selected.contaminates
selected_list["contaminate_flavor"] = null
selected_list["contaminate_color"] = null
@@ -293,24 +337,74 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
selected_list["interacts"]["transferlocation_secondary"] = selected.transferlocation_secondary
selected_list["interacts"]["absorbchance"] = selected.absorbchance
selected_list["interacts"]["digestchance"] = selected.digestchance
+ selected_list["interacts"]["belchchance"] = selected.belchchance
+
+ selected_list["autotransfer_enabled"] = selected.autotransfer_enabled
+ selected_list["autotransfer"] = list()
+ if(selected.autotransfer_enabled)
+ selected_list["autotransfer"]["autotransferchance"] = selected.autotransferchance
+ selected_list["autotransfer"]["autotransferwait"] = selected.autotransferwait
+ selected_list["autotransfer"]["autotransferlocation"] = selected.autotransferlocation
+ selected_list["autotransfer"]["autotransferextralocation"] = selected.autotransferextralocation
+ selected_list["autotransfer"]["autotransferchance_secondary"] = selected.autotransferchance_secondary
+ selected_list["autotransfer"]["autotransferlocation_secondary"] = selected.autotransferlocation_secondary
+ selected_list["autotransfer"]["autotransferextralocation_secondary"] = selected.autotransferextralocation_secondary
+ selected_list["autotransfer"]["autotransfer_min_amount"] = selected.autotransfer_min_amount
+ selected_list["autotransfer"]["autotransfer_max_amount"] = selected.autotransfer_max_amount
+ //auto-transfer flags
+ var/list/at_whitelist = list()
+ for(var/flag_name in selected.autotransfer_flags_list)
+ if(selected.autotransfer_whitelist & selected.autotransfer_flags_list[flag_name])
+ at_whitelist.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_whitelist"] = at_whitelist
+ var/list/at_blacklist = list()
+ for(var/flag_name in selected.autotransfer_flags_list)
+ if(selected.autotransfer_blacklist & selected.autotransfer_flags_list[flag_name])
+ at_blacklist.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_blacklist"] = at_blacklist
+ var/list/at_whitelist_items = list()
+ for(var/flag_name in selected.autotransfer_flags_list_items)
+ if(selected.autotransfer_whitelist_items & selected.autotransfer_flags_list_items[flag_name])
+ at_whitelist_items.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_whitelist_items"] = at_whitelist_items
+ var/list/at_blacklist_items = list()
+ for(var/flag_name in selected.autotransfer_flags_list_items)
+ if(selected.autotransfer_blacklist_items & selected.autotransfer_flags_list_items[flag_name])
+ at_blacklist_items.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_blacklist_items"] = at_blacklist_items
+ var/list/at_secondary_whitelist = list()
+ for(var/flag_name in selected.autotransfer_flags_list)
+ if(selected.autotransfer_secondary_whitelist & selected.autotransfer_flags_list[flag_name])
+ at_secondary_whitelist.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_secondary_whitelist"] = at_secondary_whitelist
+ var/list/at_secondary_blacklist = list()
+ for(var/flag_name in selected.autotransfer_flags_list)
+ if(selected.autotransfer_secondary_blacklist & selected.autotransfer_flags_list[flag_name])
+ at_secondary_blacklist.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_secondary_blacklist"] = at_secondary_blacklist
+ var/list/at_secondary_whitelist_items = list()
+ for(var/flag_name in selected.autotransfer_flags_list_items)
+ if(selected.autotransfer_secondary_whitelist_items & selected.autotransfer_flags_list_items[flag_name])
+ at_secondary_whitelist_items.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_secondary_whitelist_items"] = at_secondary_whitelist_items
+ var/list/at_secondary_blacklist_items = list()
+ for(var/flag_name in selected.autotransfer_flags_list_items)
+ if(selected.autotransfer_secondary_blacklist_items & selected.autotransfer_flags_list_items[flag_name])
+ at_secondary_blacklist_items.Add(flag_name)
+ selected_list["autotransfer"]["autotransfer_secondary_blacklist_items"] = at_secondary_blacklist_items
selected_list["disable_hud"] = selected.disable_hud
selected_list["colorization_enabled"] = selected.colorization_enabled
selected_list["belly_fullscreen_color"] = selected.belly_fullscreen_color
- selected_list["belly_fullscreen_color_secondary"] = selected.belly_fullscreen_color_secondary
- selected_list["belly_fullscreen_color_trinary"] = selected.belly_fullscreen_color_trinary
+ selected_list["belly_fullscreen_color2"] = selected.belly_fullscreen_color2
+ selected_list["belly_fullscreen_color3"] = selected.belly_fullscreen_color3
+ selected_list["belly_fullscreen_color4"] = selected.belly_fullscreen_color4
+ selected_list["belly_fullscreen_alpha"] = selected.belly_fullscreen_alpha
if(selected.colorization_enabled)
- selected_list["possible_fullscreens"] = icon_states('icons/mob/screen_full_colorized_vore.dmi') //Makes any icons inside of here selectable.
+ selected_list["possible_fullscreens"] = icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable.
else
- selected_list["possible_fullscreens"] = icon_states('icons/mob/screen_full_vore.dmi') //Where all stomachs - colorable and not - are stored.
- //INSERT COLORIZE-ONLY STOMACHS HERE.
- //This manually removed color-only stomachs from the above list.
- //For some reason, colorized stomachs have to be added to both colorized_vore(to be selected) and full_vore (to show the preview in tgui)
- //Why? I have no flipping clue. As you can see above, vore_colorized is included in the assets but isn't working. It makes no sense.
- //I can only imagine this is a BYOND/TGUI issue with the cache. If you can figure out how to fix this and make it so you only need to
- //include things in full_colorized_vore, that would be great. For now, this is the only workaround that I could get to work.
- selected_list["possible_fullscreens"] -= belly_colorable_only_fullscreens
+ selected_list["possible_fullscreens"] = icon_states('icons/mob/screen_full_vore.dmi') //Non colorable
var/list/selected_contents = list()
for(var/O in selected)
@@ -321,8 +415,13 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"ref" = "\ref[O]",
"outside" = TRUE,
)
- if(show_pictures)
- info["icon"] = cached_nom_icon(O)
+ if(show_pictures) //disables icon mode
+ if(selected.contents.len <= max_icon_content)
+ icon_overflow = FALSE
+ info["icon"] = cached_nom_icon(O)
+ else
+ icon_overflow = TRUE
+
if(isliving(O))
var/mob/living/M = O
info["stat"] = M.stat
@@ -331,6 +430,55 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
selected_contents.Add(list(info))
selected_list["contents"] = selected_contents
+ // liquid belly options
+ selected_list["show_liq"] = selected.show_liquids
+ selected_list["liq_interacts"] = list()
+ if(selected.show_liquids)
+ selected_list["liq_interacts"]["liq_reagent_gen"] = selected.reagentbellymode
+ selected_list["liq_interacts"]["liq_reagent_type"] = selected.reagent_chosen
+ selected_list["liq_interacts"]["liq_reagent_name"] = selected.reagent_name
+ selected_list["liq_interacts"]["liq_reagent_transfer_verb"] = selected.reagent_transfer_verb
+ selected_list["liq_interacts"]["liq_reagent_nutri_rate"] = selected.gen_time
+ selected_list["liq_interacts"]["liq_reagent_capacity"] = selected.custom_max_volume
+ selected_list["liq_interacts"]["liq_sloshing"] = selected.vorefootsteps_sounds
+ selected_list["liq_interacts"]["liq_reagent_addons"] = list()
+ for(var/flag_name in selected.reagent_mode_flag_list)
+ if(selected.reagent_mode_flags & selected.reagent_mode_flag_list[flag_name])
+ var/list/selected_list_member = selected_list["liq_interacts"]["liq_reagent_addons"]
+ ASSERT(islist(selected_list_member))
+ selected_list_member.Add(flag_name)
+ selected_list["liq_interacts"]["custom_reagentcolor"] = selected.custom_reagentcolor ? selected.custom_reagentcolor : selected.reagentcolor
+ selected_list["liq_interacts"]["custom_reagentalpha"] = selected.custom_reagentalpha ? selected.custom_reagentalpha : "Default"
+ selected_list["liq_interacts"]["liquid_overlay"] = selected.liquid_overlay
+ selected_list["liq_interacts"]["max_liquid_level"] = selected.max_liquid_level
+ selected_list["liq_interacts"]["reagent_touches"] = selected.reagent_touches
+ selected_list["liq_interacts"]["mush_overlay"] = selected.mush_overlay
+ selected_list["liq_interacts"]["mush_color"] = selected.mush_color
+ selected_list["liq_interacts"]["mush_alpha"] = selected.mush_alpha
+ selected_list["liq_interacts"]["max_mush"] = selected.max_mush
+ selected_list["liq_interacts"]["min_mush"] = selected.min_mush
+ selected_list["liq_interacts"]["item_mush_val"] = selected.item_mush_val
+ selected_list["liq_interacts"]["metabolism_overlay"] = selected.metabolism_overlay
+ selected_list["liq_interacts"]["metabolism_mush_ratio"] = selected.metabolism_mush_ratio
+ selected_list["liq_interacts"]["max_ingested"] = selected.max_ingested
+ selected_list["liq_interacts"]["custom_ingested_color"] = selected.custom_ingested_color ? selected.custom_ingested_color : "#3f6088"
+ selected_list["liq_interacts"]["custom_ingested_alpha"] = selected.custom_ingested_alpha
+
+ selected_list["show_liq_fullness"] = selected.show_fullness_messages
+ selected_list["liq_messages"] = list()
+ if(selected.show_fullness_messages)
+ selected_list["liq_messages"]["liq_msg_toggle1"] = selected.liquid_fullness1_messages
+ selected_list["liq_messages"]["liq_msg_toggle2"] = selected.liquid_fullness2_messages
+ selected_list["liq_messages"]["liq_msg_toggle3"] = selected.liquid_fullness3_messages
+ selected_list["liq_messages"]["liq_msg_toggle4"] = selected.liquid_fullness4_messages
+ selected_list["liq_messages"]["liq_msg_toggle5"] = selected.liquid_fullness5_messages
+
+ selected_list["liq_messages"]["liq_msg1"] = selected.liquid_fullness1_messages
+ selected_list["liq_messages"]["liq_msg2"] = selected.liquid_fullness2_messages
+ selected_list["liq_messages"]["liq_msg3"] = selected.liquid_fullness3_messages
+ selected_list["liq_messages"]["liq_msg4"] = selected.liquid_fullness4_messages
+ selected_list["liq_messages"]["liq_msg5"] = selected.liquid_fullness5_messages
+
data["selected"] = selected_list
data["prefs"] = list(
"digestable" = host.digestable,
@@ -344,17 +492,35 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"show_vore_fx" = host.show_vore_fx,
"can_be_drop_prey" = host.can_be_drop_prey,
"can_be_drop_pred" = host.can_be_drop_pred,
- "allow_inbelly_spawning" = host.allow_inbelly_spawning,
+ "latejoin_vore" = host.latejoin_vore,
+ "latejoin_prey" = host.latejoin_prey,
+ "no_spawnpred_warning" = host.no_latejoin_vore_warning,
+ "no_spawnprey_warning" = host.no_latejoin_prey_warning,
+ "no_spawnpred_warning_time" = host.no_latejoin_vore_warning_time,
+ "no_spawnprey_warning_time" = host.no_latejoin_prey_warning_time,
+ "no_spawnpred_warning_save" = host.no_latejoin_vore_warning_persists,
+ "no_spawnprey_warning_save" = host.no_latejoin_prey_warning_persists,
"allow_spontaneous_tf" = host.allow_spontaneous_tf,
"step_mechanics_active" = host.step_mechanics_pref,
"pickup_mechanics_active" = host.pickup_pref,
+ "strip_mechanics_active" = host.strip_pref,
"noisy" = host.noisy,
+ //liquid belly prefs
+ "liq_rec" = host.receive_reagents,
+ "liq_giv" = host.give_reagents,
+ "liq_apply" = host.apply_reagents,
+ "autotransferable" = host.autotransferable,
+ "noisy_full" = host.noisy_full, //Belching while full
+ "selective_active" = host.selective_preference, //Reveal active selective mode in prefs
+
"allow_mind_transfer" = host.allow_mind_transfer,
"drop_vore" = host.drop_vore,
"slip_vore" = host.slip_vore,
"stumble_vore" = host.stumble_vore,
"throw_vore" = host.throw_vore,
+ "phase_vore" = host.phase_vore,
"food_vore" = host.food_vore,
+ "consume_liquid_belly" = host.consume_liquid_belly,
"digest_pain" = host.digest_pain,
"nutrition_message_visible" = host.nutrition_message_visible,
"nutrition_messages" = host.nutrition_messages,
@@ -362,6 +528,51 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
"weight_messages" = host.weight_messages,
"eating_privacy_global" = host.eating_privacy_global,
"allow_mimicry" = host.allow_mimicry,
+ // start, vore sprites
+ "belly_rub_target" = host.belly_rub_target,
+ "vore_sprite_color" = host.vore_sprite_color,
+ "vore_sprite_multiply" = host.vore_sprite_multiply,
+ //Soulcatcher
+ "soulcatcher_allow_capture" = host.soulcatcher_pref_flags & SOULCATCHER_ALLOW_CAPTURE,
+ "soulcatcher_allow_transfer" = host.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TRANSFER,
+ "soulcatcher_allow_takeover" = host.soulcatcher_pref_flags & SOULCATCHER_ALLOW_TAKEOVER,
+ "soulcatcher_allow_deletion" = (global_flag_check(host.soulcatcher_pref_flags, SOULCATCHER_ALLOW_DELETION) + global_flag_check(host.soulcatcher_pref_flags, SOULCATCHER_ALLOW_DELETION_INSTANT))
+ )
+ // Soulcatcher
+ var/list/stored_souls = list()
+ data["soulcatcher"] = null
+ if(host.soulgem)
+ data["soulcatcher"] = list()
+ for(var/soul in host.soulgem.brainmobs)
+ var/list/info = list("displayText" = "[soul]", "value" = "\ref[soul]")
+ stored_souls.Add(list(info))
+ data["soulcatcher"]["active"] = host.soulgem.flag_check(SOULGEM_ACTIVE)
+ data["soulcatcher"]["name"] = host.soulgem.name
+ data["soulcatcher"]["caught_souls"] = stored_souls
+ data["soulcatcher"]["selected_soul"] = host.soulgem.selected_soul
+ data["soulcatcher"]["selected_sfx"] = host.soulgem.linked_belly
+ data["soulcatcher"]["interior_design"] = host.soulgem.inside_flavor
+ data["soulcatcher"]["taken_over"] = host.soulgem.is_taken_over()
+ data["soulcatcher"]["catch_self"] = host.soulgem.flag_check(NIF_SC_CATCHING_ME)
+ data["soulcatcher"]["catch_prey"] = host.soulgem.flag_check(NIF_SC_CATCHING_OTHERS)
+ data["soulcatcher"]["catch_drain"] = host.soulgem.flag_check(SOULGEM_CATCHING_DRAIN)
+ data["soulcatcher"]["catch_ghost"] = host.soulgem.flag_check(SOULGEM_CATCHING_GHOSTS)
+ data["soulcatcher"]["ext_hearing"] = host.soulgem.flag_check(NIF_SC_ALLOW_EARS)
+ data["soulcatcher"]["ext_vision"] = host.soulgem.flag_check(NIF_SC_ALLOW_EYES)
+ data["soulcatcher"]["mind_backups"] = host.soulgem.flag_check(NIF_SC_BACKUPS)
+ data["soulcatcher"]["sr_projecting"] = host.soulgem.flag_check(NIF_SC_PROJECTING)
+ data["soulcatcher"]["show_vore_sfx"] = host.soulgem.flag_check(SOULGEM_SHOW_VORE_SFX)
+ data["soulcatcher"]["see_sr_projecting"] = host.soulgem.flag_check(SOULGEM_SEE_SR_SOULS)
+ var/nutri_value = 0
+ if(istype(host, /mob/living))
+ var/mob/living/H = host
+ nutri_value = H.nutrition
+ data["abilities"] = list (
+ "nutrition" = nutri_value,
+ "current_size" = host.size_multiplier,
+ "minimum_size" = host.has_large_resize_bounds() ? RESIZE_MINIMUM_DORMS : RESIZE_MINIMUM,
+ "maximum_size" = host.has_large_resize_bounds() ? RESIZE_MAXIMUM_DORMS : RESIZE_MAXIMUM,
+ "resize_cost" = VORE_RESIZE_COST
)
return data
@@ -454,9 +665,9 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(choice != "Yes, save.")
return TRUE
if(!host.save_vore_prefs())
- tgui_alert_async(ui.user, "ERROR: Virgo-specific preferences failed to save!","Error")
+ tgui_alert_async(ui.user, "ERROR: " + STATION_PREF_NAME + "-specific preferences failed to save!","Error")
else
- to_chat(ui.user, span_notice("Virgo-specific preferences saved!"))
+ to_chat(ui.user, span_notice(STATION_PREF_NAME + "-specific preferences saved!"))
unsaved_changes = FALSE
return TRUE
if("reloadprefs")
@@ -464,9 +675,9 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(alert != "Reload")
return FALSE
if(!host.apply_vore_prefs())
- tgui_alert_async(ui.user, "ERROR: Virgo-specific preferences failed to apply!","Error")
+ tgui_alert_async(ui.user, "ERROR: " + STATION_PREF_NAME + "-specific preferences failed to apply!","Error")
else
- to_chat(ui.user,span_notice("Virgo-specific preferences applied from active slot!"))
+ to_chat(ui.user,span_notice(STATION_PREF_NAME + "-specific preferences applied from active slot!"))
unsaved_changes = FALSE
return TRUE
if("loadprefsfromslot")
@@ -474,11 +685,12 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(alert != "Load")
return FALSE
if(!host.load_vore_prefs_from_slot())
- tgui_alert_async(ui.user, "ERROR: Virgo-specific preferences failed to apply!","Error")
+ tgui_alert_async(ui.user, "ERROR: Vore-specific preferences failed to apply!","Error")
else
- to_chat(ui.user,span_notice("Virgo-specific preferences applied from active slot!"))
+ to_chat(ui.user,span_notice("Vore-specific preferences applied from active slot!"))
unsaved_changes = TRUE
return TRUE
+ //"Belly HTML Export Earlyport"
if("exportpanel")
if(!ui.user)
return FALSE
@@ -530,10 +742,16 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.client.prefs_vr.can_be_drop_prey = host.can_be_drop_prey
unsaved_changes = TRUE
return TRUE
- if("toggle_allow_inbelly_spawning")
- host.allow_inbelly_spawning = !host.allow_inbelly_spawning
+ if("toggle_latejoin_vore")
+ host.latejoin_vore = !host.latejoin_vore
if(host.client.prefs_vr)
- host.client.prefs_vr.allow_inbelly_spawning = host.allow_inbelly_spawning
+ host.client.prefs_vr.latejoin_vore = host.latejoin_vore
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_latejoin_prey")
+ host.latejoin_prey = !host.latejoin_prey
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.latejoin_prey = host.latejoin_prey
unsaved_changes = TRUE
return TRUE
if("toggle_allow_spontaneous_tf")
@@ -608,6 +826,12 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.client.prefs_vr.pickup_pref = host.pickup_pref
unsaved_changes = TRUE
return TRUE
+ if("toggle_strippref")
+ host.strip_pref = !host.strip_pref
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.strip_pref = host.strip_pref
+ unsaved_changes = TRUE
+ return TRUE
if("toggle_allow_mind_transfer")
host.allow_mind_transfer = !host.allow_mind_transfer
if(host.client.prefs_vr)
@@ -624,37 +848,93 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.show_vore_fx = !host.show_vore_fx
if(host.client.prefs_vr)
host.client.prefs_vr.show_vore_fx = host.show_vore_fx
- if(!host.show_vore_fx)
+ if (isbelly(host.loc))
+ var/obj/belly/B = host.loc
+ B.vore_fx(host, TRUE)
+ else
host.clear_fullscreen("belly")
- host.clear_fullscreen("belly2")
- host.clear_fullscreen("belly3")
- host.clear_fullscreen("belly4")
- if(!host.hud_used.hud_shown)
- host.toggle_hud_vis()
+ if(!host.hud_used.hud_shown)
+ host.toggle_hud_vis()
unsaved_changes = TRUE
return TRUE
if("toggle_noisy")
host.noisy = !host.noisy
unsaved_changes = TRUE
return TRUE
+ // liquid belly code
+ if("liq_set_attribute")
+ return liq_set_attr(ui.user, params)
+ if("liq_set_messages")
+ return liq_set_msg(ui.user, params)
+ if("toggle_liq_rec")
+ host.receive_reagents = !host.receive_reagents
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.receive_reagents = host.receive_reagents
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_liq_giv")
+ host.give_reagents = !host.give_reagents
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.give_reagents = host.give_reagents
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_liq_apply")
+ host.apply_reagents = !host.apply_reagents
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.apply_reagents = host.apply_reagents
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_autotransferable")
+ host.autotransferable = !host.autotransferable
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.autotransferable = host.autotransferable
+ unsaved_changes = TRUE
+ return TRUE
+ //Belch code
+ if("toggle_noisy_full")
+ host.noisy_full = !host.noisy_full
+ unsaved_changes = TRUE
+ return TRUE
if("toggle_drop_vore")
host.drop_vore = !host.drop_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.drop_vore = host.drop_vore
unsaved_changes = TRUE
return TRUE
if("toggle_slip_vore")
host.slip_vore = !host.slip_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.slip_vore = host.slip_vore
unsaved_changes = TRUE
return TRUE
if("toggle_stumble_vore")
host.stumble_vore = !host.stumble_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.stumble_vore = host.stumble_vore
unsaved_changes = TRUE
return TRUE
if("toggle_throw_vore")
host.throw_vore = !host.throw_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.throw_vore = host.throw_vore
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_phase_vore")
+ host.phase_vore = !host.phase_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.phase_vore = host.phase_vore
unsaved_changes = TRUE
return TRUE
if("toggle_food_vore")
host.food_vore = !host.food_vore
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.food_vore = host.food_vore
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_consume_liquid_belly")
+ host.consume_liquid_belly = !host.consume_liquid_belly
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.consume_liquid_belly = host.consume_liquid_belly
unsaved_changes = TRUE
return TRUE
if("toggle_digest_pain")
@@ -691,6 +971,225 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.update_icons_body()
unsaved_changes = TRUE
return TRUE
+ //vore sprites color
+ if("set_belly_rub")
+ host.belly_rub_target = tgui_input_list(ui.user, "Which belly would you prefer to be rubbed?","Select Target", host.vore_organs)
+ if(!(host.belly_rub_target))
+ host.belly_rub_target = null
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.belly_rub_target = host.belly_rub_target
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_no_latejoin_vore_warning")
+ host.no_latejoin_vore_warning = !host.no_latejoin_vore_warning
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_vore_warning = host.no_latejoin_vore_warning
+ if(host.no_latejoin_vore_warning_persists)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_no_latejoin_prey_warning")
+ host.no_latejoin_prey_warning = !host.no_latejoin_prey_warning
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_prey_warning = host.no_latejoin_prey_warning
+ if(host.no_latejoin_prey_warning_persists)
+ unsaved_changes = TRUE
+ return TRUE
+ if("adjust_no_latejoin_vore_warning_time")
+ host.no_latejoin_vore_warning_time = text2num(params["new_pred_time"])
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_vore_warning_time = host.no_latejoin_vore_warning_time
+ if(host.no_latejoin_vore_warning_persists)
+ unsaved_changes = TRUE
+ return TRUE
+ if("adjust_no_latejoin_prey_warning_time")
+ host.no_latejoin_prey_warning_time = text2num(params["new_prey_time"])
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_prey_warning_time = host.no_latejoin_prey_warning_time
+ if(host.no_latejoin_prey_warning_persists)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_no_latejoin_vore_warning_persists")
+ host.no_latejoin_vore_warning_persists = !host.no_latejoin_vore_warning_persists
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_vore_warning_persists = host.no_latejoin_vore_warning_persists
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_no_latejoin_prey_warning_persists")
+ host.no_latejoin_prey_warning_persists = !host.no_latejoin_prey_warning_persists
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.no_latejoin_prey_warning_persists = host.no_latejoin_prey_warning_persists
+ unsaved_changes = TRUE
+ return TRUE
+ //Soulcatcher prefs
+ if("toggle_soulcatcher_allow_capture")
+ host.soulcatcher_pref_flags ^= SOULCATCHER_ALLOW_CAPTURE
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.soulcatcher_pref_flags = host.soulcatcher_pref_flags
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_soulcatcher_allow_transfer")
+ host.soulcatcher_pref_flags ^= SOULCATCHER_ALLOW_TRANSFER
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.soulcatcher_pref_flags = host.soulcatcher_pref_flags
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_soulcatcher_allow_takeover")
+ host.soulcatcher_pref_flags ^= SOULCATCHER_ALLOW_TAKEOVER
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.soulcatcher_pref_flags = host.soulcatcher_pref_flags
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_soulcatcher_allow_deletion")
+ var/current_number = global_flag_check(host.soulcatcher_pref_flags, SOULCATCHER_ALLOW_DELETION) + global_flag_check(host.soulcatcher_pref_flags, SOULCATCHER_ALLOW_DELETION_INSTANT)
+ switch(current_number)
+ if(0)
+ host.soulcatcher_pref_flags ^= SOULCATCHER_ALLOW_DELETION
+ if(1)
+ host.soulcatcher_pref_flags ^= SOULCATCHER_ALLOW_DELETION_INSTANT
+ if(2)
+ host.soulcatcher_pref_flags &= ~(SOULCATCHER_ALLOW_DELETION)
+ host.soulcatcher_pref_flags &= ~(SOULCATCHER_ALLOW_DELETION_INSTANT)
+ if(host.client.prefs_vr)
+ host.client.prefs_vr.soulcatcher_pref_flags = host.soulcatcher_pref_flags
+ unsaved_changes = TRUE
+ return TRUE
+ if("adjust_own_size")
+ var/new_size = text2num(params["new_mob_size"])
+ new_size = clamp(new_size, RESIZE_MINIMUM_DORMS, RESIZE_MAXIMUM_DORMS)
+ if(istype(host, /mob/living))
+ var/mob/living/H = host
+ if(H.nutrition >= VORE_RESIZE_COST)
+ H.adjust_nutrition(-VORE_RESIZE_COST)
+ H.resize(new_size, uncapped = host.has_large_resize_bounds(), ignore_prefs = TRUE)
+ return TRUE
+ //Soulcatcher functions
+ if("soulcatcher_release_all")
+ host.soulgem.release_mobs()
+ return TRUE
+ if("soulcatcher_erase_all")
+ host.soulgem.erase_mobs()
+ return TRUE
+ if("soulcatcher_release")
+ host.soulgem.release_selected()
+ return TRUE
+ if("soulcatcher_transfer")
+ host.soulgem.transfer_selected()
+ return TRUE
+ if("soulcatcher_delete")
+ host.soulgem.delete_selected()
+ return TRUE
+ if("soulcatcher_transfer_control")
+ host.soulgem.take_control_selected()
+ return TRUE
+ if("soulcatcher_release_control")
+ host.soulgem.take_control_owner()
+ return TRUE
+ if("soulcatcher_select")
+ host.soulgem.selected_soul = locate(params["selected_soul"])
+ return TRUE
+ //Soulcatcher settings
+ if("soulcatcher_toggle")
+ host.soulgem.toggle_setting(SOULGEM_ACTIVE)
+ unsaved_changes = TRUE
+ return TRUE
+ if("soulcatcher_sfx")
+ var/obj/belly = locate(params["selected_belly"])
+ if(istype(belly))
+ host.soulgem.update_linked_belly(belly)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_self_catching")
+ host.soulgem.toggle_setting(NIF_SC_CATCHING_ME)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_prey_catching")
+ host.soulgem.toggle_setting(NIF_SC_CATCHING_OTHERS)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_drain_catching")
+ host.soulgem.toggle_setting(SOULGEM_CATCHING_DRAIN)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_ghost_catching")
+ host.soulgem.toggle_setting(SOULGEM_CATCHING_GHOSTS)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_ext_hearing")
+ host.soulgem.toggle_setting(NIF_SC_ALLOW_EARS)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_ext_vision")
+ host.soulgem.toggle_setting(NIF_SC_ALLOW_EYES)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_mind_backup")
+ host.soulgem.toggle_setting(NIF_SC_BACKUPS)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_sr_projecting")
+ host.soulgem.toggle_setting(NIF_SC_PROJECTING)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_vore_sfx")
+ host.soulgem.toggle_setting(SOULGEM_SHOW_VORE_SFX)
+ unsaved_changes = TRUE
+ return TRUE
+ if("toggle_sr_vision")
+ host.soulgem.toggle_setting(SOULGEM_SEE_SR_SOULS)
+ unsaved_changes = TRUE
+ return TRUE
+ if("soulcatcher_rename")
+ var/new_name = tgui_input_text(host, "Adjust the name of your soulcatcher. Limit 60 chars.", \
+ "New Name", html_decode(host.soulgem.name), 60, prevent_enter = TRUE)
+ if(new_name)
+ unsaved_changes = TRUE
+ host.soulgem.rename(new_name)
+ return TRUE
+ if("soulcatcher_interior_design")
+ var/new_flavor = tgui_input_text(host, "Type what the prey sees after being 'caught'. This will be \
+ printed after an intro set in the capture message to the prey. If you already \
+ have prey, this will be printed to them after the transit message. Limit [MAX_MESSAGE_LEN * 2] chars.", \
+ "VR Environment", html_decode(host.soulgem.inside_flavor), MAX_MESSAGE_LEN * 2, TRUE, prevent_enter = TRUE)
+ if(new_flavor)
+ unsaved_changes = TRUE
+ host.soulgem.adjust_interior(new_flavor)
+ return TRUE
+ if("soulcatcher_capture_message")
+ var/message = tgui_input_text(host, "Type what the prey sees while being 'caught'. This will be \
+ printed before the iterior design to the prey. Limit [MAX_MESSAGE_LEN / 4] chars.", \
+ "VR Capture", html_decode(host.soulgem.capture_message), MAX_MESSAGE_LEN / 4, TRUE, prevent_enter = TRUE)
+ if(message)
+ unsaved_changes = TRUE
+ host.soulgem.set_custom_message(message, "capture")
+ return TRUE
+ if("soulcatcher_transit_message")
+ var/message = tgui_input_text(host, "Type what the prey sees when you change the interior with them already captured. \
+ Limit [MAX_MESSAGE_LEN / 4] chars.", "VR Transit", html_decode(host.soulgem.transit_message), MAX_MESSAGE_LEN / 4, TRUE, prevent_enter = TRUE)
+ if(message)
+ unsaved_changes = TRUE
+ host.soulgem.set_custom_message(message, "transit")
+ return TRUE
+ if("soulcatcher_release_message")
+ var/message = tgui_input_text(host, "Type what the prey sees when they are released. \
+ Limit [MAX_MESSAGE_LEN / 4] chars.", "VR Release", html_decode(host.soulgem.release_message), MAX_MESSAGE_LEN / 4, TRUE, prevent_enter = TRUE)
+ if(message)
+ unsaved_changes = TRUE
+ host.soulgem.set_custom_message(message, "release")
+ return TRUE
+ if("soulcatcher_transfer_message")
+ var/message = tgui_input_text(host, "Type what the prey sees when they are transfered. \
+ Limit [MAX_MESSAGE_LEN / 4] chars.", "VR Transfer", html_decode(host.soulgem.transfer_message), MAX_MESSAGE_LEN / 4, TRUE, prevent_enter = TRUE)
+ if(message)
+ unsaved_changes = TRUE
+ host.soulgem.set_custom_message(message, "transfer")
+ return TRUE
+ if("soulcatcher_delete_message")
+ var/message = tgui_input_text(host, "Type what the prey sees when they are deleted. \
+ Limit [MAX_MESSAGE_LEN / 4] chars.", "VR Transfer", html_decode(host.soulgem.delete_message), MAX_MESSAGE_LEN / 4, TRUE, prevent_enter = TRUE)
+ if(message)
+ unsaved_changes = TRUE
+ host.soulgem.set_custom_message(message, "delete")
+ return TRUE
/datum/vore_look/proc/pick_from_inside(mob/user, params)
var/atom/movable/target = locate(params["pick"])
@@ -700,11 +1199,14 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
return TRUE // Aren't here anymore, need to update menu
var/intent = "Examine"
- if(isliving(target))
- intent = tgui_alert(user, "What do you want to do to them?","Query",list("Examine","Help Out","Devour"))
+ // Only allow indirect belly viewers to examine
+ if(user in OB)
+ if(isliving(target))
+ intent = tgui_alert(user, "What do you want to do to them?","Query",list("Examine","Help Out","Devour"))
- else if(istype(target, /obj/item))
- intent = tgui_alert(user, "What do you want to do to that?","Query",list("Examine","Use Hand"))
+ else if(istype(target, /obj/item))
+ intent = tgui_alert(user, "What do you want to do to that?","Query",list("Examine","Use Hand"))
+ //End of indirect vorefx changes
switch(intent)
if("Examine") //Examine a mob inside another mob
@@ -803,6 +1305,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
for(var/atom/movable/target in host.vore_selected)
to_chat(target,span_vwarning("You're squished from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!"))
+ // Send the transfer message to indirect targets as well. Slightly different message because why not.
+ to_chat(host.vore_selected.get_belly_surrounding(target.contents),span_warning("You're squished along with [target] from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!"))
host.vore_selected.transfer_contents(target, choice, 1)
return TRUE
return
@@ -814,10 +1318,15 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(ishuman(target))
available_options += "Transform"
available_options += "Health Check"
+ // Add Reforming
+ if(isobserver(target) || istype(target,/obj/item/mmi))
+ available_options += "Reform"
+
if(isliving(target))
var/mob/living/datarget = target
if(datarget.client)
available_options += "Process"
+ available_options += "Health"
intent = tgui_input_list(user, "What would you like to do with [target]?", "Vore Pick", available_options)
switch(intent)
if("Examine")
@@ -856,6 +1365,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(!choice || !(target in host.vore_selected))
return TRUE
to_chat(target,span_vwarning("You're squished from [host]'s [lowertext(host.vore_selected.name)] to their [lowertext(choice.name)]!"))
+ // Send the transfer message to indirect targets as well. Slightly different message because why not.
+ to_chat(host.vore_selected.get_belly_surrounding(target.contents),span_warning("You're squished along with [target] from [host]'s [lowertext(host.vore_selected)] to their [lowertext(choice.name)]!"))
host.vore_selected.transfer_contents(target, choice)
@@ -915,6 +1426,161 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
V.tgui_interact(user)
return TRUE
+ // Add Reforming
+ if("Reform")
+ if(host.stat)
+ to_chat(user,span_warning("You can't do that in your state!"))
+ return TRUE
+
+ if(isobserver(target))
+ var/mob/observer/T = target
+ if(!ismob(T.body_backup) || prevent_respawns.Find(T.mind.name) || ispAI(T.body_backup))
+ to_chat(user,span_warning("They don't seem to be reformable!"))
+ return TRUE
+
+ var/accepted = tgui_alert(T, "[host] is trying to reform your body! Would you like to get reformed inside [host]'s [lowertext(host.vore_selected.name)]?", "Reforming Attempt", list("Yes", "No"))
+ if(accepted != "Yes")
+ to_chat(user,span_warning("[T] refused to be reformed!"))
+ return TRUE
+ if(!isbelly(T.loc))
+ to_chat(user,span_warning("[T] is no longer inside to be reformed!"))
+ to_chat(T,span_warning("You can't be reformed outside of a belly!"))
+ return TRUE
+
+ if(isliving(T.body_backup))
+ var/mob/living/body_backup = T.body_backup
+ if(ishuman(body_backup))
+ var/mob/living/carbon/human/H = body_backup
+ body_backup.adjustBruteLoss(-6)
+ body_backup.adjustFireLoss(-6)
+ body_backup.setOxyLoss(0)
+ if(H.isSynthetic())
+ H.adjustToxLoss(-H.getToxLoss())
+ else
+ H.adjustToxLoss(-6)
+ body_backup.adjustCloneLoss(-6)
+ body_backup.updatehealth()
+ // Now we do the check to see if we should revive...
+ var/should_proceed_with_revive = TRUE
+ var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN]
+ should_proceed_with_revive &&= !H.should_have_organ(O_BRAIN) || (brain && (!istype(brain) || brain.defib_timer > 0))
+ if(!H.isSynthetic())
+ should_proceed_with_revive &&= !(HUSK in H.mutations) && H.can_defib
+ if(should_proceed_with_revive)
+ for(var/organ_tag in H.species.has_organ)
+ var/obj/item/organ/O = H.species.has_organ[organ_tag]
+ var/vital = initial(O.vital) //check for vital organs
+ if(vital)
+ O = H.internal_organs_by_name[organ_tag]
+ if(!O || O.damage > O.max_damage)
+ should_proceed_with_revive = FALSE
+ break
+ if(should_proceed_with_revive)
+ dead_mob_list.Remove(H)
+ if((H in living_mob_list) || (H in dead_mob_list))
+ WARNING("Mob [H] was defibbed but already in the living or dead list still!")
+ living_mob_list += H
+
+ H.timeofdeath = 0
+ H.set_stat(UNCONSCIOUS) //Life() can bring them back to consciousness if it needs to.
+ H.failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
+ H.reload_fullscreen()
+ else
+ body_backup.revive()
+ body_backup.forceMove(T.loc)
+ body_backup.enabled = TRUE
+ body_backup.ajourn = 0
+ body_backup.key = T.key
+ body_backup.teleop = null
+ T.body_backup = null
+ host.vore_selected.release_specific_contents(T, TRUE)
+ if(istype(body_backup, /mob/living/simple_mob))
+ var/mob/living/simple_mob/sm = body_backup
+ if(sm.icon_rest && sm.resting)
+ sm.icon_state = sm.icon_rest
+ else
+ sm.icon_state = sm.icon_living
+ T.update_icon()
+ announce_ghost_joinleave(T.mind, 0, "They now occupy their body again.")
+ else if(istype(target,/obj/item/mmi)) // A good bit of repeated code, sure, but... cleanest way to do this.
+ var/obj/item/mmi/MMI = target
+ if(!ismob(MMI.body_backup) || !MMI.brainmob.mind || prevent_respawns.Find(MMI.brainmob.mind.name))
+ to_chat(user,span_warning("They don't seem to be reformable!"))
+ return TRUE
+ var/accepted = tgui_alert(MMI.brainmob, "[host] is trying to reform your body! Would you like to get reformed inside [host]'s [lowertext(host.vore_selected.name)]?", "Reforming Attempt", list("Yes", "No"))
+ if(accepted != "Yes")
+ to_chat(user,span_warning("[MMI] refused to be reformed!"))
+ return TRUE
+
+ if(isliving(MMI.body_backup))
+ var/mob/living/body_backup = MMI.body_backup
+ body_backup.enabled = TRUE
+ body_backup.forceMove(MMI.loc)
+ body_backup.ajourn = 0
+ body_backup.teleop = null
+ //And now installing the MMI into the body...
+ if(isrobot(body_backup)) //Just do the reverse of getting the MMI pulled out in /obj/belly/proc/digestion_death
+ var/mob/living/silicon/robot/R = body_backup
+ R.revive()
+ MMI.brainmob.mind.transfer_to(R)
+ MMI.loc = R
+ R.mmi = MMI
+ R.mmi.brainmob.add_language("Robot Talk")
+ else //reference /datum/surgery_step/robotics/install_mmi/end_step
+ var/obj/item/organ/internal/mmi_holder/holder
+ if(istype(MMI, /obj/item/mmi/digital/posibrain))
+ var/obj/item/organ/internal/mmi_holder/posibrain/holdertmp = new(body_backup, 1)
+ holder = holdertmp
+ else if(istype(MMI, /obj/item/mmi/digital/robot))
+ var/obj/item/organ/internal/mmi_holder/robot/holdertmp = new(body_backup, 1)
+ holder = holdertmp
+ else
+ holder = new(body_backup, 1)
+ body_backup.internal_organs_by_name["brain"] = holder
+ MMI.loc = holder
+ holder.stored_mmi = MMI
+ holder.update_from_mmi()
+
+ if(MMI.brainmob && MMI.brainmob.mind)
+ MMI.brainmob.mind.transfer_to(body_backup)
+ body_backup.languages = MMI.brainmob.languages
+ //You've hopefully already named yourself, so... not implementing that bit.
+ var/mob/living/carbon/human/H = body_backup
+ body_backup.adjustBruteLoss(-6, TRUE)
+ body_backup.adjustFireLoss(-6, TRUE)
+ body_backup.setOxyLoss(0)
+ H.adjustToxLoss(-H.getToxLoss())
+ body_backup.adjustCloneLoss(-6)
+ body_backup.updatehealth()
+ // Now we do the check to see if we should revive...
+ var/should_proceed_with_revive = TRUE
+ var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN]
+ should_proceed_with_revive &&= !H.should_have_organ(O_BRAIN) || (brain && brain.defib_timer > 0 )
+ if(should_proceed_with_revive)
+ for(var/organ_tag in H.species.has_organ)
+ var/obj/item/organ/O = H.species.has_organ[organ_tag]
+ var/vital = initial(O.vital) //check for vital organs
+ if(vital)
+ O = H.internal_organs_by_name[organ_tag]
+ if(!O || O.damage > O.max_damage)
+ should_proceed_with_revive = FALSE
+ break
+ if(should_proceed_with_revive)
+ dead_mob_list.Remove(H)
+ if((H in living_mob_list) || (H in dead_mob_list))
+ WARNING("Mob [H] was defibbed but already in the living or dead list still!")
+ living_mob_list += H
+
+ H.timeofdeath = 0
+ H.set_stat(UNCONSCIOUS) //Life() can bring them back to consciousness if it needs to.
+ H.failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
+ H.reload_fullscreen()
+ MMI.body_backup = null
+ return TRUE
+ if("Health")
+ var/mob/living/ourtarget = target
+ to_chat(user, span_notice("Current health reading for \The [ourtarget]: [ourtarget.health] / [ourtarget.maxHealth] "))
+ return TRUE
if("Process")
var/mob/living/ourtarget = target
var/list/process_options = list()
@@ -1070,6 +1736,20 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
return FALSE
host.vore_selected.mode_flags ^= host.vore_selected.mode_flag_list[toggle_addon]
host.vore_selected.items_preserved.Cut() //Re-evaltuate all items in belly on
+ host.vore_selected.slow_digestion = FALSE
+ if(host.vore_selected.mode_flags & DM_FLAG_SLOWBODY)
+ host.vore_selected.slow_digestion = TRUE
+ if(toggle_addon == "TURBO MODE")
+ STOP_PROCESSING(SSbellies, host.vore_selected)
+ STOP_PROCESSING(SSobj, host.vore_selected)
+ if(host.vore_selected.mode_flags & DM_FLAG_TURBOMODE)
+ host.vore_selected.speedy_mob_processing = TRUE
+ START_PROCESSING(SSobj, host.vore_selected)
+ to_chat(user, span_warning("TURBO MODE activated! Belly processing speed tripled! This also affects timed settings, such as autotransfer and liquid generation."))
+ else
+ host.vore_selected.speedy_mob_processing = FALSE
+ START_PROCESSING(SSbellies, host.vore_selected)
+ to_chat(user, span_warning("TURBO MODE deactivated. Belly processing returned to normal speed."))
. = TRUE
if("b_item_mode")
var/list/menu_list = host.vore_selected.item_digest_modes.Copy()
@@ -1081,7 +1761,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.vore_selected.item_digest_mode = new_mode
host.vore_selected.items_preserved.Cut() //Re-evaltuate all items in belly on belly-mode change
. = TRUE
- if("b_contaminate")
+ if("b_contaminates") // Reverting upstream's change because why reset save files due to a different server's drama?
host.vore_selected.contaminates = !host.vore_selected.contaminates
. = TRUE
if("b_contamination_flavor")
@@ -1106,6 +1786,32 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
return FALSE
host.vore_selected.egg_type = new_egg_type
. = TRUE
+ if("b_egg_name")
+ var/new_egg_name = html_encode(tgui_input_text(user,"Custom Egg Name (Leave empty for default egg name)","New Egg Name"))
+ if(length(new_egg_name) > BELLIES_NAME_MAX)
+ tgui_alert_async(user, "Entered name too long (max [BELLIES_NAME_MAX]).","Error")
+ return FALSE
+ host.vore_selected.egg_name = new_egg_name
+ . = TRUE
+ if("b_egg_size")
+ var/new_egg_size = tgui_input_number(user,"Custom Egg Size 25% to 200% (0 for automatic item depending egg size from 25% to 100%)","New Egg Size", 0, 200)
+ if(new_egg_size == null)
+ return FALSE
+ if(new_egg_size == 0) //Disable.
+ host.vore_selected.egg_size = 0
+ to_chat(user,span_notice("Eggs will automatically calculate size depending on contents."))
+ else if (!ISINRANGE(new_egg_size,25,200))
+ host.vore_selected.egg_size = 0.25 //Set it to the default.
+ to_chat(user,span_notice("Invalid size."))
+ else if(new_egg_size)
+ host.vore_selected.egg_size = (new_egg_size/100)
+ . = TRUE
+ if("b_recycling")
+ host.vore_selected.recycling = !host.vore_selected.recycling
+ . = TRUE
+ if("b_storing_nutrition")
+ host.vore_selected.storing_nutrition = !host.vore_selected.storing_nutrition
+ . = TRUE
if("b_desc")
var/new_desc = html_encode(tgui_input_text(user,"Belly Description, '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name. ([BELLIES_DESC_MAX] char limit):","New Description",host.vore_selected.desc, multiline = TRUE, prevent_enter = TRUE))
@@ -1132,189 +1838,209 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
user.text_warnings = FALSE
var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name. '%count' will be replaced with the number of anything in your belly. '%countprey' will be replaced with the number of living prey in your belly."
switch(params["msgtype"])
- if("dmp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they expire. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Digest Message (to prey)",host.vore_selected.get_messages("dmp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(DIGEST_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they expire. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Digest Message (to prey)",host.vore_selected.get_messages(DIGEST_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"dmp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,DIGEST_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("dmo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey expires in you. Write them in 2nd person ('you feel X'). Avoid using %pred in this type."+help,"Digest Message (to you)",host.vore_selected.get_messages("dmo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(DIGEST_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey expires in you. Write them in 2nd person ('you feel X'). Avoid using %pred in this type."+help,"Digest Message (to you)",host.vore_selected.get_messages(DIGEST_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"dmo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,DIGEST_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("amp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when their absorption finishes. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorb Message (to prey)",host.vore_selected.get_messages("amp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORB_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when their absorption finishes. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorb Message (to prey)",host.vore_selected.get_messages(ABSORB_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"amp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORB_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("amo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey's absorption finishes. Write them in 2nd person ('you feel X'). Avoid using %pred in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorb Message (to you)",host.vore_selected.get_messages("amo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORB_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey's absorption finishes. Write them in 2nd person ('you feel X'). Avoid using %pred in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorb Message (to you)",host.vore_selected.get_messages(ABSORB_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"amo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORB_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("uamp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when their unnabsorption finishes. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Unabsorb Message (to prey)",host.vore_selected.get_messages("uamp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(UNABSORBS_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when their unnabsorption finishes. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Unabsorb Message (to prey)",host.vore_selected.get_messages(UNABSORBS_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"uamp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,UNABSORBS_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("uamo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey's unabsorption finishes. Write them in 2nd person ('you feel X'). Avoid using %pred in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Unabsorb Message (to you)",host.vore_selected.get_messages("uamo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(UNABSORBS_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey's unabsorption finishes. Write them in 2nd person ('you feel X'). Avoid using %pred in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Unabsorb Message (to you)",host.vore_selected.get_messages(UNABSORBS_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"uamo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,UNABSORBS_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("smo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to those nearby when prey struggles. Write them in 3rd person ('X's Y bulges')."+help,"Struggle Message (outside)",host.vore_selected.get_messages("smo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(STRUGGLE_OUTSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to those nearby when prey struggles. Write them in 3rd person ('X's Y bulges')."+help,"Struggle Message (outside)",host.vore_selected.get_messages(STRUGGLE_OUTSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"smo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,STRUGGLE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("smi")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Struggle Message (inside)",host.vore_selected.get_messages("smi"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(STRUGGLE_INSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type."+help,"Struggle Message (inside)",host.vore_selected.get_messages(STRUGGLE_INSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"smi", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,STRUGGLE_INSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("asmo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to those nearby when absorbed prey struggles. Write them in 3rd person ('X's Y bulges'). %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorbed Struggle Message (outside)",host.vore_selected.get_messages("asmo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_STRUGGLE_OUSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to those nearby when absorbed prey struggles. Write them in 3rd person ('X's Y bulges'). %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorbed Struggle Message (outside)",host.vore_selected.get_messages(ABSORBED_STRUGGLE_OUSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"asmo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_STRUGGLE_OUSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("asmi")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorbed Struggle Message (inside)",host.vore_selected.get_messages("asmi"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_STRUGGLE_INSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they struggle. Write them in 2nd person ('you feel X'). Avoid using %prey in this type. %count will not work for this type, and %countprey will only count absorbed victims."+help,"Absorbed Struggle Message (inside)",host.vore_selected.get_messages(ABSORBED_STRUGGLE_INSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"asmi", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_STRUGGLE_INSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("escap")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Escape Attempt Message (to prey)",host.vore_selected.get_messages("escap"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_ATTEMPT_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Escape Attempt Message (to prey)",host.vore_selected.get_messages(ESCAPE_ATTEMPT_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escap", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_ATTEMPT_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("escao")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Attempt Message (to you)",host.vore_selected.get_messages("escao"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_ATTEMPT_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Attempt Message (to you)",host.vore_selected.get_messages(ESCAPE_ATTEMPT_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escao", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_ATTEMPT_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("escp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they escape from within you. Write them in 2nd person ('you climb out of Y)."+help,"Escape Message (to prey)",host.vore_selected.get_messages("escp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they escape from within you. Write them in 2nd person ('you climb out of Y)."+help,"Escape Message (to prey)",host.vore_selected.get_messages(ESCAPE_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("esco")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Message (to you)",host.vore_selected.get_messages("esco"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Message (to you)",host.vore_selected.get_messages(ESCAPE_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"esco", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("escout")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey escapes from within you. Write them in 3rd person ('X climbs out of Z's Y')."+help,"Escape Message (outside)",host.vore_selected.get_messages("escout"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_OUTSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey escapes from within you. Write them in 3rd person ('X climbs out of Z's Y')."+help,"Escape Message (outside)",host.vore_selected.get_messages(ESCAPE_OUTSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escout", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("escip")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they manage to eject an item from within you. Write them in 2nd person ('you manage to O'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to prey)",host.vore_selected.get_messages("escip"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_ITEM_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they manage to eject an item from within you. Write them in 2nd person ('you manage to O'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to prey)",host.vore_selected.get_messages(ESCAPE_ITEM_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escip", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_ITEM_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("escio")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey manages to eject an item from within you. Write them in 2nd person ('O slips from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to you)",host.vore_selected.get_messages("escio"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_ITEM_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey manages to eject an item from within you. Write them in 2nd person ('O slips from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to you)",host.vore_selected.get_messages(ESCAPE_ITEM_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escio", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_ITEM_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("esciout")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey manages to eject an item from within you. Write them in 3rd person ('O from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (outside)",host.vore_selected.get_messages("esciout"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_ITEM_OUTSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey manages to eject an item from within you. Write them in 3rd person ('O from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (outside)",host.vore_selected.get_messages(ESCAPE_ITEM_OUTSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"esciout", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_ITEM_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("escfp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Escape Fail Message (to prey)",host.vore_selected.get_messages("escfp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_FAIL_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Escape Fail Message (to prey)",host.vore_selected.get_messages(ESCAPE_FAIL_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escfp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_FAIL_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("escfo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Escape Fail Message (to you)",host.vore_selected.get_messages("escfo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ESCAPE_FAIL_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Escape Fail Message (to you)",host.vore_selected.get_messages(ESCAPE_FAIL_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"escfo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ESCAPE_FAIL_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("aescap")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Absorbed Escape Attempt Message (to prey)",host.vore_selected.get_messages("aescap"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_ESCAPE_ATTEMPT_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Absorbed Escape Attempt Message (to prey)",host.vore_selected.get_messages(ABSORBED_ESCAPE_ATTEMPT_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescap", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_ESCAPE_ATTEMPT_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("aescao")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Attempt Message (to you)",host.vore_selected.get_messages("aescao"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_ESCAPE_ATTEMPT_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Attempt Message (to you)",host.vore_selected.get_messages(ABSORBED_ESCAPE_ATTEMPT_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescao", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_ESCAPE_ATTEMPT_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("aescp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they escape from within you. Write them in 2nd person ('you escape from Y')."+help,"Absorbed Escape Message (to prey)",host.vore_selected.get_messages("aescp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_ESCAPE_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they escape from within you. Write them in 2nd person ('you escape from Y')."+help,"Absorbed Escape Message (to prey)",host.vore_selected.get_messages(ABSORBED_ESCAPE_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("aesco")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Message (to you)",host.vore_selected.get_messages("aesco"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_ESCAPE_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Message (to you)",host.vore_selected.get_messages(ABSORBED_ESCAPE_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aesco", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("aescout")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when absorbed prey escapes from within you. Write them in 3rd person ('X escapes from Z's Y')."+help,"Absorbed Escape Message (outside)",host.vore_selected.get_messages("aescout"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(ABSORBED_ESCAPE_OUTSIDE)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when absorbed prey escapes from within you. Write them in 3rd person ('X escapes from Z's Y')."+help,"Absorbed Escape Message (outside)",host.vore_selected.get_messages(ABSORBED_ESCAPE_OUTSIDE), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescout", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,ABSORBED_ESCAPE_OUTSIDE, limit = MAX_MESSAGE_LEN / 4)
- if("aescfp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Absorbed Escape Fail Message (to prey)",host.vore_selected.get_messages("aescfp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(FULL_ABSORBED_ESCAPE_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Absorbed Escape Fail Message (to prey)",host.vore_selected.get_messages(FULL_ABSORBED_ESCAPE_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescfp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,FULL_ABSORBED_ESCAPE_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("aescfo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Absorbed Escape Fail Message (to you)",host.vore_selected.get_messages("aescfo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(FULL_ABSORBED_ESCAPE_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Absorbed Escape Fail Message (to you)",host.vore_selected.get_messages(FULL_ABSORBED_ESCAPE_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"aescfo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,FULL_ABSORBED_ESCAPE_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("trnspp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your primary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to prey)",host.vore_selected.get_messages("trnspp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(PRIMARY_TRANSFER_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they struggle and are transferred into your primary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to prey)",host.vore_selected.get_messages(PRIMARY_TRANSFER_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"trnspp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,PRIMARY_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("trnspo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to you)",host.vore_selected.get_messages("trnspo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(PRIMARY_TRANSFER_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey struggle and are transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to you)",host.vore_selected.get_messages(PRIMARY_TRANSFER_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"trnspo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,PRIMARY_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("trnssp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your secondary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to prey)",host.vore_selected.get_messages("trnssp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(SECONDARY_TRANSFER_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they struggle and are transferred into your secondary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to prey)",host.vore_selected.get_messages(SECONDARY_TRANSFER_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"trnssp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,SECONDARY_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("trnsso")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to you)",host.vore_selected.get_messages("trnsso"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(SECONDARY_TRANSFER_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey struggle and are transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to you)",host.vore_selected.get_messages(SECONDARY_TRANSFER_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"trnsso", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,SECONDARY_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("stmodp")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages("stmodp"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(PRIMARY_AUTO_TRANSFER_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your primary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Primary Auto-Transfer Message (to prey)",host.vore_selected.get_messages(PRIMARY_AUTO_TRANSFER_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"stmodp", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,PRIMARY_AUTO_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("stmodo")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages("stmodo"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(PRIMARY_AUTO_TRANSFER_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Primary Auto-Transfer Message (to you)",host.vore_selected.get_messages(PRIMARY_AUTO_TRANSFER_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"stmodo", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,PRIMARY_AUTO_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("stmoap")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages("stmoap"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(SECONDARY_AUTO_TRANSFER_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your secondary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Secondary Auto-Transfer Message (to prey)",host.vore_selected.get_messages(SECONDARY_AUTO_TRANSFER_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"stmoap", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,SECONDARY_AUTO_TRANSFER_PREY, limit = MAX_MESSAGE_LEN / 4)
- if("stmoao")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages("stmoao"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(SECONDARY_AUTO_TRANSFER_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Secondary Auto-Transfer Message (to you)",host.vore_selected.get_messages(SECONDARY_AUTO_TRANSFER_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"stmoao", limit = MAX_MESSAGE_LEN / 4)
- if("em")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging')."+help,"Examine Message (when full)",host.vore_selected.get_messages("em"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
- if(new_message)
- host.vore_selected.set_messages(new_message,"em", limit = MAX_MESSAGE_LEN / 2)
+ host.vore_selected.set_messages(new_message,SECONDARY_AUTO_TRANSFER_OWNER, limit = MAX_MESSAGE_LEN / 4)
- if("ema")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to people who examine you when this belly has absorbed victims. Write them in 3rd person ('Their %belly is larger'). %count will not work for this type, and %countprey will only count absorbed victims."+help,"Examine Message (with absorbed victims)",host.vore_selected.get_messages("ema"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(DIGEST_CHANCE_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages(DIGEST_CHANCE_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"ema", limit = MAX_MESSAGE_LEN / 2)
+ host.vore_selected.set_messages(new_message,DIGEST_CHANCE_PREY, limit = MAX_MESSAGE_LEN / 4)
+
+ if(DIGEST_CHANCE_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages(DIGEST_CHANCE_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(new_message)
+ host.vore_selected.set_messages(new_message,DIGEST_CHANCE_OWNER, limit = MAX_MESSAGE_LEN / 4)
+
+ if(ABSORB_CHANCE_PREY)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages(ABSORB_CHANCE_PREY), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(new_message)
+ host.vore_selected.set_messages(new_message,ABSORB_CHANCE_PREY, limit = MAX_MESSAGE_LEN / 4)
+
+ if(ABSORB_CHANCE_OWNER)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages(ABSORB_CHANCE_OWNER), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(new_message)
+ host.vore_selected.set_messages(new_message,ABSORB_CHANCE_OWNER, limit = MAX_MESSAGE_LEN / 4)
+ if(EXAMINES)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging')."+help,"Examine Message (when full)",host.vore_selected.get_messages(EXAMINES), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(new_message)
+ host.vore_selected.set_messages(new_message,EXAMINES, limit = MAX_MESSAGE_LEN / 2)
+
+ if(EXAMINES_ABSORBED)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to people who examine you when this belly has absorbed victims. Write them in 3rd person ('Their %belly is larger'). %count will not work for this type, and %countprey will only count absorbed victims."+help,"Examine Message (with absorbed victims)",host.vore_selected.get_messages(EXAMINES_ABSORBED), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(new_message)
+ host.vore_selected.set_messages(new_message,EXAMINES_ABSORBED, limit = MAX_MESSAGE_LEN / 2)
if("en")
var/list/indices = list(1,2,3,4,5,6,7,8,9,10)
@@ -1342,60 +2068,60 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(new_message)
host.weight_messages[index] = new_message
- if("im_digest")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Digest mode. Write them in 2nd person ('%pred's %belly squishes down on you.')."+help,"Idle Message (Digest)",host.vore_selected.get_messages("im_digest"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_DIGEST)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Digest mode. Write them in 2nd person ('%pred's %belly squishes down on you.')."+help,"Idle Message (Digest)",host.vore_selected.get_messages(BELLY_MODE_DIGEST), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_digest", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_DIGEST, limit = MAX_MESSAGE_LEN / 4)
- if("im_hold")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Hold mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Hold)",host.vore_selected.get_messages("im_hold"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_HOLD)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Hold mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Hold)",host.vore_selected.get_messages(BELLY_MODE_HOLD), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_hold", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_HOLD, limit = MAX_MESSAGE_LEN / 4)
- if("im_holdabsorbed")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are absorbed. Write them in 2nd person ('%pred's %belly squishes down on you.') %count will not work for this type, and %countprey will only count absorbed victims."+help,"Idle Message (Hold Absorbed)",host.vore_selected.get_messages("im_holdabsorbed"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_HOLD_ABSORB)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are absorbed. Write them in 2nd person ('%pred's %belly squishes down on you.') %count will not work for this type, and %countprey will only count absorbed victims."+help,"Idle Message (Hold Absorbed)",host.vore_selected.get_messages(BELLY_MODE_HOLD_ABSORB), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_holdabsorbed", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_HOLD_ABSORB, limit = MAX_MESSAGE_LEN / 4)
- if("im_absorb")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Absorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Absorb)",host.vore_selected.get_messages("im_absorb"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_ABSORB)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Absorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Absorb)",host.vore_selected.get_messages(BELLY_MODE_ABSORB), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_absorb", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_ABSORB, limit = MAX_MESSAGE_LEN / 4)
- if("im_heal")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Heal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Heal)",host.vore_selected.get_messages("im_heal"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_HEAL)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Heal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Heal)",host.vore_selected.get_messages(BELLY_MODE_HEAL), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_heal", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_HEAL, limit = MAX_MESSAGE_LEN / 4)
- if("im_drain")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Drain mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Drain)",host.vore_selected.get_messages("im_drain"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_DRAIN)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Drain mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Drain)",host.vore_selected.get_messages(BELLY_MODE_DRAIN), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_drain", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_DRAIN, limit = MAX_MESSAGE_LEN / 4)
- if("im_steal")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Size Steal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Size Steal)",host.vore_selected.get_messages("im_steal"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_STEAL)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Size Steal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Size Steal)",host.vore_selected.get_messages(BELLY_MODE_STEAL), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_steal", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_STEAL, limit = MAX_MESSAGE_LEN / 4)
- if("im_egg")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Encase In Egg mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Encase In Egg)",host.vore_selected.get_messages("im_egg"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_EGG)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Encase In Egg mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Encase In Egg)",host.vore_selected.get_messages(BELLY_MODE_EGG), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_egg", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_EGG, limit = MAX_MESSAGE_LEN / 4)
- if("im_shrink")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Shrink mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Shrink)",host.vore_selected.get_messages("im_shrink"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_SHRINK)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Shrink mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Shrink)",host.vore_selected.get_messages(BELLY_MODE_SHRINK), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_shrink", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_SHRINK, limit = MAX_MESSAGE_LEN / 4)
- if("im_grow")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Grow mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Grow)",host.vore_selected.get_messages("im_grow"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_GROW)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Grow mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Grow)",host.vore_selected.get_messages(BELLY_MODE_GROW), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_grow", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_GROW, limit = MAX_MESSAGE_LEN / 4)
- if("im_unabsorb")
- var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Unabsorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Unabsorb)",host.vore_selected.get_messages("im_unabsorb"), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
+ if(BELLY_MODE_UNABSORB)
+ var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Unabsorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Unabsorb)",host.vore_selected.get_messages(BELLY_MODE_UNABSORB), MAX_MESSAGE_LEN * 1.5, TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN * 1.5,0,0,0)
if(new_message)
- host.vore_selected.set_messages(new_message,"im_unabsorb", limit = MAX_MESSAGE_LEN / 4)
+ host.vore_selected.set_messages(new_message,BELLY_MODE_UNABSORB, limit = MAX_MESSAGE_LEN / 4)
if("reset")
var/confirm = tgui_alert(user,"This will delete any custom messages. Are you sure?","Confirmation",list("Cancel","DELETE"))
@@ -1431,6 +2157,10 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
host.vore_selected.primary_transfer_messages_prey = initial(host.vore_selected.primary_transfer_messages_prey)
host.vore_selected.secondary_transfer_messages_owner = initial(host.vore_selected.secondary_transfer_messages_owner)
host.vore_selected.secondary_transfer_messages_prey = initial(host.vore_selected.secondary_transfer_messages_prey)
+ host.vore_selected.primary_autotransfer_messages_owner = initial(host.vore_selected.primary_autotransfer_messages_owner)
+ host.vore_selected.primary_autotransfer_messages_prey = initial(host.vore_selected.primary_autotransfer_messages_prey)
+ host.vore_selected.secondary_autotransfer_messages_owner = initial(host.vore_selected.secondary_autotransfer_messages_owner)
+ host.vore_selected.secondary_autotransfer_messages_prey = initial(host.vore_selected.secondary_autotransfer_messages_prey)
host.vore_selected.digest_chance_messages_owner = initial(host.vore_selected.digest_chance_messages_owner)
host.vore_selected.digest_chance_messages_prey = initial(host.vore_selected.digest_chance_messages_prey)
host.vore_selected.absorb_chance_messages_owner = initial(host.vore_selected.absorb_chance_messages_owner)
@@ -1527,6 +2257,9 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
releasetest = classic_release_sounds[host.vore_selected.release_sound]
if(releasetest)
+ releasetest = sound(releasetest)
+ releasetest.volume = host.vore_selected.sound_volume
+ releasetest.frequency = host.vore_selected.noise_freq
SEND_SOUND(user, releasetest)
. = TRUE
if("b_sound")
@@ -1548,11 +2281,45 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
else
voretest = classic_vore_sounds[host.vore_selected.vore_sound]
if(voretest)
+ voretest = sound(voretest)
+ voretest.volume = host.vore_selected.sound_volume
+ voretest.frequency = host.vore_selected.noise_freq
SEND_SOUND(user, voretest)
. = TRUE
+ if("b_sound_volume")
+ var/sound_volume_input = tgui_input_number(user, "Set belly sound volume percentage.", "Sound Volume", null, 100, 0)
+ if(!isnull(sound_volume_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
+ host.vore_selected.sound_volume = sanitize_integer(sound_volume_input, 0, 100, initial(host.vore_selected.sound_volume))
+ . = TRUE
+ if("b_noise_freq")
+ var/list/preset_noise_freqs = list("high" = MAX_VOICE_FREQ, "middle-high" = 56250, "middle" = 42500, "middle-low"= 28750, "low" = MIN_VOICE_FREQ, "custom" = 1, "random" = 0)
+ var/choice = tgui_input_list(user, "What would you like to set your noise frequency to? ([MIN_VOICE_FREQ] - [MAX_VOICE_FREQ])", "Noise Frequency", preset_noise_freqs)
+ if(!choice)
+ return
+ choice = preset_noise_freqs[choice]
+ if(choice == 0)
+ host.vore_selected.noise_freq = 42500
+ return TOPIC_REFRESH
+ else if(choice == 1)
+ choice = tgui_input_number(user, "Choose your organ's noise frequency, ranging from [MIN_VOICE_FREQ] to [MAX_VOICE_FREQ]", "Custom Noise Frequency", null, MAX_VOICE_FREQ, MIN_VOICE_FREQ, round_value = TRUE)
+ if(choice > MAX_VOICE_FREQ)
+ choice = MAX_VOICE_FREQ
+ else if(choice < MIN_VOICE_FREQ)
+ choice = MIN_VOICE_FREQ
+ host.vore_selected.noise_freq = choice
+ . = TRUE
if("b_tastes")
host.vore_selected.can_taste = !host.vore_selected.can_taste
. = TRUE
+ if("b_feedable")
+ host.vore_selected.is_feedable = !host.vore_selected.is_feedable
+ . = TRUE
+ if("b_entrance_logs")
+ host.vore_selected.entrance_logs = !host.vore_selected.entrance_logs
+ . = TRUE
+ if("b_item_digest_logs")
+ host.vore_selected.item_digest_logs = !host.vore_selected.item_digest_logs
+ . = TRUE
if("b_bulge_size")
var/new_bulge = tgui_input_number(user, "Choose the required size prey must be to show up on examine, ranging from 25% to 200% Set this to 0 for no text on examine.", "Set Belly Examine Size.", max_value = 200, min_value = 0)
if(new_bulge == null)
@@ -1586,40 +2353,43 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
var/new_new_nutrition = CLAMP(new_nutrition, 0.01, 100)
host.vore_selected.nutrition_percent = new_new_nutrition
. = TRUE
+ // modified these to be flexible rather than maxing at 6/6/12/6/6
if("b_burn_dmg")
- var/new_damage = tgui_input_number(user, "Choose the amount of burn damage prey will take per tick. Ranges from 0 to 6.", "Set Belly Burn Damage.", host.vore_selected.digest_burn, 6, 0, round_value=FALSE)
+ var/new_damage = tgui_input_number(user, "Choose the amount of burn damage prey will take per tick. Max of [host.vore_selected.digest_max] across all damage types. [host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_burn] remaining.", "Set Belly Burn Damage.", host.vore_selected.digest_burn, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_burn, 0, round_value=FALSE)
if(new_damage == null)
return FALSE
- var/new_new_damage = CLAMP(new_damage, 0, 6)
- host.vore_selected.digest_burn = new_new_damage
+ new_damage = CLAMP(new_damage, 0, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_burn) // sanity check following tgui input
+ host.vore_selected.digest_burn = new_damage
+ host.vore_selected.items_preserved.Cut()
. = TRUE
if("b_brute_dmg")
- var/new_damage = tgui_input_number(user, "Choose the amount of brute damage prey will take per tick. Ranges from 0 to 6", "Set Belly Brute Damage.", host.vore_selected.digest_brute, 6, 0, round_value=FALSE)
+ var/new_damage = tgui_input_number(user, "Choose the amount of brute damage prey will take per tick. Max of [host.vore_selected.digest_max] across all damage types. [host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_brute] remaining.", "Set Belly Brute Damage.", host.vore_selected.digest_brute, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_brute, 0, round_value=FALSE)
if(new_damage == null)
return FALSE
- var/new_new_damage = CLAMP(new_damage, 0, 6)
- host.vore_selected.digest_brute = new_new_damage
+ new_damage = CLAMP(new_damage, 0, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_brute)
+ host.vore_selected.digest_brute = new_damage
+ host.vore_selected.items_preserved.Cut()
. = TRUE
if("b_oxy_dmg")
- var/new_damage = tgui_input_number(user, "Choose the amount of suffocation damage prey will take per tick. Ranges from 0 to 12.", "Set Belly Suffocation Damage.", host.vore_selected.digest_oxy, 12, 0, round_value=FALSE)
+ var/new_damage = tgui_input_number(user, "Choose the amount of oxygen damage prey will take per tick. Max of [host.vore_selected.digest_max] across all damage types. [host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_oxy] remaining.", "Set Belly Oxygen Damage.", host.vore_selected.digest_oxy, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_oxy, 0, round_value=FALSE)
if(new_damage == null)
return FALSE
- var/new_new_damage = CLAMP(new_damage, 0, 12)
- host.vore_selected.digest_oxy = new_new_damage
+ new_damage = CLAMP(new_damage, 0, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_oxy)
+ host.vore_selected.digest_oxy = new_damage
. = TRUE
if("b_tox_dmg")
- var/new_damage = tgui_input_number(user, "Choose the amount of toxins damage prey will take per tick. Ranges from 0 to 6", "Set Belly Toxins Damage.", host.vore_selected.digest_tox, 6, 0, round_value=FALSE)
+ var/new_damage = tgui_input_number(user, "Choose the amount of toxin damage prey will take per tick. Max of [host.vore_selected.digest_max] across all damage types. [host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_tox] remaining.", "Set Belly Toxin Damage.", host.vore_selected.digest_tox, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_tox, 0, round_value=FALSE)
if(new_damage == null)
return FALSE
- var/new_new_damage = CLAMP(new_damage, 0, 6)
- host.vore_selected.digest_tox = new_new_damage
+ new_damage = CLAMP(new_damage, 0, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_tox)
+ host.vore_selected.digest_tox = new_damage
. = TRUE
if("b_clone_dmg")
- var/new_damage = tgui_input_number(user, "Choose the amount of brute DNA damage (clone) prey will take per tick. Ranges from 0 to 6", "Set Belly Clone Damage.", host.vore_selected.digest_clone, 6, 0, round_value=FALSE)
+ var/new_damage = tgui_input_number(user, "Choose the amount of genetic (clone) damage prey will take per tick. Max of [host.vore_selected.digest_max] across all damage types. [host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_clone] remaining.", "Set Belly Genetic Damage.", host.vore_selected.digest_clone, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_clone, 0, round_value=FALSE)
if(new_damage == null)
return FALSE
- var/new_new_damage = CLAMP(new_damage, 0, 6)
- host.vore_selected.digest_clone = new_new_damage
+ new_damage = CLAMP(new_damage, 0, host.vore_selected.get_unused_digestion_damage() + host.vore_selected.digest_clone)
+ host.vore_selected.digest_clone = new_damage
. = TRUE
if("b_drainmode")
var/list/menu_list = host.vore_selected.drainmodes.Copy()
@@ -1661,6 +2431,11 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(!isnull(escape_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
host.vore_selected.escapechance = sanitize_integer(escape_chance_input, 0, 100, initial(host.vore_selected.escapechance))
. = TRUE
+ if("b_belchchance")
+ var/belch_chance_input = tgui_input_number(user, "Set chance for belch emote on prey resist (as %)", "Resist Belch Chance", host.vore_selected.belchchance , 100, 0)
+ if(!isnull(belch_chance_input))
+ host.vore_selected.belchchance = sanitize_integer(belch_chance_input, 0, 100, initial(host.vore_selected.belchchance))
+ . = TRUE
if("b_escapechance_absorbed")
var/escape_absorbed_chance_input = tgui_input_number(user, "Set absorbed prey escape chance on resist (as %)", "Prey Absorbed Escape Chance", null, 100, 0)
if(!isnull(escape_absorbed_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
@@ -1711,8 +2486,130 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
if(!isnull(digest_chance_input))
host.vore_selected.digestchance = sanitize_integer(digest_chance_input, 0, 100, initial(host.vore_selected.digestchance))
. = TRUE
+ if("b_autotransferchance")
+ var/autotransferchance_input = tgui_input_number(user, "Set belly auto-transfer chance (as %). You must also set the location for this to have any effect.", "Auto-Transfer Chance", host.vore_selected.autotransferchance, 100)
+ if(!isnull(autotransferchance_input))
+ host.vore_selected.autotransferchance = sanitize_integer(autotransferchance_input, 0, 100, initial(host.vore_selected.autotransferchance))
+ . = TRUE
+ if("b_autotransferwait")
+ var/autotransferwait_input = tgui_input_number(user, "Set minimum number of seconds for auto-transfer wait delay.", "Auto-Transfer Time", host.vore_selected.autotransferwait, 1800, 1)
+ if(!isnull(autotransferwait_input))
+ host.vore_selected.autotransferwait = sanitize_integer(autotransferwait_input*10, 10, 18000, initial(host.vore_selected.autotransferwait))
+ . = TRUE
+ if("b_autotransferlocation")
+ var/obj/belly/choice = tgui_input_list(user, "Where do you want your [lowertext(host.vore_selected.name)] auto-transfer to?","Select Belly", (host.vore_organs + "None - Remove" - host.vore_selected))
+ if(!choice) //They cancelled, no changes
+ return FALSE
+ else if(choice == "None - Remove")
+ host.vore_selected.autotransferlocation = null
+ else
+ host.vore_selected.autotransferlocation = choice.name
+ . = TRUE
+ if("b_autotransferextralocation")
+ var/obj/belly/choice = tgui_input_list(user, "What extra places do you want your [lowertext(host.vore_selected.name)] auto-transfer to?","Select Belly", (host.vore_organs - host.vore_selected - host.vore_selected.autotransferlocation))
+ if(!choice) //They cancelled, no changes
+ return FALSE
+ else if(choice.name in host.vore_selected.autotransferextralocation)
+ host.vore_selected.autotransferextralocation -= choice.name
+ else
+ host.vore_selected.autotransferextralocation += choice.name
+ . = TRUE
+ if("b_autotransferchance_secondary")
+ var/autotransferchance_secondary_input = tgui_input_number(user, "Set secondary belly auto-transfer chance (as %). You must also set the location for this to have any effect.", "Secondary Auto-Transfer Chance")
+ if(!isnull(autotransferchance_secondary_input))
+ host.vore_selected.autotransferchance_secondary = sanitize_integer(autotransferchance_secondary_input, 0, 100, initial(host.vore_selected.autotransferchance_secondary))
+ . = TRUE
+ if("b_autotransferlocation_secondary")
+ var/obj/belly/choice = tgui_input_list(user, "Where do you want your secondary [lowertext(host.vore_selected.name)] auto-transfer to?","Select Belly", (host.vore_organs + "None - Remove" - host.vore_selected))
+ if(!choice) //They cancelled, no changes
+ return FALSE
+ else if(choice == "None - Remove")
+ host.vore_selected.autotransferlocation_secondary = null
+ else
+ host.vore_selected.autotransferlocation_secondary = choice.name
+ . = TRUE
+ if("b_autotransferextralocation_secondary")
+ var/obj/belly/choice = tgui_input_list(user, "What extra places do you want your [lowertext(host.vore_selected.name)] auto-transfer to?","Select Belly", (host.vore_organs - host.vore_selected - host.vore_selected.autotransferlocation_secondary))
+ if(!choice) //They cancelled, no changes
+ return FALSE
+ else if(choice.name in host.vore_selected.autotransferextralocation_secondary)
+ host.vore_selected.autotransferextralocation_secondary -= choice.name
+ else
+ host.vore_selected.autotransferextralocation_secondary += choice.name
+ . = TRUE
+ if("b_autotransfer_whitelist")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Whitelist", "Whitelist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_whitelist ^= host.vore_selected.autotransfer_flags_list[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_blacklist")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Blacklist", "Blacklist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_blacklist ^= host.vore_selected.autotransfer_flags_list[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_secondary_whitelist")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Whitelist", "Whitelist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_secondary_whitelist ^= host.vore_selected.autotransfer_flags_list[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_secondary_blacklist")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Blacklist", "Blacklist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_secondary_blacklist ^= host.vore_selected.autotransfer_flags_list[toggle_addon]
+ . = TRUE
+ . = TRUE
+ if("b_autotransfer_whitelist_items")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list_items.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Whitelist", "Whitelist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_whitelist_items ^= host.vore_selected.autotransfer_flags_list_items[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_blacklist_items")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list_items.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Blacklist", "Blacklist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_blacklist_items ^= host.vore_selected.autotransfer_flags_list_items[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_secondary_whitelist_items")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list_items.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Whitelist", "Whitelist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_secondary_whitelist_items ^= host.vore_selected.autotransfer_flags_list_items[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_secondary_blacklist_items")
+ var/list/menu_list = host.vore_selected.autotransfer_flags_list_items.Copy()
+ var/toggle_addon = tgui_input_list(user, "Toggle Blacklist", "Blacklist Choice", menu_list)
+ if(!toggle_addon)
+ return FALSE
+ host.vore_selected.autotransfer_secondary_blacklist_items ^= host.vore_selected.autotransfer_flags_list_items[toggle_addon]
+ . = TRUE
+ if("b_autotransfer_min_amount")
+ var/autotransfer_min_amount_input = tgui_input_number(user, "Set the minimum amount of items your belly can belly auto-transfer at once. Set to 0 for no limit.", "Auto-Transfer Min Amount", host.vore_selected.autotransfer_min_amount, 100)
+ if(!isnull(autotransfer_min_amount_input))
+ host.vore_selected.autotransfer_min_amount = sanitize_integer(autotransfer_min_amount_input, 0, 100, initial(host.vore_selected.autotransfer_min_amount))
+ . = TRUE
+ if("b_autotransfer_max_amount")
+ var/autotransfer_max_amount_input = tgui_input_number(user, "Set the maximum amount of items your belly can belly auto-transfer at once. Set to 0 for no limit.", "Auto-Transfer Max Amount", host.vore_selected.autotransfer_max_amount, 100)
+ if(!isnull(autotransfer_max_amount_input))
+ host.vore_selected.autotransfer_max_amount = sanitize_integer(autotransfer_max_amount_input, 0, 100, initial(host.vore_selected.autotransfer_max_amount))
+ . = TRUE
+ if("b_autotransfer_enabled")
+ host.vore_selected.autotransfer_enabled = !host.vore_selected.autotransfer_enabled
+ . = TRUE
if("b_fullscreen")
host.vore_selected.belly_fullscreen = params["val"]
+ host.vore_selected.update_internal_overlay()
. = TRUE
if("b_disable_hud")
host.vore_selected.disable_hud = !host.vore_selected.disable_hud
@@ -1731,16 +2628,31 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color)
if(newcolor)
host.vore_selected.belly_fullscreen_color = newcolor
+ host.vore_selected.update_internal_overlay()
. = TRUE
- if("b_fullscreen_color_secondary")
- var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_secondary)
- if(newcolor)
- host.vore_selected.belly_fullscreen_color_secondary = newcolor
+ if("b_fullscreen_color2")
+ var/newcolor2 = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color2)
+ if(newcolor2)
+ host.vore_selected.belly_fullscreen_color2 = newcolor2
+ host.vore_selected.update_internal_overlay()
. = TRUE
- if("b_fullscreen_color_trinary")
- var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_trinary)
- if(newcolor)
- host.vore_selected.belly_fullscreen_color_trinary = newcolor
+ if("b_fullscreen_color3")
+ var/newcolor3 = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color3)
+ if(newcolor3)
+ host.vore_selected.belly_fullscreen_color3 = newcolor3
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_fullscreen_color4")
+ var/newcolor4 = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color4)
+ if(newcolor4)
+ host.vore_selected.belly_fullscreen_color4 = newcolor4
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_fullscreen_alpha")
+ var/newalpha = tgui_input_number(user, "Set alpha transparency between 0-255", "Vore Alpha",host.vore_selected.belly_fullscreen_alpha,255,0,0,1)
+ if(newalpha)
+ host.vore_selected.belly_fullscreen_alpha = newalpha
+ host.vore_selected.update_internal_overlay()
. = TRUE
if("b_save_digest_mode")
host.vore_selected.save_digest_mode = !host.vore_selected.save_digest_mode
@@ -1774,9 +2686,37 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
tgui_alert_async(user,failure_msg,"Error!")
return FALSE
+ if(host.soulgem?.linked_belly == host.vore_selected)
+ host.soulgem.linked_belly = null
+
qdel(host.vore_selected)
host.vore_selected = host.vore_organs[1]
. = TRUE
+ if("b_private_struggle")
+ host.vore_selected.private_struggle = !host.vore_selected.private_struggle
+ . = TRUE
+ if("b_vorespawn_blacklist")
+ host.vore_selected.vorespawn_blacklist = !host.vore_selected.vorespawn_blacklist
+ . = TRUE
+ if("b_vorespawn_whitelist")
+ var/new_vorespawn_whitelist = sanitize(tgui_input_text(user,"Input ckeys allowed to vorespawn on separate lines. Cancel will clear the list.","Allowed Players",jointext(host.vore_selected.vorespawn_whitelist,"\n"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0)
+ if(new_vorespawn_whitelist)
+ host.vore_selected.vorespawn_whitelist = splittext(lowertext(new_vorespawn_whitelist),"\n")
+ else
+ host.vore_selected.vorespawn_whitelist = list()
+ . = TRUE
+ if("b_vorespawn_absorbed")
+ var/current_number = global_flag_check(host.vore_selected.vorespawn_absorbed, VS_FLAG_ABSORB_YES) + global_flag_check(host.vore_selected.vorespawn_absorbed, VS_FLAG_ABSORB_PREY)
+ switch(current_number)
+ if(0)
+ host.vore_selected.vorespawn_absorbed |= VS_FLAG_ABSORB_YES
+ if(1)
+ host.vore_selected.vorespawn_absorbed |= VS_FLAG_ABSORB_PREY
+ if(2)
+ host.vore_selected.vorespawn_absorbed &= ~(VS_FLAG_ABSORB_YES)
+ host.vore_selected.vorespawn_absorbed &= ~(VS_FLAG_ABSORB_PREY)
+ unsaved_changes = TRUE
+ return TRUE
if("b_belly_sprite_to_affect")
var/belly_choice = tgui_input_list(user, "Which belly sprite do you want your [lowertext(host.vore_selected.name)] to affect?","Select Region", host.vore_icon_bellies)
if(!belly_choice) //They cancelled, no changes
@@ -1829,6 +2769,16 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
return FALSE
host.vore_selected.vore_sprite_flags ^= host.vore_selected.vore_sprite_flag_list[toggle_vs_flag]
. = TRUE
+ if("b_count_liquid_for_sprites")
+ host.vore_selected.count_liquid_for_sprite = !host.vore_selected.count_liquid_for_sprite
+ host.handle_belly_update()
+ . = TRUE
+ if("b_liquid_multiplier")
+ var/liquid_multiplier_input = tgui_input_number(user, "Set the impact amount of liquid reagents will have on your vore sprite. 1 means a belly with 100 reagents of fluid will count as 1 normal sized prey-thing's worth, 0.5 means liquid counts half as much, 2 means liquid counts double. (Range from 0.1 - 10)", "Liquid Multiplier", host.vore_selected.liquid_multiplier, 10, 0.1, round_value=FALSE)
+ if(!isnull(liquid_multiplier_input))
+ host.vore_selected.liquid_multiplier = CLAMP(liquid_multiplier_input, 0.1, 10)
+ host.handle_belly_update()
+ . = TRUE
if("b_undergarment_choice")
var/datum/category_group/underwear/undergarment_choice = tgui_input_list(user, "Which undergarment do you want to enable when your [lowertext(host.vore_selected.name)] is filled?","Select Undergarment Class", global_underwear.categories)
if(!undergarment_choice) //They cancelled, no changes
@@ -1876,3 +2826,306 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
. = TRUE
if(.)
unsaved_changes = TRUE
+
+// liquid belly procs
+/datum/vore_look/proc/liq_set_attr(mob/user, params)
+ if(!host.vore_selected)
+ tgui_alert(user, "No belly selected to modify.")
+ return FALSE
+
+ var/attr = params["liq_attribute"]
+ switch(attr)
+ if("b_show_liq")
+ if(!host.vore_selected.show_liquids)
+ host.vore_selected.show_liquids = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has liquid options."))
+ else
+ host.vore_selected.show_liquids = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] no longer has liquid options."))
+ . = TRUE
+ if("b_liq_reagent_gen")
+ if(!host.vore_selected.reagentbellymode) //liquid container adjustments and interactions.
+ host.vore_selected.reagentbellymode = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has interactions which can produce liquids."))
+ else //Doesnt produce liquids
+ host.vore_selected.reagentbellymode = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] wont produce liquids, liquids already in your [lowertext(host.vore_selected.name)] must be emptied out or removed with purge."))
+ . = TRUE
+ if("b_liq_reagent_type")
+ var/list/menu_list = host.vore_selected.reagent_choices.Copy() //Useful if we want to make certain races, synths, borgs, and other things result in additional reagents to produce - Jack
+ var/new_reagent = tgui_input_list(user, "Current reagent: [host.vore_selected.reagent_chosen]", "Choose Reagent", menu_list)
+ if(!new_reagent)
+ return FALSE
+
+ host.vore_selected.reagent_chosen = new_reagent
+ host.vore_selected.ReagentSwitch() // For changing variables when a new reagent is chosen
+ . = TRUE
+ if("b_liq_reagent_name")
+ var/new_name = html_encode(tgui_input_text(user,"New name for liquid shown when transfering and dumping on floor (The actual liquid's name is still the same):","New Name",host.vore_selected.reagent_name))
+
+ if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
+ tgui_alert(user, "Entered name length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
+ return FALSE
+
+ host.vore_selected.reagent_name = new_name
+ . = TRUE
+ if("b_liq_reagent_transfer_verb")
+ var/new_verb = html_encode(tgui_input_text(user,"New verb when liquid is transfered from this belly:","New Verb", host.vore_selected.reagent_transfer_verb))
+
+ if(length(new_verb) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
+ tgui_alert(user, "Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
+ return FALSE
+
+ host.vore_selected.reagent_transfer_verb = new_verb
+ . = TRUE
+ if("b_liq_reagent_nutri_rate")
+ host.vore_selected.gen_time_display = tgui_input_list(user, "Choose the time it takes to fill the belly from empty state using nutrition.", "Set Liquid Production Time.",list("10 minutes","30 minutes","1 hour","3 hours","6 hours","12 hours","24 hours"))
+ switch(host.vore_selected.gen_time_display)
+ if("10 minutes")
+ host.vore_selected.gen_time = 0
+ if("30 minutes")
+ host.vore_selected.gen_time = 2
+ if("1 hour")
+ host.vore_selected.gen_time = 5
+ if("3 hours")
+ host.vore_selected.gen_time = 17
+ if("6 hours")
+ host.vore_selected.gen_time = 35
+ if("12 hours")
+ host.vore_selected.gen_time = 71
+ if("24 hours")
+ host.vore_selected.gen_time = 143
+ if(null)
+ return FALSE
+ . = TRUE
+ if("b_liq_reagent_capacity")
+ var/new_custom_vol = tgui_input_number(user, "Choose the amount of liquid the belly can contain at most. Ranges from 10 to 300.", "Set Custom Belly Capacity.", host.vore_selected.custom_max_volume, 300, 10)
+ if(new_custom_vol == null)
+ return FALSE
+ var/new_new_custom_vol = CLAMP(new_custom_vol, 10, 300)
+ host.vore_selected.custom_max_volume = new_new_custom_vol
+ . = TRUE
+ if("b_liq_sloshing")
+ if(!host.vore_selected.vorefootsteps_sounds)
+ host.vore_selected.vorefootsteps_sounds = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] can now make sounds when you walk around depending on how full you are."))
+ else
+ host.vore_selected.vorefootsteps_sounds = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] wont make any liquid sounds no matter how full it is."))
+ . = TRUE
+ if("b_liq_reagent_addons")
+ var/list/menu_list = host.vore_selected.reagent_mode_flag_list.Copy()
+ var/reagent_toggle_addon = tgui_input_list(user, "Toggle your addons", "Toggle Addon", menu_list)
+ if(!reagent_toggle_addon)
+ return FALSE
+ host.vore_selected.reagent_mode_flags ^= host.vore_selected.reagent_mode_flag_list[reagent_toggle_addon]
+ . = TRUE
+ if("b_liquid_overlay")
+ if(!host.vore_selected.liquid_overlay)
+ host.vore_selected.liquid_overlay = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has liquid overlay enabled."))
+ else
+ host.vore_selected.liquid_overlay = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] no longer has liquid overlay enabled."))
+ . = TRUE
+ if("b_max_liquid_level")
+ var/new_max_liquid_level = tgui_input_number(user, "Set custom maximum liquid level. 0-100%", "Set Custom Max Level.", host.vore_selected.max_liquid_level, 100)
+ if(new_max_liquid_level == null)
+ return FALSE
+ var/new_new_max_liquid_level = CLAMP(new_max_liquid_level, 0, 100)
+ host.vore_selected.max_liquid_level = new_new_max_liquid_level
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_custom_reagentcolor")
+ var/newcolor = tgui_color_picker(user, "Choose custom color for liquid overlay. Cancel for normal reagent color.", "", host.vore_selected.custom_reagentcolor)
+ if(newcolor)
+ host.vore_selected.custom_reagentcolor = newcolor
+ else
+ host.vore_selected.custom_reagentcolor = null
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_custom_reagentalpha")
+ var/newalpha = tgui_input_number(user, "Set alpha transparency between 0-255. Leave blank to use capacity based alpha.", "Custom Liquid Alpha",255,255,0,0,1)
+ if(newalpha != null)
+ host.vore_selected.custom_reagentalpha = newalpha
+ else
+ host.vore_selected.custom_reagentalpha = null
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_reagent_touches")
+ if(!host.vore_selected.reagent_touches)
+ host.vore_selected.reagent_touches = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] will now apply reagents to creatures when digesting."))
+ else
+ host.vore_selected.reagent_touches = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] will no longer apply reagents to creatures when digesting."))
+ . = TRUE
+ if("b_mush_overlay")
+ if(!host.vore_selected.mush_overlay)
+ host.vore_selected.mush_overlay = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has fullness overlay enabled."))
+ else
+ host.vore_selected.mush_overlay = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] no longer has fullness overlay enabled."))
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_mush_color")
+ var/newcolor = tgui_color_picker(user, "Choose custom color for mush overlay.", "", host.vore_selected.mush_color)
+ if(newcolor)
+ host.vore_selected.mush_color = newcolor
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_mush_alpha")
+ var/newalpha = tgui_input_number(user, "Set alpha transparency between 0-255", "Mush Alpha",255,255)
+ if(newalpha != null)
+ host.vore_selected.mush_alpha = newalpha
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_max_mush")
+ var/new_max_mush = tgui_input_number(user, "Choose the amount of nutrition required for full mush overlay. Ranges from 0 to 6000. Default 500.", "Set Fullness Overlay Scaling.", host.vore_selected.max_mush, 6000)
+ if(new_max_mush == null)
+ return FALSE
+ var/new_new_max_mush = CLAMP(new_max_mush, 0, 6000)
+ host.vore_selected.max_mush = new_new_max_mush
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_min_mush")
+ var/new_min_mush = tgui_input_number(user, "Set custom minimum mush level. 0-100%", "Set Custom Minimum.", host.vore_selected.min_mush, 100)
+ if(new_min_mush == null)
+ return FALSE
+ var/new_new_min_mush = CLAMP(new_min_mush, 0, 100)
+ host.vore_selected.min_mush = new_new_min_mush
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_item_mush_val")
+ var/new_item_mush_val = tgui_input_number(user, "Set how much solid belly contents affect mush level. 0-1000 fullness per item.", "Set Item Mush Value.", host.vore_selected.item_mush_val, 1000)
+ if(new_item_mush_val == null)
+ return FALSE
+ var/new_new_item_mush_val = CLAMP(new_item_mush_val, 0, 1000)
+ host.vore_selected.item_mush_val = new_new_item_mush_val
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_metabolism_overlay")
+ if(!host.vore_selected.metabolism_overlay)
+ host.vore_selected.metabolism_overlay = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has ingested metabolism overlay enabled."))
+ else
+ host.vore_selected.metabolism_overlay = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] no longer has ingested metabolism overlay enabled."))
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_metabolism_mush_ratio")
+ var/new_metabolism_mush_ratio = tgui_input_number(user, "How much should ingested reagents affect fullness overlay compared to nutrition? Nutrition units per reagent unit. Default 15.", "Set Metabolism Mush Ratio.", host.vore_selected.metabolism_mush_ratio, 500)
+ if(new_metabolism_mush_ratio == null)
+ return FALSE
+ var/new_new_metabolism_mush_ratio = CLAMP(new_metabolism_mush_ratio, 0, 500)
+ host.vore_selected.metabolism_mush_ratio = new_new_metabolism_mush_ratio
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_max_ingested")
+ var/new_max_ingested = tgui_input_number(user, "Choose the amount of reagents within ingested metabolism required for full mush overlay when not using mush overlay option. Ranges from 0 to 6000. Default 500.", "Set Metabolism Overlay Scaling.", host.vore_selected.max_ingested, 6000)
+ if(new_max_ingested == null)
+ return FALSE
+ var/new_new_max_ingested = CLAMP(new_max_ingested, 0, 6000)
+ host.vore_selected.max_ingested = new_new_max_ingested
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_custom_ingested_color")
+ var/newcolor = tgui_color_picker(user, "Choose custom color for ingested metabolism overlay. Cancel for reagent-based dynamic blend.", "", host.vore_selected.custom_ingested_color)
+ if(newcolor)
+ host.vore_selected.custom_ingested_color = newcolor
+ else
+ host.vore_selected.custom_ingested_color = null
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_custom_ingested_alpha")
+ var/newalpha = tgui_input_number(user, "Set alpha transparency between 0-255 when not using mush overlay option.", "Custom Ingested Alpha",255,255)
+ if(newalpha != null)
+ host.vore_selected.custom_ingested_alpha = newalpha
+ host.vore_selected.update_internal_overlay()
+ . = TRUE
+ if("b_liq_purge")
+ var/alert = tgui_alert(user, "Are you sure you want to delete the liquids in your [lowertext(host.vore_selected.name)]?","Confirmation",list("Delete","Cancel"))
+ if(alert != "Delete")
+ return FALSE
+ else
+ host.vore_selected.reagents.clear_reagents()
+ . = TRUE
+ if(.)
+ unsaved_changes = TRUE
+
+/datum/vore_look/proc/liq_set_msg(mob/user, params)
+ if(!host.vore_selected)
+ tgui_alert(user, "No belly selected to modify.")
+ return FALSE
+
+ var/attr = params["liq_messages"]
+ switch(attr)
+ if("b_show_liq_fullness")
+ if(!host.vore_selected.show_fullness_messages)
+ host.vore_selected.show_fullness_messages = 1
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] now has liquid examination options."))
+ else
+ host.vore_selected.show_fullness_messages = 0
+ to_chat(user,span_warning("Your [lowertext(host.vore_selected.name)] no longer has liquid examination options."))
+ . = TRUE
+ if("b_liq_msg_toggle1")
+ host.vore_selected.liquid_fullness1_messages = !host.vore_selected.liquid_fullness1_messages
+ . = TRUE
+ if("b_liq_msg_toggle2")
+ host.vore_selected.liquid_fullness2_messages = !host.vore_selected.liquid_fullness2_messages
+ . = TRUE
+ if("b_liq_msg_toggle3")
+ host.vore_selected.liquid_fullness3_messages = !host.vore_selected.liquid_fullness3_messages
+ . = TRUE
+ if("b_liq_msg_toggle4")
+ host.vore_selected.liquid_fullness4_messages = !host.vore_selected.liquid_fullness4_messages
+ . = TRUE
+ if("b_liq_msg_toggle5")
+ host.vore_selected.liquid_fullness5_messages = !host.vore_selected.liquid_fullness5_messages
+ . = TRUE
+ if("b_liq_msg1")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+
+ var/new_message = tgui_input_text(user,"These are sent to people who examine you when this belly is 0 to 20% full. Write them in 3rd person ('Their %belly is bulging')."+help,"Liquid Examine Message (0 - 20%)",host.vore_selected.get_reagent_messages("full1"))
+ if(new_message)
+ host.vore_selected.set_reagent_messages(new_message,"full1")
+ . = TRUE
+ if("b_liq_msg2")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+
+ var/new_message = tgui_input_text(user,"These are sent to people who examine you when this belly is 20 to 40% full. Write them in 3rd person ('Their %belly is bulging')."+help,"Liquid Examine Message (20 - 40%)",host.vore_selected.get_reagent_messages("full2"))
+ if(new_message)
+ host.vore_selected.set_reagent_messages(new_message,"full2")
+ . = TRUE
+ if("b_liq_msg3")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+
+ var/new_message = tgui_input_text(user,"These are sent to people who examine you when this belly is 40 to 60% full. Write them in 3rd person ('Their %belly is bulging')."+help,"Liquid Examine Message (40 - 60%)",host.vore_selected.get_reagent_messages("full3"))
+ if(new_message)
+ host.vore_selected.set_reagent_messages(new_message,"full3")
+ . = TRUE
+ if("b_liq_msg4")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+
+ var/new_message = tgui_input_text(user,"These are sent to people who examine you when this belly is 60 to 80% full. Write them in 3rd person ('Their %belly is bulging')."+help,"Liquid Examine Message (60 - 80%)",host.vore_selected.get_reagent_messages("full4"))
+ if(new_message)
+ host.vore_selected.set_reagent_messages(new_message,"full4")
+ . = TRUE
+ if("b_liq_msg5")
+ tgui_alert(user,"Setting abusive or deceptive messages will result in a ban. Consider this your warning. Max 150 characters per message, max 10 messages per topic.","Really, don't.")
+ var/help = " Press enter twice to separate messages. '%pred' will be replaced with your name. '%prey' will be replaced with the prey's name. '%belly' will be replaced with your belly's name."
+
+ var/new_message = tgui_input_text(user,"These are sent to people who examine you when this belly is 80 to 100% full. Write them in 3rd person ('Their %belly is bulging')."+help,"Liquid Examine Message (80 - 100%)",host.vore_selected.get_reagent_messages("full5"))
+ if(new_message)
+ host.vore_selected.set_reagent_messages(new_message,"full5")
+ . = TRUE
+ if(.)
+ unsaved_changes = TRUE
+
+#undef VORE_RESIZE_COST
+#undef STATION_PREF_NAME
diff --git a/code/modules/vore/mob_tf.dm b/code/modules/vore/mob_tf.dm
index 1961b680afb..b2403e4e506 100644
--- a/code/modules/vore/mob_tf.dm
+++ b/code/modules/vore/mob_tf.dm
@@ -36,6 +36,7 @@
N.identifying_gender = M.gender
mob_belly_transfer(M)
+ M.soulgem.transfer_self(src) // Soulcatcher
nutrition = M.nutrition
src.ckey = M.ckey
@@ -64,6 +65,8 @@
if(!tf_mob_holder)
return
var/mob/living/ourmob = tf_mob_holder
+ if(soulgem) //Should always be the case, but...Safety. Done here first
+ soulgem.transfer_self(ourmob)
if(ourmob.ai_holder)
var/datum/ai_holder/our_AI = ourmob.ai_holder
our_AI.set_stance(STANCE_IDLE)
@@ -94,6 +97,7 @@
/mob/living/proc/handle_tf_holder()
if(!tf_mob_holder)
return
+ if(tf_mob_holder.loc != src) return // Prevent bodyswapped creatures having their life linked
if(stat != tf_mob_holder.stat)
if(stat == DEAD)
tf_mob_holder.death(FALSE, null)
@@ -112,7 +116,6 @@
new_mob.feeding = feeding
new_mob.can_be_drop_prey = can_be_drop_prey
new_mob.can_be_drop_pred = can_be_drop_pred
- new_mob.allow_inbelly_spawning = allow_inbelly_spawning
new_mob.digest_leave_remains = digest_leave_remains
new_mob.allowmobvore = allowmobvore
new_mob.permit_healbelly = permit_healbelly
@@ -125,6 +128,7 @@
new_mob.slip_vore = slip_vore
new_mob.throw_vore = throw_vore
new_mob.food_vore = food_vore
+ new_mob.consume_liquid_belly = consume_liquid_belly
new_mob.resizable = resizable
new_mob.show_vore_fx = show_vore_fx
new_mob.step_mechanics_pref = step_mechanics_pref
@@ -137,3 +141,23 @@
new_mob.allow_mimicry = allow_mimicry
new_mob.text_warnings = text_warnings
new_mob.allow_mind_transfer = allow_mind_transfer
+
+ new_mob.phase_vore = phase_vore
+ new_mob.latejoin_vore = latejoin_vore
+ new_mob.latejoin_prey = latejoin_prey
+ new_mob.receive_reagents = receive_reagents
+ new_mob.give_reagents = give_reagents
+ new_mob.apply_reagents = apply_reagents
+ new_mob.autotransferable = autotransferable
+ new_mob.strip_pref = strip_pref
+ new_mob.vore_sprite_color = vore_sprite_color
+ new_mob.vore_sprite_multiply = vore_sprite_multiply
+ new_mob.noisy_full = noisy_full
+ new_mob.no_latejoin_vore_warning = no_latejoin_vore_warning
+ new_mob.no_latejoin_prey_warning = no_latejoin_prey_warning
+ new_mob.no_latejoin_vore_warning_time = no_latejoin_vore_warning_time
+ new_mob.no_latejoin_prey_warning_time = no_latejoin_prey_warning_time
+ new_mob.no_latejoin_vore_warning_persists = no_latejoin_vore_warning_persists
+ new_mob.no_latejoin_prey_warning_persists = no_latejoin_prey_warning_persists
+ new_mob.belly_rub_target = belly_rub_target
+ new_mob.soulcatcher_pref_flags = soulcatcher_pref_flags
diff --git a/code/modules/vore/mouseray.dm b/code/modules/vore/mouseray.dm
index 12a9aead588..1e71d41a3bc 100644
--- a/code/modules/vore/mouseray.dm
+++ b/code/modules/vore/mouseray.dm
@@ -101,6 +101,7 @@
ourmob.vore_selected = M.vore_selected
M.vore_selected = null
ourmob.mob_belly_transfer(M)
+ M.soulgem.transfer_self(ourmob) // Soulcatcher
ourmob.Life(1)
if(ishuman(M))
@@ -193,6 +194,7 @@
B.owner = ourmob
M.vore_organs -= B
ourmob.vore_organs += B
+ M.soulgem.transfer_self(ourmob) // Soulcatcher
ourmob.Life(1)
diff --git a/code/modules/xenoarcheaology/artifacts/replicator_vr.dm b/code/modules/xenoarcheaology/artifacts/replicator_vr.dm
index a86b44de893..4c456355d54 100644
--- a/code/modules/xenoarcheaology/artifacts/replicator_vr.dm
+++ b/code/modules/xenoarcheaology/artifacts/replicator_vr.dm
@@ -127,6 +127,8 @@
M.vore_organs -= B
new_mob.vore_organs += B
+ M.soulgem.transfer_self(new_mob) // Soulcatcher
+
new_mob.ckey = M.ckey
if(M.ai_holder && new_mob.ai_holder)
var/datum/ai_holder/old_AI = M.ai_holder
@@ -179,6 +181,8 @@
M.vore_organs -= B
new_mob.vore_organs += B
+ M.soulgem.transfer_self(new_mob) // Soulcatcher
+
new_mob.ckey = M.ckey
if(M.ai_holder && new_mob.ai_holder)
var/datum/ai_holder/old_AI = M.ai_holder
diff --git a/code/modules/xenoarcheaology/tools/suspension_generator.dm b/code/modules/xenoarcheaology/tools/suspension_generator.dm
index 6d0a9509b88..c79470b41aa 100644
--- a/code/modules/xenoarcheaology/tools/suspension_generator.dm
+++ b/code/modules/xenoarcheaology/tools/suspension_generator.dm
@@ -189,7 +189,7 @@
/obj/machinery/suspension_gen/Destroy()
deactivate()
- ..()
+ . = ..()
/obj/machinery/suspension_gen/verb/rotate_counterclockwise()
set src in view(1)
diff --git a/code/modules/xenobio2/machinery/injector_computer.dm b/code/modules/xenobio2/machinery/injector_computer.dm
index aa9a2379911..aeaa16c3020 100644
--- a/code/modules/xenobio2/machinery/injector_computer.dm
+++ b/code/modules/xenobio2/machinery/injector_computer.dm
@@ -21,7 +21,7 @@
/obj/machinery/computer/xenobio2/Destroy()
injector.computer = null
- ..()
+ . = ..()
/obj/machinery/computer/xenobio2/attack_hand(mob/user)
if(..())
diff --git a/icons/mob/screen_full_vore.dmi b/icons/mob/screen_full_vore.dmi
index 376a39399b5..82d69137f40 100644
Binary files a/icons/mob/screen_full_vore.dmi and b/icons/mob/screen_full_vore.dmi differ
diff --git a/icons/mob/screen_full_vore_list.dmi b/icons/mob/screen_full_vore_list.dmi
new file mode 100644
index 00000000000..ce1e5b999b0
Binary files /dev/null and b/icons/mob/screen_full_vore_list.dmi differ
diff --git a/icons/mob/screen_full_vore_list_credits.txt b/icons/mob/screen_full_vore_list_credits.txt
new file mode 100644
index 00000000000..31337e7d52f
--- /dev/null
+++ b/icons/mob/screen_full_vore_list_credits.txt
@@ -0,0 +1,70 @@
+Yeah hey if you're reading this, this is just a little .txt file keeping a record of which artist created which belly sprite (if any credit is due).
+
+Scottred:
+VBO_belly1
+VBO_belly2
+VBO_belly3
+VBO_belly4
+VBO_belly6
+VBO_belly7
+VBO_intestines6
+VBO_intestines7
+VBO_intestines8
+
+VerySoft:
+VBO_belly8
+
+TheMirth:
+VBO_belly5
+VBO_maw1
+
+Tsumibeer:
+VBO_intestines1
+VBO_intestines2
+VBO_intestines3
+VBO_intestines4
+VBO_intestines5
+
+Ewebun:
+VBO_maw2
+VBO_maw3
+VBO_maw4
+VBO_maw5
+VBO_maw6
+VBO_maw7
+VBO_maw8
+VBO_maw9
+VBO_maw10
+VBO_maw11
+
+FishyBoner:
+VBO_maw12
+VBO_trash
+
+original art by kernelDecoy (used with permission) with edits by kcin2001:
+https://twitter.com/kernelDecoy/status/1447387990762954757
+VBO_foot
+https://www.furaffinity.net/view/51185745/
+VBO_paw
+
+
+Drawn by homogenousrule, commissioner; Kashargul:
+VBO_belly9
+VBO_gematically_angular
+VBO_maw13
+VBO_maw14
+VBO_intestines9
+VBO_notbelly
+VBO_wriggly
+
+Hunter Dovetail:
+VBO_maw15
+VBO_maw16
+VBOanim_belly2
+VBOanim_gullet1
+VBOanim_gullet2
+VBOanim_intestine1
+VBOanim_belly3
+VBO_anim_intestine2
+
+
diff --git a/icons/mob/vore_fullscreens/VBO_belly1.dmi b/icons/mob/vore_fullscreens/VBO_belly1.dmi
new file mode 100644
index 00000000000..bc551c30b20
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly2.dmi b/icons/mob/vore_fullscreens/VBO_belly2.dmi
new file mode 100644
index 00000000000..068a0083212
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly3.dmi b/icons/mob/vore_fullscreens/VBO_belly3.dmi
new file mode 100644
index 00000000000..9c4de6a392d
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly3.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly4.dmi b/icons/mob/vore_fullscreens/VBO_belly4.dmi
new file mode 100644
index 00000000000..d07724da340
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly4.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly5.dmi b/icons/mob/vore_fullscreens/VBO_belly5.dmi
new file mode 100644
index 00000000000..570632c7152
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly5.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly6.dmi b/icons/mob/vore_fullscreens/VBO_belly6.dmi
new file mode 100644
index 00000000000..0ad58eff5f9
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly6.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly7.dmi b/icons/mob/vore_fullscreens/VBO_belly7.dmi
new file mode 100644
index 00000000000..fce6253714a
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly7.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly8.dmi b/icons/mob/vore_fullscreens/VBO_belly8.dmi
new file mode 100644
index 00000000000..50e4ba9a47c
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly8.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly9.dmi b/icons/mob/vore_fullscreens/VBO_belly9.dmi
new file mode 100644
index 00000000000..905e5782823
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly9.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_belly9_fluidless.dmi b/icons/mob/vore_fullscreens/VBO_belly9_fluidless.dmi
new file mode 100644
index 00000000000..03e79d97caa
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_belly9_fluidless.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_breast.dmi b/icons/mob/vore_fullscreens/VBO_breast.dmi
new file mode 100644
index 00000000000..0188034966e
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_breast.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_breast1.dmi b/icons/mob/vore_fullscreens/VBO_breast1.dmi
new file mode 100644
index 00000000000..6500a6bc7b7
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_breast1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_coils.dmi b/icons/mob/vore_fullscreens/VBO_coils.dmi
new file mode 100644
index 00000000000..76e443f0d38
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_coils.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_coils1.dmi b/icons/mob/vore_fullscreens/VBO_coils1.dmi
new file mode 100644
index 00000000000..133b3b3c0f6
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_coils1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_darkslit.dmi b/icons/mob/vore_fullscreens/VBO_darkslit.dmi
new file mode 100644
index 00000000000..9ba6d111c5b
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_darkslit.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_fleshs.dmi b/icons/mob/vore_fullscreens/VBO_fleshs.dmi
new file mode 100644
index 00000000000..4971c00c27d
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_fleshs.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_fleshs1.dmi b/icons/mob/vore_fullscreens/VBO_fleshs1.dmi
new file mode 100644
index 00000000000..fc955048bdd
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_fleshs1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_foot.dmi b/icons/mob/vore_fullscreens/VBO_foot.dmi
new file mode 100644
index 00000000000..afa34bbf9f0
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_foot.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_gematically_angular.dmi b/icons/mob/vore_fullscreens/VBO_gematically_angular.dmi
new file mode 100644
index 00000000000..0ce3ebffbff
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_gematically_angular.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines1.dmi b/icons/mob/vore_fullscreens/VBO_intestines1.dmi
new file mode 100644
index 00000000000..c7d42d3a150
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines2.dmi b/icons/mob/vore_fullscreens/VBO_intestines2.dmi
new file mode 100644
index 00000000000..dea84d12fae
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines3.dmi b/icons/mob/vore_fullscreens/VBO_intestines3.dmi
new file mode 100644
index 00000000000..29d3184889a
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines3.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines4.dmi b/icons/mob/vore_fullscreens/VBO_intestines4.dmi
new file mode 100644
index 00000000000..9a377850c19
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines4.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines5.dmi b/icons/mob/vore_fullscreens/VBO_intestines5.dmi
new file mode 100644
index 00000000000..19440f296ed
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines5.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines6.dmi b/icons/mob/vore_fullscreens/VBO_intestines6.dmi
new file mode 100644
index 00000000000..8e9431b1dbf
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines6.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines7.dmi b/icons/mob/vore_fullscreens/VBO_intestines7.dmi
new file mode 100644
index 00000000000..978bafcd469
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines7.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines8.dmi b/icons/mob/vore_fullscreens/VBO_intestines8.dmi
new file mode 100644
index 00000000000..df243a8e906
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines8.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines9.dmi b/icons/mob/vore_fullscreens/VBO_intestines9.dmi
new file mode 100644
index 00000000000..5b6232c9eb7
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines9.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_intestines9_fluidless.dmi b/icons/mob/vore_fullscreens/VBO_intestines9_fluidless.dmi
new file mode 100644
index 00000000000..6ef00953ab7
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_intestines9_fluidless.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw1.dmi b/icons/mob/vore_fullscreens/VBO_maw1.dmi
new file mode 100644
index 00000000000..36cba8e0124
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw10.dmi b/icons/mob/vore_fullscreens/VBO_maw10.dmi
new file mode 100644
index 00000000000..600b9b5596a
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw10.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw11.dmi b/icons/mob/vore_fullscreens/VBO_maw11.dmi
new file mode 100644
index 00000000000..2f00c920b7e
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw11.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw12.dmi b/icons/mob/vore_fullscreens/VBO_maw12.dmi
new file mode 100644
index 00000000000..c457af036a7
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw12.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw13.dmi b/icons/mob/vore_fullscreens/VBO_maw13.dmi
new file mode 100644
index 00000000000..0683c05bbb5
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw13.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw14.dmi b/icons/mob/vore_fullscreens/VBO_maw14.dmi
new file mode 100644
index 00000000000..a49bbf74dc3
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw14.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw15.dmi b/icons/mob/vore_fullscreens/VBO_maw15.dmi
new file mode 100644
index 00000000000..ef73a2bba85
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw15.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw16.dmi b/icons/mob/vore_fullscreens/VBO_maw16.dmi
new file mode 100644
index 00000000000..6d51235d8a8
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw16.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw17.dmi b/icons/mob/vore_fullscreens/VBO_maw17.dmi
new file mode 100644
index 00000000000..b59222b98ce
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw17.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw18.dmi b/icons/mob/vore_fullscreens/VBO_maw18.dmi
new file mode 100644
index 00000000000..3dca1e7d688
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw18.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw19.dmi b/icons/mob/vore_fullscreens/VBO_maw19.dmi
new file mode 100644
index 00000000000..f8fd0534155
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw19.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw2.dmi b/icons/mob/vore_fullscreens/VBO_maw2.dmi
new file mode 100644
index 00000000000..649f25bf45d
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw20.dmi b/icons/mob/vore_fullscreens/VBO_maw20.dmi
new file mode 100644
index 00000000000..c52d27abb63
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw20.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw21.dmi b/icons/mob/vore_fullscreens/VBO_maw21.dmi
new file mode 100644
index 00000000000..c8da78737d6
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw21.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw22.dmi b/icons/mob/vore_fullscreens/VBO_maw22.dmi
new file mode 100644
index 00000000000..aaf2c3f9fb1
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw22.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw23.dmi b/icons/mob/vore_fullscreens/VBO_maw23.dmi
new file mode 100644
index 00000000000..85863ef3bb1
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw23.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw24.dmi b/icons/mob/vore_fullscreens/VBO_maw24.dmi
new file mode 100644
index 00000000000..6a8e050a572
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw24.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw25.dmi b/icons/mob/vore_fullscreens/VBO_maw25.dmi
new file mode 100644
index 00000000000..233df3ac31e
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw25.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw26.dmi b/icons/mob/vore_fullscreens/VBO_maw26.dmi
new file mode 100644
index 00000000000..0a2bc0224e6
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw26.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw3.dmi b/icons/mob/vore_fullscreens/VBO_maw3.dmi
new file mode 100644
index 00000000000..44616d41440
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw3.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw4.dmi b/icons/mob/vore_fullscreens/VBO_maw4.dmi
new file mode 100644
index 00000000000..81268b1b57f
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw4.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw5.dmi b/icons/mob/vore_fullscreens/VBO_maw5.dmi
new file mode 100644
index 00000000000..bc6bf6b210c
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw5.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw6.dmi b/icons/mob/vore_fullscreens/VBO_maw6.dmi
new file mode 100644
index 00000000000..b7c3a3e9976
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw6.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw7.dmi b/icons/mob/vore_fullscreens/VBO_maw7.dmi
new file mode 100644
index 00000000000..f36155782d0
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw7.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw8.dmi b/icons/mob/vore_fullscreens/VBO_maw8.dmi
new file mode 100644
index 00000000000..16a10c27da0
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw8.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_maw9.dmi b/icons/mob/vore_fullscreens/VBO_maw9.dmi
new file mode 100644
index 00000000000..2394f700fa6
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_maw9.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_notbelly.dmi b/icons/mob/vore_fullscreens/VBO_notbelly.dmi
new file mode 100644
index 00000000000..e34abf974b6
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_notbelly.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_paw.dmi b/icons/mob/vore_fullscreens/VBO_paw.dmi
new file mode 100644
index 00000000000..d36ac005eb4
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_paw.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_synth1.dmi b/icons/mob/vore_fullscreens/VBO_synth1.dmi
new file mode 100644
index 00000000000..64d5fb28b2e
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_synth1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_synth2.dmi b/icons/mob/vore_fullscreens/VBO_synth2.dmi
new file mode 100644
index 00000000000..570d731044b
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_synth2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_trash.dmi b/icons/mob/vore_fullscreens/VBO_trash.dmi
new file mode 100644
index 00000000000..8b18ca26e26
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_trash.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_vines.dmi b/icons/mob/vore_fullscreens/VBO_vines.dmi
new file mode 100644
index 00000000000..7d5c1ea6005
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_vines.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBO_wriggly.dmi b/icons/mob/vore_fullscreens/VBO_wriggly.dmi
new file mode 100644
index 00000000000..19fc6fbfb40
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBO_wriggly.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly1.dmi b/icons/mob/vore_fullscreens/VBOanim_belly1.dmi
new file mode 100644
index 00000000000..1445e8cf276
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly10.dmi b/icons/mob/vore_fullscreens/VBOanim_belly10.dmi
new file mode 100644
index 00000000000..48421281d58
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly10.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly2.dmi b/icons/mob/vore_fullscreens/VBOanim_belly2.dmi
new file mode 100644
index 00000000000..3991b9c4672
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly3.dmi b/icons/mob/vore_fullscreens/VBOanim_belly3.dmi
new file mode 100644
index 00000000000..65b16722bd3
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly3.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly4.dmi b/icons/mob/vore_fullscreens/VBOanim_belly4.dmi
new file mode 100644
index 00000000000..200a6f46ec8
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly4.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly5.dmi b/icons/mob/vore_fullscreens/VBOanim_belly5.dmi
new file mode 100644
index 00000000000..ec08879ca90
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly5.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly6.dmi b/icons/mob/vore_fullscreens/VBOanim_belly6.dmi
new file mode 100644
index 00000000000..3704fdd0198
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly6.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly7.dmi b/icons/mob/vore_fullscreens/VBOanim_belly7.dmi
new file mode 100644
index 00000000000..96f4011e967
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly7.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly8.dmi b/icons/mob/vore_fullscreens/VBOanim_belly8.dmi
new file mode 100644
index 00000000000..2be8c17a1d0
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly8.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_belly9.dmi b/icons/mob/vore_fullscreens/VBOanim_belly9.dmi
new file mode 100644
index 00000000000..f5a8e4518b5
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_belly9.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_gullet1.dmi b/icons/mob/vore_fullscreens/VBOanim_gullet1.dmi
new file mode 100644
index 00000000000..5f23f20d0b3
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_gullet1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_intestine1.dmi b/icons/mob/vore_fullscreens/VBOanim_intestine1.dmi
new file mode 100644
index 00000000000..38fdab34881
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_intestine1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_intestine2.dmi b/icons/mob/vore_fullscreens/VBOanim_intestine2.dmi
new file mode 100644
index 00000000000..b04eabd3d23
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_intestine2.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_snakebelly1.dmi b/icons/mob/vore_fullscreens/VBOanim_snakebelly1.dmi
new file mode 100644
index 00000000000..71d9b6433e4
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_snakebelly1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_synthbelly1.dmi b/icons/mob/vore_fullscreens/VBOanim_synthbelly1.dmi
new file mode 100644
index 00000000000..12762f2ac37
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_synthbelly1.dmi differ
diff --git a/icons/mob/vore_fullscreens/VBOanim_taurbelly1.dmi b/icons/mob/vore_fullscreens/VBOanim_taurbelly1.dmi
new file mode 100644
index 00000000000..e8413420ba5
Binary files /dev/null and b/icons/mob/vore_fullscreens/VBOanim_taurbelly1.dmi differ
diff --git a/icons/mob/vore_fullscreens/a_tumby.dmi b/icons/mob/vore_fullscreens/a_tumby.dmi
new file mode 100644
index 00000000000..676168c4ac1
Binary files /dev/null and b/icons/mob/vore_fullscreens/a_tumby.dmi differ
diff --git a/icons/mob/vore_fullscreens/another_tumby.dmi b/icons/mob/vore_fullscreens/another_tumby.dmi
new file mode 100644
index 00000000000..9124fcc5bf6
Binary files /dev/null and b/icons/mob/vore_fullscreens/another_tumby.dmi differ
diff --git a/icons/mob/vore_fullscreens/base.dmi b/icons/mob/vore_fullscreens/base.dmi
new file mode 100644
index 00000000000..783deffbdb2
Binary files /dev/null and b/icons/mob/vore_fullscreens/base.dmi differ
diff --git a/icons/mob/vore_fullscreens/brown_internals.dmi b/icons/mob/vore_fullscreens/brown_internals.dmi
new file mode 100644
index 00000000000..7ad008a2faa
Binary files /dev/null and b/icons/mob/vore_fullscreens/brown_internals.dmi differ
diff --git a/icons/mob/vore_fullscreens/brown_internals_hole.dmi b/icons/mob/vore_fullscreens/brown_internals_hole.dmi
new file mode 100644
index 00000000000..eb52aec2f45
Binary files /dev/null and b/icons/mob/vore_fullscreens/brown_internals_hole.dmi differ
diff --git a/icons/mob/vore_fullscreens/bubbles.dmi b/icons/mob/vore_fullscreens/bubbles.dmi
new file mode 100644
index 00000000000..5f9445db783
Binary files /dev/null and b/icons/mob/vore_fullscreens/bubbles.dmi differ
diff --git a/icons/mob/vore_fullscreens/da_tumby.dmi b/icons/mob/vore_fullscreens/da_tumby.dmi
new file mode 100644
index 00000000000..e1586225a63
Binary files /dev/null and b/icons/mob/vore_fullscreens/da_tumby.dmi differ
diff --git a/icons/mob/vore_fullscreens/dark.dmi b/icons/mob/vore_fullscreens/dark.dmi
new file mode 100644
index 00000000000..4ad14771b89
Binary files /dev/null and b/icons/mob/vore_fullscreens/dark.dmi differ
diff --git a/icons/mob/vore_fullscreens/screen_full_vore_list.dmi b/icons/mob/vore_fullscreens/screen_full_vore_list.dmi
new file mode 100644
index 00000000000..ad50cba2356
Binary files /dev/null and b/icons/mob/vore_fullscreens/screen_full_vore_list.dmi differ
diff --git a/icons/mob/vore_fullscreens/synth_flesh_mono.dmi b/icons/mob/vore_fullscreens/synth_flesh_mono.dmi
new file mode 100644
index 00000000000..98ae1a3e8fe
Binary files /dev/null and b/icons/mob/vore_fullscreens/synth_flesh_mono.dmi differ
diff --git a/icons/mob/vore_fullscreens/synth_flesh_mono_hole.dmi b/icons/mob/vore_fullscreens/synth_flesh_mono_hole.dmi
new file mode 100644
index 00000000000..ae535b10d25
Binary files /dev/null and b/icons/mob/vore_fullscreens/synth_flesh_mono_hole.dmi differ
diff --git a/icons/mob/vore_fullscreens/yet_another_tumby.dmi b/icons/mob/vore_fullscreens/yet_another_tumby.dmi
new file mode 100644
index 00000000000..f0a99f0a62f
Binary files /dev/null and b/icons/mob/vore_fullscreens/yet_another_tumby.dmi differ
diff --git a/maps/groundbase/groundbase_defines.dm b/maps/groundbase/groundbase_defines.dm
index 1c4474653fd..5f0b9a015e4 100644
--- a/maps/groundbase/groundbase_defines.dm
+++ b/maps/groundbase/groundbase_defines.dm
@@ -308,7 +308,7 @@
// We have a bunch of stuff common to the station z levels
/datum/map_z_level/groundbase
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
holomap_legend_x = 220
holomap_legend_y = 160
diff --git a/maps/stellar_delight/stellar_delight_defines.dm b/maps/stellar_delight/stellar_delight_defines.dm
index e158dfcb4fd..bff4f51d2ef 100644
--- a/maps/stellar_delight/stellar_delight_defines.dm
+++ b/maps/stellar_delight/stellar_delight_defines.dm
@@ -229,7 +229,7 @@
// We have a bunch of stuff common to the station z levels
/datum/map_z_level/stellar_delight
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
holomap_legend_x = 220
holomap_legend_y = 160
diff --git a/maps/tether/tether_defines.dm b/maps/tether/tether_defines.dm
index b38a365df3a..f2d3c151e0c 100644
--- a/maps/tether/tether_defines.dm
+++ b/maps/tether/tether_defines.dm
@@ -324,14 +324,14 @@
// We have a bunch of stuff common to the station z levels
/datum/map_z_level/tether/station
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
holomap_legend_x = 220
holomap_legend_y = 160
/datum/map_z_level/tether/station/surface_low
z = Z_LEVEL_TETHER_SURFACE_LOW
name = "Surface 1"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y
@@ -339,7 +339,7 @@
/datum/map_z_level/tether/station/surface_mid
z = Z_LEVEL_TETHER_SURFACE_MID
name = "Surface 2"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
base_turf = /turf/simulated/open
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE
@@ -347,7 +347,7 @@
/datum/map_z_level/tether/station/surface_high
z = Z_LEVEL_TETHER_SURFACE_HIGH
name = "Surface 3"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_VORESPAWN
base_turf = /turf/simulated/open
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X + TETHER_HOLOMAP_CENTER_GUTTER + TETHER_MAP_SIZE
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y
@@ -355,7 +355,7 @@
/datum/map_z_level/tether/transit
z = Z_LEVEL_TETHER_TRANSIT
name = "Transit"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_SEALED|MAP_LEVEL_PLAYER|MAP_LEVEL_CONTACT|MAP_LEVEL_XENOARCH_EXEMPT
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_SEALED|MAP_LEVEL_PLAYER|MAP_LEVEL_CONTACT|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_VORESPAWN
base_turf = /turf/space/v3b_midpoint // Special type that spawns fall triggers
/datum/map_z_level/tether/station/space_low
@@ -363,7 +363,7 @@
name = "Asteroid 1"
base_turf = /turf/space
transit_chance = 33
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_BELOW_BLOCKED
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST|MAP_LEVEL_BELOW_BLOCKED|MAP_LEVEL_VORESPAWN
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X + TETHER_HOLOMAP_CENTER_GUTTER + TETHER_MAP_SIZE
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE
diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm
index 04cc7d48877..bdd750c1555 100644
--- a/maps/~map_system/maps.dm
+++ b/maps/~map_system/maps.dm
@@ -37,6 +37,7 @@ var/list/all_maps = list()
var/static/list/secret_levels = list() // Z-levels that (non-admin) ghosts can't get to
var/static/list/hidden_levels = list() // Z-levels who's contents are hidden, but not forbidden (gateways)
var/static/list/empty_levels = list() // Empty Z-levels that may be used for various things
+ var/static/list/vorespawn_levels = list() //Z-levels where players are allowed to vore latejoin to.
var/static/list/mappable_levels = list()// List of levels where mapping or other similar devices might work fully
var/static/list/below_blocked_levels = list()// List of levels where mapping or other similar devices might work fully
// End Static Lists
@@ -316,6 +317,7 @@ var/list/all_maps = list()
if(flags & MAP_LEVEL_PLAYER) map.player_levels += z
if(flags & MAP_LEVEL_SEALED) map.sealed_levels += z
if(flags & MAP_LEVEL_XENOARCH_EXEMPT) map.xenoarch_exempt_levels += z
+ if(flags & MAP_LEVEL_VORESPAWN) map.vorespawn_levels += z
if(flags & MAP_LEVEL_PERSIST) map.persist_levels += z
if(flags & MAP_LEVEL_EMPTY)
if(!map.empty_levels) map.empty_levels = list()
diff --git a/sound/vore/shortgurgles/gurgle_L1.ogg b/sound/vore/shortgurgles/gurgle_L1.ogg
new file mode 100644
index 00000000000..509af467c58
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_L1.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_L2.ogg b/sound/vore/shortgurgles/gurgle_L2.ogg
new file mode 100644
index 00000000000..bfa4641fc33
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_L2.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_L3.ogg b/sound/vore/shortgurgles/gurgle_L3.ogg
new file mode 100644
index 00000000000..fd0939a6939
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_L3.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_M1.ogg b/sound/vore/shortgurgles/gurgle_M1.ogg
new file mode 100644
index 00000000000..3563236d0b0
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_M1.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_M2.ogg b/sound/vore/shortgurgles/gurgle_M2.ogg
new file mode 100644
index 00000000000..88b83d1ff2e
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_M2.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_M3.ogg b/sound/vore/shortgurgles/gurgle_M3.ogg
new file mode 100644
index 00000000000..3292eaf3b35
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_M3.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_S1.ogg b/sound/vore/shortgurgles/gurgle_S1.ogg
new file mode 100644
index 00000000000..83696a5ebb3
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_S1.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_S2.ogg b/sound/vore/shortgurgles/gurgle_S2.ogg
new file mode 100644
index 00000000000..a9f0058c80e
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_S2.ogg differ
diff --git a/sound/vore/shortgurgles/gurgle_S3.ogg b/sound/vore/shortgurgles/gurgle_S3.ogg
new file mode 100644
index 00000000000..bea507a13c1
Binary files /dev/null and b/sound/vore/shortgurgles/gurgle_S3.ogg differ
diff --git a/sound/vore/walkslosh1.ogg b/sound/vore/walkslosh1.ogg
new file mode 100644
index 00000000000..2226617ee33
Binary files /dev/null and b/sound/vore/walkslosh1.ogg differ
diff --git a/sound/vore/walkslosh10.ogg b/sound/vore/walkslosh10.ogg
new file mode 100644
index 00000000000..b2693e96bd1
Binary files /dev/null and b/sound/vore/walkslosh10.ogg differ
diff --git a/sound/vore/walkslosh2.ogg b/sound/vore/walkslosh2.ogg
new file mode 100644
index 00000000000..91bc538a776
Binary files /dev/null and b/sound/vore/walkslosh2.ogg differ
diff --git a/sound/vore/walkslosh3.ogg b/sound/vore/walkslosh3.ogg
new file mode 100644
index 00000000000..ca7d9a9ab3b
Binary files /dev/null and b/sound/vore/walkslosh3.ogg differ
diff --git a/sound/vore/walkslosh4.ogg b/sound/vore/walkslosh4.ogg
new file mode 100644
index 00000000000..556ec90f41c
Binary files /dev/null and b/sound/vore/walkslosh4.ogg differ
diff --git a/sound/vore/walkslosh5.ogg b/sound/vore/walkslosh5.ogg
new file mode 100644
index 00000000000..6b9a5501d01
Binary files /dev/null and b/sound/vore/walkslosh5.ogg differ
diff --git a/sound/vore/walkslosh6.ogg b/sound/vore/walkslosh6.ogg
new file mode 100644
index 00000000000..feb75c0cf15
Binary files /dev/null and b/sound/vore/walkslosh6.ogg differ
diff --git a/sound/vore/walkslosh7.ogg b/sound/vore/walkslosh7.ogg
new file mode 100644
index 00000000000..d9cdeb08591
Binary files /dev/null and b/sound/vore/walkslosh7.ogg differ
diff --git a/sound/vore/walkslosh8.ogg b/sound/vore/walkslosh8.ogg
new file mode 100644
index 00000000000..1cbafad7cb3
Binary files /dev/null and b/sound/vore/walkslosh8.ogg differ
diff --git a/sound/vore/walkslosh9.ogg b/sound/vore/walkslosh9.ogg
new file mode 100644
index 00000000000..7a0199d257b
Binary files /dev/null and b/sound/vore/walkslosh9.ogg differ
diff --git a/tgui/packages/tgui/interfaces/VorePanel/FeatureColorInput.tsx b/tgui/packages/tgui/interfaces/VorePanel/FeatureColorInput.tsx
new file mode 100644
index 00000000000..2961040bd0b
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/FeatureColorInput.tsx
@@ -0,0 +1,40 @@
+import { useBackend } from 'tgui/backend';
+import { Box, Button, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+export const FeatureColorInput = (props: {
+ action_name: string;
+ value_of: BooleanLike | string;
+ back_color: string;
+ name_of: string;
+}) => {
+ const { act } = useBackend();
+ const { action_name, value_of, back_color, name_of } = props;
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/LiquidColorInput.tsx b/tgui/packages/tgui/interfaces/VorePanel/LiquidColorInput.tsx
new file mode 100644
index 00000000000..191d11577f8
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/LiquidColorInput.tsx
@@ -0,0 +1,37 @@
+import { useBackend } from 'tgui/backend';
+import { Box, Button, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+export const LiquidColorInput = (props: {
+ action_name: string;
+ value_of: BooleanLike | string;
+ back_color: string;
+ name_of: string;
+}) => {
+ const { act } = useBackend();
+ const { action_name, value_of, back_color, name_of } = props;
+ return (
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreAbilities.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreAbilities.tsx
new file mode 100644
index 00000000000..48d0c2ffd14
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreAbilities.tsx
@@ -0,0 +1,57 @@
+import { useBackend } from 'tgui/backend';
+import { LabeledList, Section, Slider, Stack } from 'tgui-core/components';
+import { toFixed } from 'tgui-core/math';
+
+import { abilities } from './types';
+
+export const VoreAbilities = (props: { abilities: abilities }) => {
+ const { act } = useBackend();
+
+ const { abilities } = props;
+
+ const { nutrition, current_size, minimum_size, maximum_size, resize_cost } =
+ abilities;
+
+ function is_enabled(nutri: number, cost: number): boolean {
+ return nutri >= cost;
+ }
+
+ return (
+
+
+
+
+
+ toFixed(value, 2) + '%'}
+ value={current_size * 100}
+ minValue={minimum_size * 100}
+ maxValue={maximum_size * 100}
+ onChange={(e, value: number) =>
+ act('adjust_own_size', {
+ new_mob_size: value / 100,
+ })
+ }
+ />
+
+ Cost:
+ {resize_cost}
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreBellySelectionAndCustomization.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreBellySelectionAndCustomization.tsx
index 2f0ebb58ee4..f5767dd7967 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreBellySelectionAndCustomization.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreBellySelectionAndCustomization.tsx
@@ -1,25 +1,34 @@
import { useBackend } from 'tgui/backend';
-import { Stack } from 'tgui-core/components';
import { Box, Divider, Icon, Section, Tabs } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
import { digestModeToColor } from './constants';
-import type { bellyData, hostMob, selectedData } from './types';
+import { bellyData, hostMob, selectedData } from './types';
import { VoreSelectedBelly } from './VoreSelectedBelly';
export const VoreBellySelectionAndCustomization = (props: {
our_bellies: bellyData[];
- selected: selectedData;
- host_mobtype: hostMob;
+ selected: selectedData | null;
show_pictures: BooleanLike;
+ host_mobtype: hostMob;
+ icon_overflow: BooleanLike;
+ vore_words: Record;
}) => {
const { act } = useBackend();
- const { our_bellies, selected, show_pictures, host_mobtype } = props;
+ const {
+ our_bellies,
+ selected,
+ show_pictures,
+ host_mobtype,
+ icon_overflow,
+ vore_words,
+ } = props;
return (
-
+
act('newbelly')}>
@@ -60,9 +69,11 @@ export const VoreBellySelectionAndCustomization = (props: {
{selected && (
)}
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreContentsPanel.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreContentsPanel.tsx
index c34a96cb553..298e7dede2e 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreContentsPanel.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreContentsPanel.tsx
@@ -1,22 +1,30 @@
import { useBackend } from 'tgui/backend';
import { Button, Image, LabeledList, Stack } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
import { stats } from './constants';
-import type { contentData } from './types';
+import { contentData } from './types';
export const VoreContentsPanel = (props: {
contents: contentData[];
belly?: string;
outside?: BooleanLike;
show_pictures: BooleanLike;
+ icon_overflow: BooleanLike;
}) => {
const { act } = useBackend();
- const { contents, belly, outside = false, show_pictures } = props;
+
+ const {
+ contents,
+ belly,
+ outside = false,
+ show_pictures,
+ icon_overflow,
+ } = props;
return (
<>
- {(outside && (
+ {outside ? (
- )) ||
- null}
- {(show_pictures && (
+ ) : (
+ ''
+ )}
+ {(show_pictures && !icon_overflow && (
{contents.map((thing) => (
@@ -64,8 +73,8 @@ export const VoreContentsPanel = (props: {
)) || (
- {contents.map((thing) => (
-
+ {contents.map((thing, i) => (
+
{tabs[tabIndex] || 'Error'}
>
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode.tsx
index 40989cfee94..071caca2796 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode.tsx
@@ -1,6 +1,6 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
export const VoreSelectedBellyDescriptionsBellymode = (props: {
message_mode: BooleanLike;
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape.tsx
index b5ba928305b..fe4b7c88aa4 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape.tsx
@@ -1,6 +1,6 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
import type { interactData } from '../types';
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle.tsx
index 333038ae3ff..1d9fe4dd3f2 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle.tsx
@@ -1,6 +1,6 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
export const VoreSelectedBellyDescriptionsIdle = (props: {
message_mode: BooleanLike;
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsInteractionChance.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsInteractionChance.tsx
index 7c4cccd4abe..4a7ec86874c 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsInteractionChance.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsInteractionChance.tsx
@@ -1,6 +1,6 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
import type { interactData } from '../types';
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsTransfer.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsTransfer.tsx
index 66d139c1e1c..e3d5960a902 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsTransfer.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsTransfer.tsx
@@ -1,16 +1,17 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
+import { BooleanLike } from 'tgui-core/react';
-import type { interactData } from '../types';
+import type { autotransferData, interactData } from '../types';
export const VoreSelectedBellyDescriptionsTransfer = (props: {
message_mode: BooleanLike;
interacts: interactData;
+ autotransfer: autotransferData;
}) => {
const { act } = useBackend();
- const { message_mode, interacts } = props;
+ const { message_mode, interacts, autotransfer } = props;
return (
@@ -62,6 +63,54 @@ export const VoreSelectedBellyDescriptionsTransfer = (props: {
>
)}
+ {(message_mode || !!autotransfer.autotransferlocation) && (
+ <>
+
+
+ >
+ )}
+ {(message_mode || !!autotransfer.autotransferlocation_secondary) && (
+ <>
+
+
+ >
+ )}
);
};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx
index 0f6c9a6c4e9..ec97a580bf6 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx
@@ -9,7 +9,7 @@ import {
} from 'tgui-core/components';
import { SYNTAX_COLOR, SYNTAX_REGEX } from '../constants';
-import type { Data, selectedData } from '../types';
+import type { selectedData } from '../types';
import { VoreSelectedBellyDescriptionsBellymode } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode';
import { VoreSelectedBellyDescriptionsEscape } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape';
import { VoreSelectedBellyDescriptionsIdle } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle';
@@ -53,11 +53,12 @@ const DescriptionSyntaxHighlighting = (props: { desc: string }) => {
export const VoreSelectedBellyDescriptions = (props: {
belly: selectedData;
+ vore_words: Record;
}) => {
- const { act, data } = useBackend();
+ const { act } = useBackend();
const [showFormatHelp, setShowFormatHelp] = useState(false);
- const { belly } = props;
+ const { belly, vore_words } = props;
const {
verb,
release_verb,
@@ -67,6 +68,8 @@ export const VoreSelectedBellyDescriptions = (props: {
message_mode,
escapable,
interacts,
+ autotransfer_enabled,
+ autotransfer,
emote_active,
} = belly;
@@ -117,7 +120,7 @@ export const VoreSelectedBellyDescriptions = (props: {
Only used in transfer messages - belly prey is going to.
- {Object.entries(data.vore_words).map(([word, options]) => (
+ {Object.entries(vore_words).map(([word, options]) => (
Replaces self with one of these options: {options.join(', ')}
@@ -126,6 +129,33 @@ export const VoreSelectedBellyDescriptions = (props: {
)}
+
+ Description:{' '}
+
+
+
+
+ Description (Absorbed):{' '}
+
+
+
+
-
- Description:{' '}
-
-
-
-
- Description (Absorbed):{' '}
-
-
-
-
);
};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyInteractions.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyInteractions.tsx
index a329250c808..fa3703f2d23 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyInteractions.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyInteractions.tsx
@@ -1,11 +1,15 @@
import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section } from 'tgui-core/components';
-export const VoreSelectedBellyInteractions = (props) => {
+import type { selectedData } from '../types';
+
+export const VoreSelectedBellyInteractions = (props: {
+ belly: selectedData;
+}) => {
const { act } = useBackend();
const { belly } = props;
- const { escapable, interacts } = belly;
+ const { escapable, interacts, autotransfer_enabled, autotransfer } = belly;
return (
{
{interacts.digestchance + '%'}
+
+
+
+
) : (
'These options only display while interactions are turned on.'
)}
+
+ act('set_attribute', { attribute: 'b_autotransfer_enabled' })
+ }
+ icon={autotransfer_enabled ? 'toggle-on' : 'toggle-off'}
+ selected={autotransfer_enabled}
+ >
+ {autotransfer_enabled
+ ? 'Auto-Transfer Enabled'
+ : 'Auto-Transfer Disabled'}
+
+ }
+ >
+ {autotransfer_enabled ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {(autotransfer.autotransferextralocation &&
+ autotransfer.autotransferextralocation.join(', ')) ||
+ ''}
+
+
+ {(autotransfer.autotransfer_whitelist.length &&
+ autotransfer.autotransfer_whitelist.join(', ')) ||
+ 'Everything'}
+
+
+ {(autotransfer.autotransfer_whitelist_items.length &&
+ autotransfer.autotransfer_whitelist_items.join(', ')) ||
+ 'Everything'}
+
+
+ {(autotransfer.autotransfer_blacklist.length &&
+ autotransfer.autotransfer_blacklist.join(', ')) ||
+ 'Nothing'}
+
+
+ {(autotransfer.autotransfer_blacklist_items.length &&
+ autotransfer.autotransfer_blacklist_items.join(', ')) ||
+ 'Nothing'}
+
+
+
+
+
+
+
+
+
+ {(autotransfer.autotransferextralocation_secondary &&
+ autotransfer.autotransferextralocation_secondary.join(', ')) ||
+ ''}
+
+
+ {(autotransfer.autotransfer_secondary_whitelist.length &&
+ autotransfer.autotransfer_secondary_whitelist.join(', ')) ||
+ 'Everything'}
+
+
+ {(autotransfer.autotransfer_secondary_whitelist_items.length &&
+ autotransfer.autotransfer_secondary_whitelist_items.join(
+ ', ',
+ )) ||
+ 'Everything'}
+
+
+ {(autotransfer.autotransfer_secondary_blacklist.length &&
+ autotransfer.autotransfer_secondary_blacklist.join(', ')) ||
+ 'Nothing'}
+
+
+ {(autotransfer.autotransfer_secondary_blacklist_items.length &&
+ autotransfer.autotransfer_secondary_blacklist_items.join(
+ ', ',
+ )) ||
+ 'Nothing'}
+
+
+ ) : (
+ 'These options only display while Auto-Transfer is enabled.'
+ )}
+
);
};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidMessages.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidMessages.tsx
new file mode 100644
index 00000000000..fdefb79667e
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidMessages.tsx
@@ -0,0 +1,131 @@
+import { useBackend } from 'tgui/backend';
+import { Button, LabeledList, Section } from 'tgui-core/components';
+
+import type { selectedData } from '../types';
+
+export const VoreSelectedBellyLiquidMessages = (props: {
+ belly: selectedData;
+}) => {
+ const { act } = useBackend();
+
+ const { belly } = props;
+ const { show_liq_fullness, liq_messages } = belly;
+
+ return (
+
+ act('liq_set_messages', { liq_messages: 'b_show_liq_fullness' })
+ }
+ icon={show_liq_fullness ? 'toggle-on' : 'toggle-off'}
+ selected={show_liq_fullness}
+ tooltipPosition="left"
+ tooltip={
+ 'These are the settings for belly visibility when involving liquids fullness.'
+ }
+ >
+ {show_liq_fullness ? 'Messages On' : 'Messages Off'}
+
+ }
+ >
+ {show_liq_fullness ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ 'These options only display while liquid examination settings are turned on.'
+ )}
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidOptions.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidOptions.tsx
new file mode 100644
index 00000000000..3adb1771ca2
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyLiquidOptions.tsx
@@ -0,0 +1,330 @@
+import { useBackend } from 'tgui/backend';
+import { Button, LabeledList, Section } from 'tgui-core/components';
+
+import { reagentToColor } from '../constants';
+import { LiquidColorInput } from '../LiquidColorInput';
+import type { selectedData } from '../types';
+
+export const VoreSelectedBellyLiquidOptions = (props: {
+ belly: selectedData;
+}) => {
+ const { act } = useBackend();
+
+ const { belly } = props;
+ const { show_liq, liq_interacts } = belly;
+
+ const generationTime = (liq_interacts.liq_reagent_nutri_rate + 1) * 10;
+ const generationMinutes = generationTime % 60;
+ const generationHours = Math.floor(generationTime / 60);
+
+ return (
+
+ act('liq_set_attribute', { liq_attribute: 'b_show_liq' })
+ }
+ icon={show_liq ? 'toggle-on' : 'toggle-off'}
+ selected={show_liq}
+ tooltipPosition="left"
+ tooltip={
+ 'These are the settings for liquid bellies, every belly has a liquid storage.'
+ }
+ >
+ {show_liq ? 'Liquids On' : 'Liquids Off'}
+
+ }
+ >
+ {show_liq ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {(liq_interacts.liq_reagent_addons.length &&
+ liq_interacts.liq_reagent_addons.join(', ')) ||
+ 'None'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ 'These options only display while liquid settings are turned on.'
+ )}
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyOptions.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyOptions.tsx
index f23ab65cda1..11c7589cbcd 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyOptions.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyOptions.tsx
@@ -2,6 +2,7 @@ import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Stack } from 'tgui-core/components';
import { capitalize } from 'tgui-core/string';
+import { vorespawnAbsorbedColor, vorespawnAbsorbedText } from '../constants';
import type { hostMob, selectedData } from '../types';
import { VoreSelectedMobTypeBellyButtons } from './VoreSelectedMobTypeBellyButtons';
@@ -14,6 +15,7 @@ export const VoreSelectedBellyOptions = (props: {
const { belly, host_mobtype } = props;
const {
can_taste,
+ is_feedable,
nutrition_percent,
digest_brute,
digest_burn,
@@ -29,9 +31,19 @@ export const VoreSelectedBellyOptions = (props: {
contaminate_flavor,
contaminate_color,
egg_type,
+ egg_name,
+ egg_size,
+ recycling,
+ storing_nutrition,
+ entrance_logs,
+ item_digest_logs,
selective_preference,
save_digest_mode,
eating_privacy_local,
+ vorespawn_blacklist,
+ vorespawn_whitelist,
+ vorespawn_absorbed,
+ private_struggle,
drainmode,
} = belly;
@@ -48,10 +60,19 @@ export const VoreSelectedBellyOptions = (props: {
{can_taste ? 'Yes' : 'No'}
+
+
+
- {(contaminates && (
+ {contaminates ? (
<>
>
- )) ||
- null}
+ ) : (
+ ''
+ )}
+
+
+
+
+
+
+ {vorespawn_blacklist ? (
+ ''
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx
index 94d9c779981..13a92cef05b 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx
@@ -2,6 +2,7 @@ import { useBackend } from 'tgui/backend';
import { Box, Button, LabeledList, Section, Stack } from 'tgui-core/components';
import { classes } from 'tgui-core/react';
+import { FeatureColorInput } from '../FeatureColorInput';
import type { selectedData } from '../types';
export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
@@ -10,16 +11,19 @@ export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
const { belly } = props;
const {
belly_fullscreen,
+ belly_fullscreen_color,
+ belly_fullscreen_color2,
+ belly_fullscreen_color3,
+ belly_fullscreen_color4,
+ colorization_enabled,
possible_fullscreens,
disable_hud,
- belly_fullscreen_color,
- belly_fullscreen_color_secondary,
- belly_fullscreen_color_trinary,
- colorization_enabled,
vore_sprite_flags,
affects_voresprite,
absorbed_voresprite,
absorbed_multiplier,
+ liquid_voresprite,
+ liquid_multiplier,
item_voresprite,
item_multiplier,
health_voresprite,
@@ -29,6 +33,7 @@ export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
belly_sprite_to_affect,
undergarment_chosen,
undergarment_if_none,
+ undergarment_color,
tail_option_shown,
tail_to_change_to,
} = belly;
@@ -86,6 +91,28 @@ export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
{absorbed_multiplier}
+
+
+
+
+
+
+
>
) : (
''
@@ -214,69 +247,36 @@ export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
@@ -328,7 +328,7 @@ export const VoreSelectedBellyVisuals = (props: { belly: selectedData }) => {
-
+
Belly styles:
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical .tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical .tsx
deleted file mode 100644
index 4da8778f871..00000000000
--- a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical .tsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import { useBackend } from 'tgui/backend';
-import { Button, Section, Stack } from 'tgui-core/components';
-import type { BooleanLike } from 'tgui-core/react';
-
-import type { localPrefs } from '../types';
-import { VoreUserPreferenceItem } from '../VoreUserPreferenceItem';
-
-export const VoreUserPreferencesMechanical = (props: {
- show_pictures: BooleanLike;
- preferences: localPrefs;
-}) => {
- const { act } = useBackend();
- const { show_pictures, preferences } = props;
-
- return (
- act('show_pictures')}
- >
- Contents Preference: {show_pictures ? 'Show Pictures' : 'Show List'}
-
- }
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- act('switch_selective_mode_pref')}>
- Selective Mode Preference
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical.tsx
new file mode 100644
index 00000000000..1b1b89d0e4a
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesMechanical.tsx
@@ -0,0 +1,132 @@
+import { useBackend } from 'tgui/backend';
+import { Button, Section, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+import { localPrefs } from '../types';
+import { VoreUserPreferenceItem } from '../VoreUserPreferenceItem';
+
+export const VoreUserPreferencesMechanical = (props: {
+ show_pictures: BooleanLike;
+ icon_overflow: BooleanLike;
+ preferences: localPrefs;
+}) => {
+ const { act } = useBackend();
+ const { show_pictures, icon_overflow, preferences } = props;
+
+ return (
+ act('show_pictures')}
+ >
+ Contents Preference: {show_pictures ? 'Show Pictures' : 'Show List'}
+
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSoulcatcher.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSoulcatcher.tsx
new file mode 100644
index 00000000000..d2ccf1ab71e
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSoulcatcher.tsx
@@ -0,0 +1,56 @@
+import { Box, Section, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+import { localPrefs } from '../types';
+import { VoreUserPreferenceItem } from '../VoreUserPreferenceItem';
+
+export const VoreUserPreferencesSoulcatcher = (props: {
+ soulcatcher_allow_capture: BooleanLike;
+ preferences: localPrefs;
+}) => {
+ const { soulcatcher_allow_capture, preferences } = props;
+
+ return (
+
+
+
+ }
+ >
+ {soulcatcher_allow_capture ? (
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ ''
+ )}
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpawn.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpawn.tsx
new file mode 100644
index 00000000000..94026e86cb3
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpawn.tsx
@@ -0,0 +1,131 @@
+import { useBackend } from 'tgui/backend';
+import { Box, Button, NumberInput, Section, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+import { localPrefs } from '../types';
+import { VoreUserPreferenceItem } from '../VoreUserPreferenceItem';
+
+export const VoreUserPreferencesSpawn = (props: {
+ latejoin_vore: BooleanLike;
+ no_spawnpred_warning_time: number;
+ no_spawnpred_warning_save: BooleanLike;
+ latejoin_prey: BooleanLike;
+ no_spawnprey_warning_time: number;
+ no_spawnprey_warning_save: BooleanLike;
+ preferences: localPrefs;
+}) => {
+ const { act } = useBackend();
+ const {
+ latejoin_vore,
+ no_spawnpred_warning_time,
+ no_spawnpred_warning_save,
+ latejoin_prey,
+ no_spawnprey_warning_time,
+ no_spawnprey_warning_save,
+ preferences,
+ } = props;
+
+ return (
+
+
+
+
+ }
+ >
+
+ {latejoin_vore ? (
+ <>
+
+
+
+
+
+ act('adjust_no_latejoin_vore_warning_time', {
+ new_pred_time: value,
+ })
+ }
+ />
+
+
+ act('toggle_no_latejoin_vore_warning_persists')}
+ >
+ P
+
+
+ >
+ ) : (
+ ''
+ )}
+ {latejoin_prey ? (
+ <>
+
+
+
+
+
+ act('adjust_no_latejoin_prey_warning_time', {
+ new_prey_time: value,
+ })
+ }
+ />
+
+
+ act('toggle_no_latejoin_prey_warning_persists')}
+ >
+ P
+
+
+ >
+ ) : (
+ ''
+ )}
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpontaneous.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpontaneous.tsx
new file mode 100644
index 00000000000..948f7531a8e
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferencesTabs/VoreUserPreferencesSpontaneous.tsx
@@ -0,0 +1,79 @@
+import { Box, Section, Stack } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+import { localPrefs } from '../types';
+import { VoreUserPreferenceItem } from '../VoreUserPreferenceItem';
+
+export const VoreUserPreferencesSpontaneous = (props: {
+ can_be_drop_prey: BooleanLike;
+ can_be_drop_pred: BooleanLike;
+ preferences: localPrefs;
+}) => {
+ const { can_be_drop_prey, can_be_drop_pred, preferences } = props;
+
+ return (
+
+
+
+
+ }
+ >
+ {can_be_drop_prey || can_be_drop_pred ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ ''
+ )}
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanel/constants.ts b/tgui/packages/tgui/interfaces/VorePanel/constants.ts
index ead6ad753c0..34c1c16a872 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/constants.ts
+++ b/tgui/packages/tgui/interfaces/VorePanel/constants.ts
@@ -1,7 +1,14 @@
export const stats: (string | undefined)[] = [undefined, 'average', 'bad'];
+export const vorespawnAbsorbedText: string[] = ['No', 'Yes', 'Prey Choice'];
+export const vorespawnAbsorbedColor: (string | undefined)[] = [
+ undefined,
+ 'green',
+ 'orange',
+];
export const digestModeToColor = {
- Hold: null,
+ Default: undefined,
+ Hold: undefined,
Digest: 'red',
Absorb: 'purple',
Unabsorb: 'purple',
@@ -14,6 +21,21 @@ export const digestModeToColor = {
'Encase In Egg': 'blue',
};
+export const reagentToColor = {
+ Water: undefined,
+ Milk: undefined,
+ Cream: undefined,
+ Honey: 'teal',
+ 'Cherry Jelly': 'teal',
+ 'Digestive acid': 'red',
+ 'Diluted digestive acid': 'red',
+ 'Space cleaner': undefined,
+ 'Space Lube': undefined,
+ Biomass: 'teal',
+ 'Concentrated Radium': 'orange',
+ Tricordrazine: 'green',
+};
+
export const digestModeToPreyMode = {
Hold: 'being held.',
Digest: 'being digested.',
diff --git a/tgui/packages/tgui/interfaces/VorePanel/index.tsx b/tgui/packages/tgui/interfaces/VorePanel/index.tsx
index e48115a4d6a..5af0709d16e 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/index.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanel/index.tsx
@@ -3,9 +3,10 @@ import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Button, Icon, NoticeBox, Stack, Tabs } from 'tgui-core/components';
-import type { Data } from './types';
+import { Data } from './types';
import { VoreBellySelectionAndCustomization } from './VoreBellySelectionAndCustomization';
import { VoreInsidePanel } from './VoreInsidePanel';
+import { VoreSoulcatcher } from './VoreSoulcatcher';
import { VoreUserPreferences } from './VoreUserPreferences';
/**
@@ -14,11 +15,156 @@ import { VoreUserPreferences } from './VoreUserPreferences';
* - The Belly Selection Panel, where you can select what belly people will go into and customize the active one.
* - User Preferences, where you can adjust all of your vore preferences on the fly.
*/
-export const VorePanel = (props) => {
+
+/**
+ * CHOMPedits specified here. Read ALL of this if conflicts happen, I can't find a way to add comments line by line.
+ *
+ * Under VoreSelectedBelly the following strings have been added to const{}:
+ * show_liq, liq_interacts, liq_reagent_gen, liq_reagent_type, liq_reagent_name,
+ * liq_reagent_transfer_verb, liq_reagent_nutri_rate, liq_reagent_capacity, liq_sloshing, liq_reagent_addons,
+ * show_liq_fullness, liq_messages, liq_msg_toggle1, liq_msg_toggle2, liq_msg_toggle3, liq_msg_toggle4,
+ * liq_msg_toggle5, liq_msg1, liq_msg2, liq_msg3, liq_msg4, liq_msg5, sound_volume, egg_name, recycling, storing_nutrition, entrance_logs, item_digest_logs, noise_freq,
+ * custom_reagentcolor, custom_reagentalpha, liquid_overlay, max_liquid_level, mush_overlay, reagent_touches, mush_color, mush_alpha, max_mush, min_mush, item_mush_val,
+ * metabolism_overlay, metabolism_mush_ratio, max_ingested, custom_ingested_color, custom_ingested_alpha
+ *
+ * To the tabs section of VoreSelectedBelly return
+ * setTabIndex(5)}>
+ * Liquid Options
+ *
+ * setTabIndex(6)}>
+ * Liquid Messages
+ *
+ *
+ * All of the content for tabIndex === 5 and tabIndex === 6
+ *
+ * Under VoreUserPreferences the following strings have been added to const{}:
+ * liq_rec, liq_giv,
+ *
+ * To VoreUserPreferences return
+ *
+ * act("toggle_liq_rec")}
+ * icon={liq_rec ? "toggle-on" : "toggle-off"}
+ * selected={liq_rec}
+ * fluid
+ * tooltipPosition="top"
+ * tooltip={"This button is for allowing or preventing others from giving you liquids from their vore organs."
+ * + (liq_rec ? " Click here to prevent receiving liquids." : " Click here to allow receiving liquids.")}
+ * >
+ * {liq_rec ? "Receiving Liquids Allowed" : "Do Not Allow Receiving Liquids"}
+ *
+ *
+ *
+ * act("toggle_liq_giv")}
+ * icon={liq_giv ? "toggle-on" : "toggle-off"}
+ * selected={liq_giv}
+ * fluid
+ * tooltipPosition="top"
+ * tooltip={"This button is for allowing or preventing others from taking liquids from your vore organs."
+ * + (liq_giv ? " Click here to prevent taking liquids." : " Click here to allow taking liquids.")}
+ * >
+ * {liq_giv ? "Taking Liquids Allowed" : "Do Not Allow Taking Liquids"}
+ *
+ *
+ *
+ * NEW EDITS 2/25/21: COLORED BELLY OVERLAYS
+ * LINE 5:
+ *import { Box, Button, ByondUi, Stack, Collapsible, Icon, LabeledList, NoticeBox, Section, Tabs } from "../components";
+ *
+ * LINE 172 -
+ *
+ * LINE 301 - belly_fullscreen_color,
+ * mapRef,
+ *
+ * LINE 604 -
+ *
+ *
+ * act("set_attribute", { attribute: "b_fullscreen_color", val: null })}>
+ * Select Color
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * act("set_attribute", { attribute: "b_disable_hud" })}
+ * icon={disable_hud ? "toggle-on" : "toggle-off"}
+ * selected={disable_hud}
+ * >
+ * {disable_hud ? "Yes" : "No"}
+ *
+ *
+ *
+ *
+ *
+ * Belly styles:
+ * act("set_attribute", { attribute: "b_fullscreen", val: null })}>
+ * Disabled
+ *
+ * {Object.keys(possible_fullscreens).map(key => (
+ * act("set_attribute", { attribute: "b_fullscreen", val: key })}>
+ *
+ *
+ * ))}
+ *
+ *
+ *
+ * LINE 900 - const [tabIndex, setTabIndex] = useLocalState('tabIndex', 0);
+ *
+ * return tabIndex===4 ? null : (
+ *
+ * New preference added, noisy_full
+ * noisy_full enables belching when nutrition exceeds 500, very similar to the noisy preference.
+ *
+ * That's everything so far.
+ *
+ */
+
+export const VorePanel = () => {
const { act, data } = useBackend();
- const { inside, our_bellies, selected, prefs, show_pictures, host_mobtype } =
- data;
+ const {
+ inside,
+ our_bellies,
+ selected,
+ soulcatcher,
+ abilities,
+ prefs,
+ show_pictures,
+ icon_overflow,
+ host_mobtype,
+ unsaved_changes,
+ vore_words,
+ } = data;
const [tabIndex, setTabIndex] = useState(0);
@@ -28,19 +174,34 @@ export const VorePanel = (props) => {
+ );
+ tabs[1] = (
+
+ );
+ tabs[2] = (
+
);
- tabs[1] = ;
-
return (
-
+
- {(data.unsaved_changes && (
+ {(unsaved_changes && (
Warning: Unsaved Changes!
@@ -66,7 +227,11 @@ export const VorePanel = (props) => {
''}
500 ? '30%' : '20%'}>
-
+
@@ -80,6 +245,13 @@ export const VorePanel = (props) => {
setTabIndex(1)}
+ >
+ Soulcatcher
+
+
+ setTabIndex(2)}
>
Preferences
diff --git a/tgui/packages/tgui/interfaces/VorePanel/types.ts b/tgui/packages/tgui/interfaces/VorePanel/types.ts
index ea36a398da3..b7fb2ddb7c9 100644
--- a/tgui/packages/tgui/interfaces/VorePanel/types.ts
+++ b/tgui/packages/tgui/interfaces/VorePanel/types.ts
@@ -3,21 +3,25 @@ import { BooleanLike } from 'tgui-core/react';
export type Data = {
unsaved_changes: BooleanLike;
show_pictures: BooleanLike;
+ icon_overflow: BooleanLike;
inside: insideData;
host_mobtype: hostMob;
our_bellies: bellyData[];
- selected: selectedData;
+ selected: selectedData | null;
prefs: prefData;
- abilities: {
- nutrition: number;
- current_size: number;
- minimum_size: number;
- maximum_size: number;
- resize_cost: number;
- };
+ soulcatcher: soulcatcherData | null;
+ abilities: abilities;
vore_words: Record;
};
+export type abilities = {
+ nutrition: number;
+ current_size: number;
+ minimum_size: number;
+ maximum_size: number;
+ resize_cost: number;
+};
+
export type hostMob = {
is_cyborg: BooleanLike;
is_vore_simple_mob: BooleanLike;
@@ -30,6 +34,9 @@ export type insideData = {
desc?: string;
pred?: string;
ref?: string;
+ liq_lvl?: number;
+ liq_reagent_type?: string;
+ liuq_name?: string;
contents?: contentData[];
};
@@ -65,7 +72,13 @@ export type selectedData = {
sound: string;
release_sound: string;
can_taste: BooleanLike;
+ is_feedable: BooleanLike;
egg_type: string;
+ egg_name: string;
+ egg_size: number;
+ recycling: BooleanLike;
+ storing_nutrition: BooleanLike;
+ entrance_logs: BooleanLike;
nutrition_percent: number;
digest_brute: number;
digest_burn: number;
@@ -89,9 +102,53 @@ export type selectedData = {
belly_overall_mult: number;
drainmode: string;
belly_fullscreen_color: string;
- belly_fullscreen_color_secondary: string;
- belly_fullscreen_color_trinary: string;
+ belly_fullscreen_color2: string;
+ belly_fullscreen_color3: string;
+ belly_fullscreen_color4: string;
+ belly_fullscreen_alpha: number;
colorization_enabled: BooleanLike;
+ custom_reagentcolor: string;
+ custom_reagentalpha: number;
+ liquid_overlay: BooleanLike;
+ max_liquid_level: number;
+ reagent_touches: BooleanLike;
+ mush_overlay: BooleanLike;
+ mush_color: string;
+ mush_alpha: number;
+ max_mush: number;
+ min_mush: number;
+ item_mush_val: number;
+ metabolism_overlay: BooleanLike;
+ metabolism_mush_ratio: number;
+ max_ingested: number;
+ custom_ingested_color: string;
+ custom_ingested_alpha: number;
+ vorespawn_blacklist: BooleanLike;
+ vorespawn_whitelist: string[];
+ vorespawn_absorbed: number;
+ sound_volume: number;
+ affects_voresprite: BooleanLike;
+ absorbed_voresprite: BooleanLike;
+ absorbed_multiplier: number;
+ liquid_voresprite: BooleanLike;
+ liquid_multiplier: number;
+ item_voresprite: BooleanLike;
+ item_multiplier: number;
+ health_voresprite: number;
+ resist_animation: BooleanLike;
+ voresprite_size_factor: number;
+ belly_sprite_to_affect: string;
+ undergarment_chosen: string;
+ undergarment_if_none: string;
+ undergarment_color: string;
+ belly_sprite_option_shown: BooleanLike;
+ tail_option_shown: BooleanLike;
+ tail_to_change_to: BooleanLike | string;
+ tail_colouration: BooleanLike;
+ tail_extra_overlay: BooleanLike;
+ tail_extra_overlay2: BooleanLike;
+ noise_freq: number;
+ item_digest_logs: BooleanLike;
private_struggle: BooleanLike;
addons: string[];
vore_sprite_flags: string[];
@@ -105,25 +162,10 @@ export type selectedData = {
disable_hud: BooleanLike;
possible_fullscreens: string[];
contents: contentData[];
- affects_voresprite: BooleanLike;
- absorbed_voresprite: BooleanLike;
- absorbed_multiplier: number;
- liquid_voresprite: BooleanLike;
- liquid_multiplier: number;
- item_voresprite: BooleanLike;
- item_multiplier: number;
- health_voresprite: BooleanLike;
- resist_animation: BooleanLike;
- voresprite_size_factor: number;
- belly_sprite_to_affect: string;
- belly_sprite_option_shown: BooleanLike;
- tail_option_shown: BooleanLike;
- tail_to_change_to: BooleanLike | string;
- tail_colouration: BooleanLike;
- tail_extra_overlay: BooleanLike;
- tail_extra_overlay2: BooleanLike;
- undergarment_chosen: undefined; // NOT IMPLEMENTED!!!
- undergarment_if_none: undefined; // NOT IMPLEMENTED!!!
+ show_liq: BooleanLike;
+ liq_interacts: liqInteractData;
+ show_liq_fullness: BooleanLike;
+ liq_messages: liqMessageData;
};
export type interactData = {
@@ -136,12 +178,67 @@ export type interactData = {
transferlocation_secondary: string;
absorbchance: number;
digestchance: number;
+ belchchance: number;
};
-type autotransferData = {
+export type autotransferData = {
autotransferchance: number;
autotransferwait: number;
autotransferlocation: string;
+ autotransferextralocation: string[];
+ autotransferchance_secondary: number;
+ autotransferlocation_secondary: string;
+ autotransferextralocation_secondary: string[];
+ autotransfer_min_amount: number;
+ autotransfer_max_amount: number;
+ autotransfer_whitelist: string[];
+ autotransfer_blacklist: string[];
+ autotransfer_whitelist_items: string[];
+ autotransfer_blacklist_items: string[];
+ autotransfer_secondary_whitelist: string[];
+ autotransfer_secondary_blacklist: string[];
+ autotransfer_secondary_whitelist_items: string[];
+ autotransfer_secondary_blacklist_items: string[];
+};
+
+type liqInteractData = {
+ liq_reagent_gen: BooleanLike;
+ liq_reagent_type: string;
+ liq_reagent_name: string;
+ liq_reagent_transfer_verb: string;
+ liq_reagent_nutri_rate: number;
+ liq_reagent_capacity: number;
+ liq_sloshing: BooleanLike;
+ liq_reagent_addons: string[];
+ custom_reagentcolor: string;
+ custom_reagentalpha: number | string;
+ liquid_overlay: BooleanLike;
+ max_liquid_level: number;
+ reagent_touches: BooleanLike;
+ mush_overlay: BooleanLike;
+ mush_color: string;
+ mush_alpha: number;
+ max_mush: number;
+ min_mush: number;
+ item_mush_val: number;
+ metabolism_overlay: BooleanLike;
+ metabolism_mush_ratio: number;
+ max_ingested: number;
+ custom_ingested_color: string;
+ custom_ingested_alpha: number;
+};
+
+type liqMessageData = {
+ liq_msg_toggle1: BooleanLike;
+ liq_msg_toggle2: BooleanLike;
+ liq_msg_toggle3: BooleanLike;
+ liq_msg_toggle4: BooleanLike;
+ liq_msg_toggle5: BooleanLike;
+ liq_msg1: BooleanLike;
+ liq_msg2: BooleanLike;
+ liq_msg3: BooleanLike;
+ liq_msg4: BooleanLike;
+ liq_msg5: BooleanLike;
};
export type prefData = {
@@ -156,16 +253,32 @@ export type prefData = {
show_vore_fx: BooleanLike;
can_be_drop_prey: BooleanLike;
can_be_drop_pred: BooleanLike;
+ latejoin_vore: BooleanLike;
+ latejoin_prey: BooleanLike;
+ no_spawnpred_warning: BooleanLike;
+ no_spawnprey_warning: BooleanLike;
+ no_spawnpred_warning_time: number;
+ no_spawnprey_warning_time: number;
+ no_spawnpred_warning_save: BooleanLike;
+ no_spawnprey_warning_save: BooleanLike;
allow_spontaneous_tf: BooleanLike;
- allow_inbelly_spawning: BooleanLike;
step_mechanics_active: BooleanLike;
pickup_mechanics_active: BooleanLike;
+ strip_mechanics_active: BooleanLike;
noisy: BooleanLike;
+ liq_rec: BooleanLike;
+ liq_giv: BooleanLike;
+ liq_apply: BooleanLike;
+ consume_liquid_belly: BooleanLike;
+ autotransferable: BooleanLike;
+ noisy_full: BooleanLike;
+ selective_active: string;
allow_mind_transfer: BooleanLike;
drop_vore: BooleanLike;
slip_vore: BooleanLike;
stumble_vore: BooleanLike;
throw_vore: BooleanLike;
+ phase_vore: BooleanLike;
food_vore: BooleanLike;
digest_pain: BooleanLike;
nutrition_message_visible: BooleanLike;
@@ -174,8 +287,38 @@ export type prefData = {
weight_messages: string[];
eating_privacy_global: BooleanLike;
allow_mimicry: BooleanLike;
+ belly_rub_target: string | null;
vore_sprite_color: { stomach: string; 'taur belly': string };
vore_sprite_multiply: { stomach: BooleanLike; 'taur belly': BooleanLike };
+ soulcatcher_allow_capture: BooleanLike;
+ soulcatcher_allow_transfer: BooleanLike;
+ soulcatcher_allow_deletion: BooleanLike;
+ soulcatcher_allow_takeover: BooleanLike;
+};
+
+export type soulcatcherData = {
+ active: BooleanLike;
+ name: string;
+ caught_souls: DropdownEntry[];
+ selected_sfx: string;
+ selected_soul: string;
+ interior_design: string;
+ catch_self: BooleanLike;
+ taken_over: BooleanLike;
+ catch_prey: BooleanLike;
+ catch_drain: BooleanLike;
+ catch_ghost: BooleanLike;
+ ext_hearing: BooleanLike;
+ ext_vision: BooleanLike;
+ mind_backups: BooleanLike;
+ sr_projecting: BooleanLike;
+ show_vore_sfx: BooleanLike;
+ see_sr_projecting: BooleanLike;
+};
+
+export type DropdownEntry = {
+ displayText: string;
+ value: string;
};
export type localPrefs = {
@@ -191,10 +334,13 @@ export type localPrefs = {
toggle_slip_vore: preferenceData;
toggle_stumble_vore: preferenceData;
toggle_throw_vore: preferenceData;
+ toggle_phase_vore: preferenceData;
toggle_food_vore: preferenceData;
toggle_digest_pain: preferenceData;
- inbelly_spawning: preferenceData;
+ spawnbelly: preferenceData;
+ spawnprey: preferenceData;
noisy: preferenceData;
+ noisy_full: preferenceData;
resize: preferenceData;
steppref: preferenceData;
vore_fx: preferenceData;
@@ -204,8 +350,20 @@ export type localPrefs = {
mind_transfer: preferenceData;
examine_nutrition: preferenceData;
examine_weight: preferenceData;
+ strippref: preferenceData;
eating_privacy_global: preferenceData;
allow_mimicry: preferenceData;
+ autotransferable: preferenceData;
+ liquid_receive: preferenceData;
+ liquid_give: preferenceData;
+ liquid_apply: preferenceData;
+ toggle_consume_liquid_belly: preferenceData;
+ no_spawnpred_warning: preferenceData;
+ no_spawnprey_warning: preferenceData;
+ soulcatcher: preferenceData;
+ soulcatcher_transfer: preferenceData;
+ soulcatcher_takeover: preferenceData;
+ soulcatcher_delete: preferenceData;
};
export type preferenceData = {
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyString.tsx b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyString.tsx
index 81f94c66ef6..045e8c19243 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyString.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyString.tsx
@@ -1,6 +1,10 @@
import { ItemModeSpan, ModeSpan } from './constants';
-import type { Belly } from './types';
-import { GetAddons } from './VorePanelExportBellyStringHelpers';
+import { Belly } from './types';
+import {
+ GetAddons,
+ GetAutotransferFlags,
+ GetLiquidAddons,
+} from './VorePanelExportBellyStringHelpers';
// prettier-ignore
export const generateBellyString = (belly: Belly, index: number) => {
@@ -26,6 +30,7 @@ export const generateBellyString = (belly: Belly, index: number) => {
digest_clone,
can_taste,
+ is_feedable,
contaminates,
contamination_flavor,
contamination_color,
@@ -36,8 +41,16 @@ export const generateBellyString = (belly: Belly, index: number) => {
emote_active,
emote_time,
shrink_grow_size,
+ vorespawn_blacklist,
+ vorespawn_whitelist,
+ vorespawn_absorbed,
egg_type,
+ egg_name,
selective_preference,
+ recycling,
+ storing_nutrition,
+ entrance_logs,
+ item_digest_logs,
// Messages
struggle_messages_outside,
@@ -65,6 +78,10 @@ export const generateBellyString = (belly: Belly, index: number) => {
primary_transfer_messages_prey,
secondary_transfer_messages_owner,
secondary_transfer_messages_prey,
+ primary_autotransfer_messages_owner,
+ primary_autotransfer_messages_prey,
+ secondary_autotransfer_messages_owner,
+ secondary_autotransfer_messages_prey,
digest_chance_messages_owner,
digest_chance_messages_prey,
absorb_chance_messages_owner,
@@ -97,6 +114,24 @@ export const generateBellyString = (belly: Belly, index: number) => {
fancy_vore,
vore_sound,
release_sound,
+ sound_volume,
+ noise_freq,
+
+ // Visuals
+ affects_vore_sprites,
+ count_absorbed_prey_for_sprite,
+ resist_triggers_animation,
+ size_factor_for_sprite,
+ belly_sprite_to_affect,
+
+ // Visuals (Belly Fullscreens Preview and Coloring)
+ belly_fullscreen,
+ belly_fullscreen_color,
+ belly_fullscreen_color2,
+ belly_fullscreen_color3,
+ belly_fullscreen_color4,
+ belly_fullscreen_alpha,
+ colorization_enabled,
// Visuals (Vore FX)
disable_hud,
@@ -116,6 +151,68 @@ export const generateBellyString = (belly: Belly, index: number) => {
absorbchance,
digestchance,
+
+ belchchance,
+
+ // Interactions (Auto-Transfer)
+ autotransferwait,
+ autotransferchance,
+ autotransferlocation,
+ autotransferextralocation,
+ autotransferchance_secondary,
+ autotransferlocation_secondary,
+ autotransferextralocation_secondary,
+ autotransfer_enabled,
+ autotransfer_min_amount,
+ autotransfer_max_amount,
+ autotransfer_whitelist,
+ autotransfer_blacklist,
+ autotransfer_secondary_whitelist,
+ autotransfer_secondary_blacklist,
+ autotransfer_whitelist_items,
+ autotransfer_blacklist_items,
+ autotransfer_secondary_whitelist_items,
+ autotransfer_secondary_blacklist_items,
+
+ // Liquid Options
+ show_liquids,
+ reagentbellymode,
+ reagent_chosen,
+ reagent_name,
+ reagent_transfer_verb,
+ gen_time_display,
+ custom_max_volume,
+ vorefootsteps_sounds,
+ reagent_mode_flag_list,
+ liquid_overlay,
+ max_liquid_level,
+ reagent_touches,
+ mush_overlay,
+ mush_color,
+ mush_alpha,
+ max_mush,
+ min_mush,
+ item_mush_val,
+ custom_reagentcolor,
+ custom_reagentalpha,
+ metabolism_overlay,
+ metabolism_mush_ratio,
+ max_ingested,
+ custom_ingested_color,
+ custom_ingested_alpha,
+
+ // Liquid Messages
+ liquid_fullness1_messages,
+ liquid_fullness2_messages,
+ liquid_fullness3_messages,
+ liquid_fullness4_messages,
+ liquid_fullness5_messages,
+
+ fullness1_messages,
+ fullness2_messages,
+ fullness3_messages,
+ fullness4_messages,
+ fullness5_messages,
} = belly;
let result = '';
@@ -324,6 +421,30 @@ export const generateBellyString = (belly: Belly, index: number) => {
});
result += '';
+ result += '';
+ primary_autotransfer_messages_owner?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '';
+ primary_autotransfer_messages_prey?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '';
+ secondary_autotransfer_messages_owner?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '';
+ secondary_autotransfer_messages_prey?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
result += '';
digest_chance_messages_owner?.forEach((msg) => {
result += msg + '
';
@@ -510,6 +631,7 @@ export const generateBellyString = (belly: Belly, index: number) => {
result += '
';
result += '
';
result += '- Can Taste: ' + (can_taste ? 'Yes' : 'No') + '
';
+ result += '- Feedable: ' + (is_feedable ? 'Yes' : 'No') + '
';
result += '- Contaminates: ' + (contaminates ? 'Yes' : 'No') + '
';
result += '- Contamination Flavor: ' + contamination_flavor + '
';
result += '- Contamination Color: ' + contamination_color + '
';
@@ -520,6 +642,9 @@ export const generateBellyString = (belly: Belly, index: number) => {
result += '- Idle Emotes: ' + (emote_active ? 'Active' : 'Inactive') + '
';
result += '- Idle Emote Delay: ' + emote_time + ' seconds
';
result += '- Shrink/Grow Size: ' + shrink_grow_size * 100 + '%
';
+ result += '- Vore Spawn Blacklist: ' + (vorespawn_blacklist ? 'Yes' : 'No') + '
';
+ result += '- Vore Spawn Whitelist: ' + (vorespawn_whitelist.length ? vorespawn_whitelist.join(', ') : 'Anyone!') + '
';
+ result += '- Vore Spawn Absorbed: ' + (vorespawn_absorbed === 0 ? 'No' : vorespawn_absorbed === 1 ? 'Yes' : 'Prey Choice') + '
';
result += '- Egg Type: ' + egg_type + '
';
result += '- Selective Mode Preference: ' + selective_preference + '
';
result += '
';
@@ -556,6 +681,18 @@ export const generateBellyString = (belly: Belly, index: number) => {
result += '
';
+ result += '
Vore Sprites';
+ result += '
';
+ result += '- Affect Vore Sprites: ' + (affects_vore_sprites ? 'Yes' : 'No') + '
';
+ result += '- Count Absorbed prey for vore sprites: ' + (count_absorbed_prey_for_sprite ? 'Yes' : 'No') + '
';
+ result += '- Animation when prey resist: ' + (resist_triggers_animation ? 'Yes' : 'No') + '
';
+ result += '- Vore Sprite Size Factor: ' + size_factor_for_sprite + '
';
+ result += '- Belly Sprite to affect: ' + belly_sprite_to_affect + '
';
+ result += '
';
+ result += '
Belly Fullscreens Preview and Coloring';
+ result += '
';
+ result += '- Color: ' + belly_fullscreen_color + '';
+ result += '
';
result += '
Vore FX';
result += '
';
result += '- Disable Prey HUD: ' + (disable_hud ? 'Yes' : 'No') + '
';
@@ -586,10 +723,126 @@ export const generateBellyString = (belly: Belly, index: number) => {
result += '- Secondary Transfer Location: ' + transferlocation_secondary + '
';
result += '- Absorb Chance: ' + absorbchance + '%
';
result += '- Digest Chance: ' + digestchance + '%
';
+ result += '- Belch Chance: ' + belchchance + '%
';
+ result += '
';
+ result += '
';
+ result += '
Auto-Transfer Options (' +
+ (autotransfer_enabled ? 'Enabled' : 'Disabled') +
+ ')';
+ result += '
';
+ result += '- Auto-Transfer Time: ' + autotransferwait / 10 + 's
';
+ result += '- Auto-Transfer Chance: ' + autotransferchance + '%
';
+ result += '- Auto-Transfer Location: ' + autotransferlocation + '
';
+ result += '- Auto-Transfer Chance: ' + autotransferchance_secondary + '%
';
+ result += '- Auto-Transfer Location: ' + autotransferlocation_secondary + '
';
+ result += '- Auto-Transfer Min Amount: ' + autotransfer_min_amount + '
';
+ result += '- Auto-Transfer Max Amount: ' + autotransfer_max_amount + '
';
+ result += '- Auto-Transfer Primary Chance: ' + autotransferchance + '%
';
+ result += '- Auto-Transfer Primary Location: ' + autotransferlocation + '
';
+ result += '- Auto-Transfer Primary Location Extras: ' + autotransferextralocation.join(', ') + '
';
+ result += '- Auto-Transfer Primary Whitelist (Mobs): ' + GetAutotransferFlags(autotransfer_whitelist, true) + '
';
+ result += '- Auto-Transfer Primary Whitelist (Items): ' + GetAutotransferFlags(autotransfer_whitelist_items, true) + '
';
+ result += '- Auto-Transfer Primary Blacklist (Mobs): ' + GetAutotransferFlags(autotransfer_blacklist, false) + '
';
+ result += '- Auto-Transfer Primary Blacklist (Items): ' + GetAutotransferFlags(autotransfer_blacklist_items, false) + '
';
+ result += '- Auto-Transfer Secondary Chance: ' + autotransferchance_secondary + '%
';
+ result += '- Auto-Transfer Secondary Location: ' + autotransferlocation_secondary + '
';
+ result += '- Auto-Transfer Secondary Location Extras: ' + autotransferextralocation_secondary.join(', ') + '
';
+ result += '- Auto-Transfer Secondary Whitelist (Mobs): ' + GetAutotransferFlags(autotransfer_secondary_whitelist, true) + '
';
+ result += '- Auto-Transfer Secondary Whitelist (Items): ' + GetAutotransferFlags(autotransfer_secondary_whitelist_items, true) + '
';
+ result += '- Auto-Transfer Secondary Blacklist (Mobs): ' + GetAutotransferFlags(autotransfer_secondary_blacklist, false) + '
';
+ result += '- Auto-Transfer Secondary Blacklist (Items): ' + GetAutotransferFlags(autotransfer_secondary_blacklist_items, false) + '
';
result += '
';
result += '
';
// END INTERACTIONS
+ // LIQUID OPTIONS
+
+ result += '';
+ result += '';
+
+ result += '
';
+ result += '
';
+ result += '
';
+ result += '- Generate Liquids: ' + (reagentbellymode ? 'On' : 'Off') + '
';
+ result += '- Liquid Type: ' + reagent_chosen + '
';
+ result += '- Liquid Name: ' + reagent_name + '
';
+ result += '- Transfer Verb: ' + reagent_transfer_verb + '
';
+ result += '- Generation Time: ' + gen_time_display + '
';
+ result += '- Liquid Capacity: ' + custom_max_volume + '
';
+ result += '- Slosh Sounds: ' + (vorefootsteps_sounds ? 'On' : 'Off') + '
';
+ result += '- Liquid Addons: ' + GetLiquidAddons(reagent_mode_flag_list) + '
';
+ result += '
';
+ result += '
';
+
+ // END LIQUID OPTIONS
+ // LIQUID MESSAGES
+
+ result += '';
+ result += '';
+
+ result += '
';
+ result += '
';
+
+ result += '
'; // Start Div liquidMessagesTabpanel
+ result += '
';
+
+ result += '
';
+ result += '
';
+
+ result += '
';
+ fullness1_messages?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '
';
+ fullness2_messages?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '
';
+ fullness3_messages?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '
';
+ fullness4_messages?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '
';
+ fullness5_messages?.forEach((msg) => {
+ result += msg + '
';
+ });
+ result += '
';
+
+ result += '
';
+ result += '
';
+ result += '
'; // End Div liquidMessagesTabpanel
+
+ result += '
';
+
+ // END LIQUID MESSAGES
result += '';
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyStringHelpers.tsx b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyStringHelpers.tsx
index 54b40cf5109..7b2278fef0f 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyStringHelpers.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportBellyStringHelpers.tsx
@@ -1,4 +1,6 @@
-import { AddonIcon } from './constants';
+import { BooleanLike } from 'tgui-core/react';
+
+import { AddonIcon, AutotransferFlagIcon, ReagentAddonIcon } from './constants';
export const GetAddons = (addons: string[]) => {
let result: string[] = [];
@@ -19,3 +21,50 @@ export const GetAddons = (addons: string[]) => {
return result;
};
+
+export const GetLiquidAddons = (addons: string[]) => {
+ let result: string[] = [];
+
+ addons?.forEach((addon) => {
+ result.push(
+ '' +
+ addon +
+ '',
+ );
+ });
+
+ if (result.length === 0) {
+ result.push('No Addons Set');
+ }
+
+ return result;
+};
+
+export const GetAutotransferFlags = (
+ addons: string[],
+ whitelist: BooleanLike,
+) => {
+ let result: string[] = [];
+
+ addons?.forEach((addon) => {
+ result.push(
+ '' +
+ addon +
+ '',
+ );
+ });
+
+ if (result.length === 0) {
+ if (whitelist) {
+ result.push('Everything');
+ } else {
+ result.push('Nothing');
+ }
+ }
+
+ return result;
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportDownload.tsx b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportDownload.tsx
index b4e82281487..6361c4048c8 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportDownload.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/VorePanelExportDownload.tsx
@@ -1,11 +1,11 @@
import { useBackend } from 'tgui/backend';
-import type { Data } from './types';
+import { Data } from './types';
import { generateBellyString } from './VorePanelExportBellyString';
import { getCurrentTimestamp } from './VorePanelExportTimestamp';
export const downloadPrefs = (extension: string) => {
- const { act, data } = useBackend();
+ const { data } = useBackend();
const { db_version, db_repo, mob_name, bellies } = data;
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/constants.ts b/tgui/packages/tgui/interfaces/VorePanelExport/constants.ts
index 5b07412443a..cf3f9ce9246 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/constants.ts
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/constants.ts
@@ -17,6 +17,8 @@ export const ItemModeSpan = {
'Digest (Food Only)':
'Item: Digest (Food Only)',
Digest: 'Item: Digest',
+ 'Digest (Dispersed Damage)':
+ 'Item: Digest (Dispersed Damage)',
};
export const AddonIcon = {
@@ -28,3 +30,33 @@ export const AddonIcon = {
'Jams Sensors': 'bi-wifi-off',
'Complete Absorb': '',
};
+
+export const ReagentAddonIcon = {
+ 'Produce Liquids': '',
+ 'Digestion Liquids': '',
+ 'Absorption Liquids': '',
+ 'Draining Liquids': '',
+};
+
+export const AutotransferFlagIcon = {
+ Creatures: '',
+ Absorbed: '',
+ Carbon: '',
+ Silicon: '',
+ Mobs: '',
+ Animals: '',
+ Mice: '',
+ Dead: '',
+ 'Digestable Creatures': '',
+ 'Absorbable Creatures': '',
+ 'Full Health': '',
+ Items: '',
+ Trash: '',
+ Eggs: '',
+ Remains: '',
+ 'Indigestible Items': '',
+ 'Recyclable Items': '',
+ Ores: '',
+ 'Clothes and Bags': '',
+ Food: '',
+};
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/index.tsx b/tgui/packages/tgui/interfaces/VorePanelExport/index.tsx
index f9b6336b051..a2bb9b119b6 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/index.tsx
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/index.tsx
@@ -2,7 +2,7 @@ import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Button, Section } from 'tgui-core/components';
-import type { Data } from './types';
+import { Data } from './types';
import { downloadPrefs } from './VorePanelExportDownload';
export const VorePanelExport = () => {
diff --git a/tgui/packages/tgui/interfaces/VorePanelExport/types.ts b/tgui/packages/tgui/interfaces/VorePanelExport/types.ts
index a05c4964d47..cc6da7fff6e 100644
--- a/tgui/packages/tgui/interfaces/VorePanelExport/types.ts
+++ b/tgui/packages/tgui/interfaces/VorePanelExport/types.ts
@@ -29,6 +29,7 @@ export type Belly = {
digest_clone: number;
can_taste: BooleanLike;
+ is_feedable: BooleanLike;
contaminates: BooleanLike;
contamination_flavor: string;
contamination_color: string;
@@ -39,8 +40,16 @@ export type Belly = {
emote_active: BooleanLike;
emote_time: number;
shrink_grow_size: number;
+ vorespawn_blacklist: BooleanLike;
+ vorespawn_whitelist: string[];
+ vorespawn_absorbed: number;
egg_type: string;
+ egg_name: string;
selective_preference: string;
+ recycling: BooleanLike;
+ storing_nutrition: BooleanLike;
+ entrance_logs: BooleanLike;
+ item_digest_logs: BooleanLike;
// Messages
struggle_messages_outside: string[];
@@ -68,6 +77,10 @@ export type Belly = {
primary_transfer_messages_prey: string[];
secondary_transfer_messages_owner: string[];
secondary_transfer_messages_prey: string[];
+ primary_autotransfer_messages_owner: string[];
+ primary_autotransfer_messages_prey: string[];
+ secondary_autotransfer_messages_owner: string[];
+ secondary_autotransfer_messages_prey: string[];
digest_chance_messages_owner: string[];
digest_chance_messages_prey: string[];
absorb_chance_messages_owner: string[];
@@ -100,6 +113,30 @@ export type Belly = {
fancy_vore: BooleanLike;
vore_sound: string;
release_sound: string;
+ sound_volume: number;
+ noise_freq: number;
+
+ // Visuals
+ affects_vore_sprites: BooleanLike;
+ count_absorbed_prey_for_sprite: BooleanLike;
+ absorbed_multiplier: number;
+ count_liquid_for_sprite: BooleanLike;
+ liquid_multiplier: number;
+ count_items_for_sprite: BooleanLike;
+ item_multiplier: number;
+ health_impacts_size: BooleanLike;
+ resist_triggers_animation: BooleanLike;
+ size_factor_for_sprite: number;
+ belly_sprite_to_affect: string;
+
+ // Visuals (Belly Fullscreens Preview and Coloring)
+ belly_fullscreen: string;
+ belly_fullscreen_color: string;
+ belly_fullscreen_color2: string;
+ belly_fullscreen_color3: string;
+ belly_fullscreen_color4: string;
+ belly_fullscreen_alpha: number;
+ colorization_enabled: BooleanLike;
// Visuals (Vore FX)
disable_hud: BooleanLike;
@@ -119,4 +156,65 @@ export type Belly = {
absorbchance: number;
digestchance: number;
+ belchchance: number;
+
+ // Interactions (Auto-Transfer)
+ autotransferwait: number;
+ autotransferchance: number;
+ autotransferlocation: string;
+ autotransferextralocation: string[];
+ autotransfer_enabled: BooleanLike;
+ autotransferchance_secondary: number;
+ autotransferlocation_secondary: string;
+ autotransferextralocation_secondary: string[];
+ autotransfer_min_amount: number;
+ autotransfer_max_amount: number;
+ autotransfer_whitelist: string[];
+ autotransfer_blacklist: string[];
+ autotransfer_secondary_whitelist: string[];
+ autotransfer_secondary_blacklist: string[];
+ autotransfer_whitelist_items: string[];
+ autotransfer_blacklist_items: string[];
+ autotransfer_secondary_whitelist_items: string[];
+ autotransfer_secondary_blacklist_items: string[];
+
+ // Liquid Options
+ show_liquids: BooleanLike;
+ reagentbellymode: BooleanLike;
+ reagent_chosen: string;
+ reagent_name: string;
+ reagent_transfer_verb: string;
+ gen_time_display: string;
+ custom_max_volume: number;
+ vorefootsteps_sounds: BooleanLike;
+ reagent_mode_flag_list: string[];
+ liquid_overlay: BooleanLike;
+ max_liquid_level: number;
+ reagent_touches: BooleanLike;
+ mush_overlay: BooleanLike;
+ mush_color: string;
+ mush_alpha: number;
+ max_mush: number;
+ min_mush: number;
+ item_mush_val: number;
+ custom_reagentcolor: string;
+ custom_reagentalpha: number;
+ metabolism_overlay: BooleanLike;
+ metabolism_mush_ratio: number;
+ max_ingested: number;
+ custom_ingested_color: string;
+ custom_ingested_alpha: number;
+
+ // Liquid Messages
+ liquid_fullness1_messages: BooleanLike;
+ liquid_fullness2_messages: BooleanLike;
+ liquid_fullness3_messages: BooleanLike;
+ liquid_fullness4_messages: BooleanLike;
+ liquid_fullness5_messages: BooleanLike;
+
+ fullness1_messages: string[];
+ fullness2_messages: string[];
+ fullness3_messages: string[];
+ fullness4_messages: string[];
+ fullness5_messages: string[];
};
diff --git a/vorestation.dme b/vorestation.dme
index 08d7aa068f3..33405b678ce 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -44,6 +44,7 @@
#include "code\__defines\assets.dm"
#include "code\__defines\atmos.dm"
#include "code\__defines\atoms_movable.dm"
+#include "code\__defines\belly_messages.dm"
#include "code\__defines\belly_modes_vr.dm"
#include "code\__defines\blueprints.dm"
#include "code\__defines\borg_overlays.dm"
@@ -100,6 +101,7 @@
#include "code\__defines\mecha.dm"
#include "code\__defines\misc.dm"
#include "code\__defines\mobs.dm"
+#include "code\__defines\nif.dm"
#include "code\__defines\nifsoft.dm"
#include "code\__defines\objects.dm"
#include "code\__defines\observer.dm"
@@ -133,6 +135,8 @@
#include "code\__defines\shuttle.dm"
#include "code\__defines\simple_mob.dm"
#include "code\__defines\size.dm"
+#include "code\__defines\slosh.dm"
+#include "code\__defines\soulcatcher.dm"
#include "code\__defines\sound.dm"
#include "code\__defines\span.dm"
#include "code\__defines\species_languages.dm"
@@ -173,8 +177,8 @@
#include "code\__defines\dcs\signals.dm"
#include "code\__defines\dcs\signals\signals_client.dm"
#include "code\__defines\dcs\signals\signals_subsystem.dm"
-#include "code\__defines\dcs\signals\signals_mobs\signals_mob_main.dm"
#include "code\__defines\dcs\signals\signals_turf.dm"
+#include "code\__defines\dcs\signals\signals_mobs\signals_mob_main.dm"
#include "code\__defines\traits\_traits.dm"
#include "code\__defines\traits\declarations.dm"
#include "code\__defines\traits\sources.dm"
@@ -548,6 +552,7 @@
#include "code\datums\elements\footstep.dm"
#include "code\datums\elements\footstep_override.dm"
#include "code\datums\elements\light_blocking.dm"
+#include "code\datums\elements\slosh.dm"
#include "code\datums\elements\turf_transparency.dm"
#include "code\datums\game_masters\_common.dm"
#include "code\datums\helper_datums\construction_datum.dm"
@@ -1296,6 +1301,7 @@
#include "code\game\objects\effects\decals\Cleanable\misc.dm"
#include "code\game\objects\effects\decals\Cleanable\robots.dm"
#include "code\game\objects\effects\decals\Cleanable\tracks.dm"
+#include "code\game\objects\effects\decals\Cleanable\vore.dm"
#include "code\game\objects\effects\decals\posters\bs12.dm"
#include "code\game\objects\effects\decals\posters\polarisposters.dm"
#include "code\game\objects\effects\decals\posters\polarisposters_vr.dm"
@@ -2009,6 +2015,7 @@
#include "code\modules\asset_cache\asset_cache_client.dm"
#include "code\modules\asset_cache\asset_cache_item.dm"
#include "code\modules\asset_cache\asset_list.dm"
+#include "code\modules\asset_cache\assets\belly_assets.dm"
#include "code\modules\asset_cache\assets\browser.dm"
#include "code\modules\asset_cache\assets\circuits.dm"
#include "code\modules\asset_cache\assets\cloning.dm"
@@ -2142,6 +2149,7 @@
#include "code\modules\client\preference_setup\loadout\loadout_general.dm"
#include "code\modules\client\preference_setup\loadout\loadout_gloves.dm"
#include "code\modules\client\preference_setup\loadout\loadout_head.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_item_tf.dm"
#include "code\modules\client\preference_setup\loadout\loadout_mask.dm"
#include "code\modules\client\preference_setup\loadout\loadout_shoes.dm"
#include "code\modules\client\preference_setup\loadout\loadout_smoking.dm"
@@ -3985,6 +3993,7 @@
#include "code\modules\reagents\Chemistry-Metabolism.dm"
#include "code\modules\reagents\holder\distilling.dm"
#include "code\modules\reagents\holder\holder.dm"
+#include "code\modules\reagents\holder\vorebelly.dm"
#include "code\modules\reagents\hoses\connector.dm"
#include "code\modules\reagents\hoses\hose.dm"
#include "code\modules\reagents\hoses\hose_connector.dm"
@@ -4041,6 +4050,7 @@
#include "code\modules\reagents\reagents\drugs.dm"
#include "code\modules\reagents\reagents\food_drinks.dm"
#include "code\modules\reagents\reagents\food_drinks_vr.dm"
+#include "code\modules\reagents\reagents\liquid_belly.dm"
#include "code\modules\reagents\reagents\medicine.dm"
#include "code\modules\reagents\reagents\medicine_vr.dm"
#include "code\modules\reagents\reagents\modifiers.dm"
@@ -4346,6 +4356,7 @@
#include "code\modules\vore\eating\belly_dat_vr.dm"
#include "code\modules\vore\eating\belly_import.dm"
#include "code\modules\vore\eating\belly_messages.dm"
+#include "code\modules\vore\eating\belly_obj_liquids.dm"
#include "code\modules\vore\eating\belly_obj_vr.dm"
#include "code\modules\vore\eating\bellymodes_datum_vr.dm"
#include "code\modules\vore\eating\bellymodes_vr.dm"
@@ -4360,11 +4371,15 @@
#include "code\modules\vore\eating\silicon_vr.dm"
#include "code\modules\vore\eating\simple_animal_vr.dm"
#include "code\modules\vore\eating\slipvore_vr.dm"
+#include "code\modules\vore\eating\soulcatcher.dm"
+#include "code\modules\vore\eating\soulcatcher_mob.dm"
+#include "code\modules\vore\eating\soulcatcher_observer.dm"
#include "code\modules\vore\eating\stumblevore_vr.dm"
#include "code\modules\vore\eating\transforming_vr.dm"
#include "code\modules\vore\eating\vertical_nom_vr.dm"
#include "code\modules\vore\eating\vore_vr.dm"
#include "code\modules\vore\eating\vorehooks_vr.dm"
+#include "code\modules\vore\eating\vorepanel_prefs.dm"
#include "code\modules\vore\eating\vorepanel_vr.dm"
#include "code\modules\vore\fluffstuff\custom_boxes_vr.dm"
#include "code\modules\vore\fluffstuff\custom_clothes_vr.dm"