diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm new file mode 100644 index 00000000000..fd5ad3d8b26 --- /dev/null +++ b/code/__defines/belly_modes_vr.dm @@ -0,0 +1,13 @@ +// Belly Mode Constants +#define DM_HOLD "Hold" +#define DM_DIGEST "Digest" +#define DM_HEAL "Heal" +#define DM_ABSORB "Absorb" +#define DM_TRANSFORM_MALE "Transform (Male)" //I totally don't have a thing for TF. Nope! ~CK +#define DM_TRANSFORM_FEMALE "Transform (Female)" +#define DM_TRANSFORM_KEEP_GENDER "Transform (Keep Gender)" +#define DM_TRANSFORM_CHANGE_SPECIES "Transform (Change Species)" +#define DM_TRANSFORM_CHANGE_SPECIES_EGG "Transform (Change Species) (EGG)" +#define DM_TRANSFORM_KEEP_GENDER_EGG "Transform (Keep Gender) (EGG)" +#define DM_TRANSFORM_MALE_EGG "Transform (Male) (EGG)" +#define DM_TRANSFORM_FEMALE_EGG "Transform (Female) (EGG)" diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm new file mode 100644 index 00000000000..b344368341e --- /dev/null +++ b/code/_helpers/global_lists_vr.dm @@ -0,0 +1,63 @@ +//Important items that are preserved when people are digested, cryo'd, etc. +var/global/list/important_items = list( + /obj/item/weapon/hand_tele, + /obj/item/weapon/card/id/captains_spare, + /obj/item/device/aicard, + /obj/item/device/mmi, + /obj/item/device/paicard, + /obj/item/weapon/gun, + /obj/item/weapon/pinpointer, + /obj/item/clothing/suit, + /obj/item/clothing/shoes/magboots, + /obj/item/blueprints, + /obj/item/clothing/head/helmet/space, + /obj/item/weapon/storage/internal, + /obj/item/weapon/disk/nuclear) + + /* TODOPOLARIS - Depends on porting object + /obj/item/weapon/card/id/digested) + */ + +var/global/list/digestion_sounds = list( + 'sound/vore/digest1.ogg', + 'sound/vore/digest2.ogg', + 'sound/vore/digest3.ogg', + 'sound/vore/digest4.ogg', + 'sound/vore/digest5.ogg', + 'sound/vore/digest6.ogg', + 'sound/vore/digest7.ogg', + 'sound/vore/digest8.ogg', + 'sound/vore/digest9.ogg', + 'sound/vore/digest10.ogg', + 'sound/vore/digest11.ogg', + 'sound/vore/digest12.ogg') + +var/global/list/death_sounds = list( + 'sound/vore/death1.ogg', + 'sound/vore/death2.ogg', + 'sound/vore/death3.ogg', + 'sound/vore/death4.ogg', + 'sound/vore/death5.ogg', + 'sound/vore/death6.ogg', + 'sound/vore/death7.ogg', + 'sound/vore/death8.ogg', + 'sound/vore/death9.ogg', + 'sound/vore/death10.ogg') + +var/global/list/vore_sounds = list( + "Gulp" = 'sound/vore/gulp.ogg', + "Insert" = 'sound/vore/insert.ogg', + "Insertion1" = 'sound/vore/insertion1.ogg', + "Insertion2" = 'sound/vore/insertion2.ogg', + "Insertion3" = 'sound/vore/insertion3.ogg', + "Schlorp" = 'sound/vore/schlorp.ogg', + "Squish1" = 'sound/vore/squish1.ogg', + "Squish2" = 'sound/vore/squish2.ogg', + "Squish3" = 'sound/vore/squish3.ogg', + "Squish4" = 'sound/vore/squish4.ogg') + +var/global/list/struggle_sounds = list( + "Squish1" = 'sound/vore/squish1.ogg', + "Squish2" = 'sound/vore/squish2.ogg', + "Squish3" = 'sound/vore/squish3.ogg', + "Squish4" = 'sound/vore/squish4.ogg') \ No newline at end of file diff --git a/code/_helpers/text_vr.dm b/code/_helpers/text_vr.dm new file mode 100644 index 00000000000..a16b6c0cfc3 --- /dev/null +++ b/code/_helpers/text_vr.dm @@ -0,0 +1,9 @@ +//Readds quotes and apostrophes to HTML-encoded strings +/proc/readd_quotes(var/t) + var/list/repl_chars = list(""" = "\"","'" = "'") + for(var/char in repl_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+5) + index = findtext(t, char) + return t diff --git a/code/_helpers/type2type_vr.dm b/code/_helpers/type2type_vr.dm new file mode 100644 index 00000000000..e6df5318061 --- /dev/null +++ b/code/_helpers/type2type_vr.dm @@ -0,0 +1,107 @@ +/* +// Contains VOREStation type2type functions +// list2text - takes delimiter and returns text +// text2list - takes delimiter, and creates list +// +*/ + +// Concatenates a list of strings into a single string. A seperator may optionally be provided. +/proc/list2text(list/ls, sep) + if (ls.len <= 1) // Early-out code for empty or singleton lists. + return ls.len ? ls[1] : "" + + var/l = ls.len // Made local for sanic speed. + var/i = 0 // Incremented every time a list index is accessed. + + if (sep <> null) + // Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc... + #define S1 sep, ls[++i] + #define S4 S1, S1, S1, S1 + #define S16 S4, S4, S4, S4 + #define S64 S16, S16, S16, S16 + + . = "[ls[++i]]" // Make sure the initial element is converted to text. + + // Having the small concatenations come before the large ones boosted speed by an average of at least 5%. + if (l-1 & 0x01) // 'i' will always be 1 here. + . = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2. + if (l-i & 0x02) + . = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4. + if (l-i & 0x04) + . = text("[][][][][][][][][]", ., S4) // And so on.... + if (l-i & 0x08) + . = text("[][][][][][][][][][][][][][][][][]", ., S4, S4) + if (l-i & 0x10) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16) + if (l-i & 0x20) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16) + if (l-i & 0x40) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64) + while (l > i) // Chomp through the rest of the list, 128 elements at a time. + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) + + #undef S64 + #undef S16 + #undef S4 + #undef S1 + else + // Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc... + #define S1 ls[++i] + #define S4 S1, S1, S1, S1 + #define S16 S4, S4, S4, S4 + #define S64 S16, S16, S16, S16 + + . = "[ls[++i]]" // Make sure the initial element is converted to text. + + if (l-1 & 0x01) // 'i' will always be 1 here. + . += S1 // Append 1 element if the remaining elements are not a multiple of 2. + if (l-i & 0x02) + . = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4. + if (l-i & 0x04) + . = text("[][][][][]", ., S4) // And so on... + if (l-i & 0x08) + . = text("[][][][][][][][][]", ., S4, S4) + if (l-i & 0x10) + . = text("[][][][][][][][][][][][][][][][][]", ., S16) + if (l-i & 0x20) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16) + if (l-i & 0x40) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64) + while (l > i) // Chomp through the rest of the list, 128 elements at a time. + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) + + #undef S64 + #undef S16 + #undef S4 + #undef S1 + +// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator) +/proc/text2list(text, delimiter="\n") + var/delim_len = length(delimiter) + if (delim_len < 1) + return list(text) + + . = list() + var/last_found = 1 + var/found + + do + found = findtext(text, delimiter, last_found, 0) + . += copytext(text, last_found, found) + last_found = found + delim_len + while (found) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 093975051b5..36304a13dc2 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -13,6 +13,7 @@ /mob/living/attackby(obj/item/I, mob/user) user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Code if(istype(I) && ismob(user)) I.attack(src, user) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index c3162b030cd..76122a914ba 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -26,6 +26,8 @@ //Random events (vomiting etc) handle_random_events() + attempt_vr(src,"handle_internal_contents",args) //VOREStation Code + . = 1 //Handle temperature/pressure differences between body and environment diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index f45fd574cea..9b60baaa9c0 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -47,6 +47,7 @@ dead_mob_list += src else living_mob_list += src + hook_vr("mob_new",list(src)) //VOREStation Code ..() /mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) diff --git a/code/modules/vore/eating/belly_vr.dm b/code/modules/vore/eating/belly_vr.dm new file mode 100644 index 00000000000..942de92674c --- /dev/null +++ b/code/modules/vore/eating/belly_vr.dm @@ -0,0 +1,362 @@ +// +// The belly object is what holds onto a mob while they're inside a predator. +// It takes care of altering the pred's decription, digesting the prey, relaying struggles etc. +// It is not, however, for printing messages about entering/exiting the belly. That is done in voretype etc. +// + +// +// Parent type of all the various "belly" varieties. +// +/datum/belly + var/name // Name of this location + var/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_ABSORB) // Possible digest modes + var/list/transform_modes = list(DM_TRANSFORM_MALE,DM_TRANSFORM_FEMALE,DM_TRANSFORM_KEEP_GENDER,DM_TRANSFORM_CHANGE_SPECIES,DM_TRANSFORM_CHANGE_SPECIES_EGG,DM_TRANSFORM_KEEP_GENDER_EGG,DM_TRANSFORM_MALE_EGG,DM_TRANSFORM_FEMALE_EGG) + var/inside_flavor // Flavor text description of inside sight/sound/smells/feels. + var/vore_sound = 'sound/vore/gulp.ogg' // Sound when ingesting someone + var/vore_verb = "ingest" // Verb for eating with this in messages + 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/emoteTime = 600 // How long between stomach emotes at prey + var/digest_brute = 2 // Brute damage per tick in digestion mode + var/digest_burn = 3 // Burn damage per tick in digestion mode + var/digest_tickrate = 3 // Modulus this of air controller tick number to iterate gurgles on + var/immutable = 0 // Prevents this belly from being deleted + + var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest. + var/tmp/mob/living/owner // The mob whose belly this is. + var/tmp/list/internal_contents = list() // People/Things you've eaten into this belly! + var/tmp/is_full // Flag for if digested remeans are present. (for disposal messages) + var/tmp/recent_struggle = 0 // Flag to prevent struggle emote spam + var/tmp/emotePend = 0 // If there's already a spawned thing counting for the next emote + + // Don't forget to watch your commas at the end of each line if you change these. + var/list/struggle_messages_outside = list( + "%pred's %belly wobbles with a squirming meal.", + "%pred's %belly jostles with movement.", + "%pred's %belly briefly swells outward as someone pushes from inside.", + "%pred's %belly fidgets with a trapped victim.", + "%pred's %belly jiggles with motion from inside.", + "%pred's %belly sloshes around.", + "%pred's %belly gushes softly.", + "%pred's %belly lets out a wet squelch.") + + var/list/struggle_messages_inside = list( + "Your useless squirming only causes %pred's slimy %belly to squelch over your body.", + "Your struggles only cause %pred's %belly to gush softly around you.", + "Your movement only causes %pred's %belly to slosh around you.", + "Your motion causes %pred's %belly to jiggle.", + "You fidget around inside of %pred's %belly.", + "You shove against the walls of %pred's %belly, making it briefly swell outward.", + "You jostle %pred's %belly with movement.", + "You squirm inside of %pred's %belly, making it wobble around.") + + var/list/digest_messages_owner = list( + "You feel %prey's body succumb to your digestive system, which breaks it apart into soft slurry.", + "You hear a lewd glorp as your %belly muscles grind %prey into a warm pulp.", + "Your %belly lets out a rumble as it melts %prey into sludge.", + "You feel a soft gurgle as %prey's body loses form in your %belly. They're nothing but a soft mass of churning slop now.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your thighs.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your rump.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your belly.", + "Your %belly groans as %prey falls apart into a thick soup. You can feel their remains soon flowing deeper into your body to be absorbed.", + "Your %belly kneads on every fiber of %prey, softening them down into mush to fuel your next hunt.", + "Your %belly churns %prey down into a hot slush. You can feel the nutrients coursing through your digestive track with a series of long, wet glorps.") + + var/list/digest_messages_prey = list( + "Your body succumbs to %pred's digestive system, which breaks you apart into soft slurry.", + "%pred's %belly lets out a lewd glorp as their muscles grind you into a warm pulp.", + "%pred's %belly lets out a rumble as it melts you into sludge.", + "%pred feels a soft gurgle as your body loses form in their %belly. You're nothing but a soft mass of churning slop now.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's thighs.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's rump.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's belly.", + "%pred's %belly groans as you fall apart into a thick soup. Your remains soon flow deeper into %pred's body to be absorbed.", + "%pred's %belly kneads on every fiber of your body, softening you down into mush to fuel their next hunt.", + "%pred's %belly churns you down into a hot slush. Your nutrient-rich remains course through their digestive track with a series of long, wet glorps.") + + var/list/examine_messages = list( + "They have something solid in their %belly!", + "It looks like they have something in their %belly!") + + //Mostly for being overridden on precreated bellies on mobs. Could be VV'd into + //a carbon's belly if someone really wanted. No UI for carbons to adjust this. + var/list/emote_lists = list() + +// Constructor that sets the owning mob +/datum/belly/New(var/mob/living/owning_mob) + owner = owning_mob + +// Toggle digestion on/off and notify user of the new setting. +// If multiple digestion modes are avaliable (i.e. unbirth) then user should be prompted. +/datum/belly/proc/toggle_digestion() + return + +// Checks if any mobs are present inside the belly +// return True if the belly is empty. +/datum/belly/proc/is_empty() + return internal_contents.len == 0 + +// Release all contents of this belly into the owning mob's location. +// If that location is another mob, contents are transferred into whichever of its bellies the owning mob is in. +// Returns the number of mobs so released. +/datum/belly/proc/release_all_contents() + var/tick = 0 //easiest way to check if the list has anything + for (var/atom/movable/M in internal_contents) + if(istype(M,/mob/living)) + var/mob/living/ML = M + if(ML.absorbed) + continue + + M.loc = owner.loc // Move the belly contents into the same location as belly's owner. + src.internal_contents -= M // Remove from the belly contents + + if (isliving(owner.loc)) // This makes sure that the mob behaves properly if released into another mob + var/mob/living/carbon/loc_mob = owner.loc + for (var/bellytype in loc_mob.vore_organs) + var/datum/belly/belly = loc_mob.vore_organs[bellytype] + if (owner in belly.internal_contents) + belly.internal_contents += M + tick++ + owner.visible_message("[owner] expels everything from their [lowertext(name)]!") + return tick + +// Release a specific atom from the contents of this belly into the owning mob's location. +// If that location is another mob, the atom is transferred into whichever of its bellies the owning mob is in. +// Returns the number of atoms so released. +/datum/belly/proc/release_specific_contents(var/atom/movable/M) + if (!(M in internal_contents)) + return 0 // They weren't in this belly anyway + + M.loc = owner.loc // Move the belly contents into the same location as belly's owner. + src.internal_contents -= M // Remove from the belly contents + + if(istype(M,/mob/living)) + var/mob/living/ML = M + if(ML.absorbed) + ML.absorbed = 0 + ML.reagents = new/datum/reagents(1000,M) //Human reagent datums hold 1000 + var/datum/reagents/OR = owner.reagents + var/absorbed_count = 2 //Prey that we were, plus the pred gets a portion + for(var/mob/living/P in internal_contents) + if(P.absorbed) + absorbed_count++ + + OR.trans_to(ML,OR.total_volume / absorbed_count) + + var/datum/belly/B = check_belly(M.loc) + if(B) + B.internal_contents += M + + owner.visible_message("[owner] expels [M] from their [lowertext(name)]!") + owner.update_icons() + return 1 + +// Actually perform the mechanics of devouring the tasty prey. +// The purpose of this method is to avoid duplicate code, and ensure that all necessary +// steps are taken. +/datum/belly/proc/nom_mob(var/mob/prey, var/mob/user) + if (prey.buckled) + prey.buckled.unbuckle_mob() + + prey.loc = owner + internal_contents += prey + + if(inside_flavor) + prey << "[inside_flavor]" + +// Get the line that should show up in Examine message if the owner of this belly +// is examined. By making this a proc, we not only take advantage of polymorphism, +// 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. +/datum/belly/proc/get_examine_msg() + if(internal_contents.len && examine_messages.len) + var/formatted_message + var/raw_message = pick(examine_messages) + + formatted_message = replacetext(raw_message,"%belly",lowertext(name)) + + return("[formatted_message]
") + +// The next function gets the messages set on the belly, in human-readable format. +// This is useful in customization boxes and such. The delimiter right now is \n\n so +// in message boxes, this looks nice and is easily delimited. +/datum/belly/proc/get_messages(var/type, var/delim = "\n\n") + ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em") + var/list/raw_messages + + switch(type) + if("smo") + raw_messages = struggle_messages_outside + if("smi") + raw_messages = struggle_messages_inside + if("dmo") + raw_messages = digest_messages_owner + if("dmp") + raw_messages = digest_messages_prey + if("em") + raw_messages = examine_messages + + var/messages = list2text(raw_messages,delim) + return messages + +// The next function sets the messages on the belly, from human-readable var +// replacement strings and linebreaks as delimiters (two \n\n by default). +// They also sanitize the messages. +/datum/belly/proc/set_messages(var/raw_text, var/type, var/delim = "\n\n") + ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em") + + var/list/raw_list = text2list(html_encode(raw_text),delim) + if(raw_list.len > 10) + raw_list.Cut(11) + log_debug("[owner] tried to set [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 [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("smo") + struggle_messages_outside = raw_list + if("smi") + struggle_messages_inside = raw_list + if("dmo") + digest_messages_owner = raw_list + if("dmp") + digest_messages_prey = raw_list + if("em") + examine_messages = raw_list + + 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. +// Indigestable items are removed, and M is deleted. +/datum/belly/proc/digestion_death(var/mob/living/M) + is_full = 1 + M.death(1) + internal_contents -= M + + // If digested prey is also a pred... anyone inside their bellies gets moved up. + if (is_vore_predator(M)) + var/vore/pred_capable/P = M + for (var/bellytype in P.vore_organs) + var/datum/belly/belly = P.vore_organs[bellytype] + for (var/obj/SubPrey in belly.internal_contents) + SubPrey.loc = src.owner + internal_contents += SubPrey + if (istype(SubPrey, /mob)) + SubPrey << "As [M] melts away around you, you find yourself in [owner]'s [name]" + + //Drop all items into the belly. + if (config.items_survive_digestion) + for (var/obj/item/W in M) + _handle_digested_item(W) + + //Reagent transfer + if(M.reagents && istype(M.reagents,/datum/reagents)) + var/datum/reagents/RL = M.reagents + RL.trans_to(owner,RL.total_volume*0.5) + + // Delete the digested mob + qdel(M) + +// Recursive method - To recursively scan thru someone's inventory for digestable/indigestable. +/datum/belly/proc/_handle_digested_item(var/obj/item/W) + // PDA's are handled specially in order to get the ID out of them. + if (istype(W, /obj/item/device/pda)) + var/obj/item/device/pda/PDA = W + if (PDA.id) + W = PDA.id + PDA.id = null + qdel(PDA) + + if (istype(W, /obj/item/weapon/card/id)) + // Keep IDs around, but destroy them! + var/obj/item/weapon/card/id/ID = W + ID.desc = "A partially digested card that has seen better days. Much of it's data has been destroyed." + ID.icon_state = "digested" + ID.access = list() // No access + ID.loc = src.owner + internal_contents += ID + else if (!_is_digestable(W)) + W.loc = src.owner + internal_contents += W + else + for (var/obj/item/SubItem in W) + _handle_digested_item(SubItem) + qdel(W) + +/datum/belly/proc/_is_digestable(var/obj/item/I) + for (var/T in important_items) + if(istype(I, T)) + return 0 + return 1 + +// Handle a mob being absorbed +/datum/belly/proc/absorb_living(var/mob/living/M) + M.absorbed = 1 + M << "[owner]'s [name] absorbs your body, making you part of them." + owner << "Your [name] absorbs [M]'s body, making them part of you." + + //Reagent sharing for absorbed with pred + var/datum/reagents/OR = owner.reagents + var/datum/reagents/PR = M.reagents + + PR.trans_to(owner,PR.total_volume) + M.reagents = OR + del(PR) + + //This is probably already the case, but for sub-prey, it won't be. + M.loc = owner + + //Seek out absorbed prey of the prey, absorb them too. + //This in particular will recurse oddly because if there is absorbed prey of prey of prey... + //it will just move them up one belly. This should never happen though since... when they were + //absobred, they should have been absorbed as well! + for(var/I in M.vore_organs) + var/datum/belly/B = M.vore_organs[I] + for(var/mob/living/Mm in B.internal_contents) + if(Mm.absorbed) + internal_contents += Mm + B.internal_contents -= Mm + absorb_living(Mm) + +//Handle a mob struggling +// Called from /mob/living/carbon/relaymove() +/datum/belly/proc/relay_struggle(var/mob/living/user, var/direction) + if (!(user in internal_contents) || recent_struggle) + return // User is not in this belly, or struggle too soon. + + recent_struggle = 1 + spawn(25) + recent_struggle = 0 + + //if(prob(80)) //Using the cooldown above to prevent spam instead + var/struggle_outer_message = pick(struggle_messages_outside) + var/struggle_user_message = pick(struggle_messages_inside) + + struggle_outer_message = replacetext(struggle_outer_message,"%pred",owner) + struggle_outer_message = replacetext(struggle_outer_message,"%prey",user) + struggle_outer_message = replacetext(struggle_outer_message,"%belly",lowertext(name)) + + struggle_user_message = replacetext(struggle_user_message,"%pred",owner) + struggle_user_message = replacetext(struggle_user_message,"%prey",user) + struggle_user_message = replacetext(struggle_user_message,"%belly",lowertext(name)) + + struggle_outer_message = "" + struggle_outer_message + "" + struggle_user_message = "" + struggle_user_message + "" + + for(var/mob/M in hearers(4, owner)) + M.show_message(struggle_outer_message, 2) // hearable + user << struggle_user_message + + var/strsound = pick(struggle_sounds) + playsound(user.loc, strsound, 50, 1) diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm new file mode 100644 index 00000000000..aa7fbbc71a1 --- /dev/null +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -0,0 +1,1794 @@ +// Process the predator's effects upon the contents of its belly (i.e digestion/transformation etc) +// Called from /mob/living/Life() proc. +/datum/belly/proc/process_Life() + +///////////////////////////// TIMER ///////////////////////////// + if(!internal_contents.len || air_master.current_cycle%3 != 1) + return + +/////////////////////////// Auto-Emotes /////////////////////////// + if((digest_mode in emote_lists) && !emotePend) + emotePend = 1 + + spawn(emoteTime) + var/list/EL = emote_lists[digest_mode] + for(var/mob/living/M in internal_contents) + M << "[pick(EL)]" + src.emotePend = 0 + +//////////////////////// Absorbed Handling //////////////////////// + for(var/mob/living/M in internal_contents) + if(M.absorbed) + M.Weaken(5) + +///////////////////////////// DM_HOLD ///////////////////////////// + if(digest_mode == DM_HOLD) + return //Pretty boring, huh + +//////////////////////////// DM_DIGEST //////////////////////////// + if(digest_mode == DM_DIGEST) + + if(prob(50)) //Was SO OFTEN. AAAA. + var/churnsound = pick(digestion_sounds) + for(var/mob/hearer in range(1,owner)) + hearer << sound(churnsound,volume=80) + + for (var/mob/living/M in internal_contents) + //Pref protection! + if (!M.digestable || M.absorbed) + continue + + //Person just died in guts! + if(M.stat == DEAD) + var/digest_alert_owner = pick(digest_messages_owner) + var/digest_alert_prey = pick(digest_messages_prey) + + //Replace placeholder vars + digest_alert_owner = replacetext(digest_alert_owner,"%pred",owner) + digest_alert_owner = replacetext(digest_alert_owner,"%prey",M) + digest_alert_owner = replacetext(digest_alert_owner,"%belly",lowertext(name)) + + digest_alert_prey = replacetext(digest_alert_prey,"%pred",owner) + digest_alert_prey = replacetext(digest_alert_prey,"%prey",M) + digest_alert_prey = replacetext(digest_alert_prey,"%belly",lowertext(name)) + + //Send messages + owner << "" + digest_alert_owner + "" + M << "" + digest_alert_prey + "" + + owner.nutrition += 20 // so eating dead mobs gives you *something*. + var/deathsound = pick(death_sounds) + for(var/mob/hearer in range(1,owner)) + hearer << deathsound + digestion_death(M) + owner.update_icons() + continue + + // Deal digestion damage (and feed the pred) + if(!(M.status_flags & GODMODE)) + M.adjustBruteLoss(2) + M.adjustFireLoss(3) + + /* POLARISTODO - Depends on weight and scale + var/offset + if (M.weight > 137) + offset = 1 + ((M.weight - 137) / 137) + if (M.weight < 137) + offset = (137 - M.weight) / 137 + var/difference = owner.playerscale / M.playerscale + if(offset) // If any different than default weight, multiply the % of offset. + owner.nutrition += offset*(10/difference) + else + owner.nutrition += (10/difference) + */ + + return + + +//////////////////////////// DM_ABSORB //////////////////////////// + if(digest_mode == DM_ABSORB) + + for (var/mob/living/M in internal_contents) + + if(prob(10)) //Less often than gurgles. People might leave this on forever. + var/absorbsound = pick(digestion_sounds) + M << sound(absorbsound,volume=80) + owner << sound(absorbsound,volume=80) + + if(M.absorbed) + continue + + if(M.nutrition >= 4) //Drain them until there's no nutrients left. Slowly "absorb" them. + M.nutrition -= 3 + owner.nutrition += 3 + else if(M.nutrition < 4) //When they're finally drained. + absorb_living(M) + + return + +///////////////////////////// DM_HEAL ///////////////////////////// + if(digest_mode == DM_HEAL) + if(prob(50)) //Wet heals! + var/healsound = pick(digestion_sounds) + for(var/mob/hearer in range(1,owner)) + hearer << sound(healsound,volume=80) + + for (var/mob/living/M in internal_contents) + if(M.stat != DEAD) + if(owner.nutrition > 90 && (M.health < M.maxHealth)) + M.adjustBruteLoss(-5) + M.adjustFireLoss(-5) + owner.nutrition -= 2 + if(M.nutrition <= 400) + M.nutrition += 1 + return + +/* POLARISTODO - Depends on Taurs, and egg objects. + +///////////////////////////// DM_TRANSFORM_MALE ///////////////////////////// + if(digest_mode == DM_TRANSFORM_MALE && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + var/TFchance = prob(10) + if(TFchance == 1) + + var/TFmodify = rand(1,3) + if(TFmodify == 1 && P.r_eyes != O.r_eyes || P.g_eyes != O.g_eyes || P.b_eyes != O.b_eyes) + P.r_eyes = O.r_eyes + P.g_eyes = O.g_eyes + P.b_eyes = O.b_eyes + P << "You feel lightheaded and drowsy..." + owner << "Your belly feels warm as your womb makes subtle changes to your captive's body." + P.update_body() + + if(TFmodify == 2 && P.r_hair != O.r_hair || P.g_hair != O.g_hair || P.b_hair != O.b_hair || P.r_skin != O.r_skin || P.g_skin != O.g_skin || P.b_skin != O.b_skin) + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + + if(TFmodify == 3 && P.gender != MALE) + P.gender = MALE + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_body() + + if(O.nutrition > 0) + O.nutrition -= 2 + if(P.nutrition < 400) + P.nutrition += 1 + return + + +///////////////////////////// DM_TRANSFORM_FEMALE ///////////////////////////// + if(digest_mode == DM_TRANSFORM_FEMALE && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + var/TFchance = prob(10) + if(TFchance == 1) + var/TFmodify = rand(1,3) + if(TFmodify == 1 && P.r_eyes != O.r_eyes || P.g_eyes != O.g_eyes || P.b_eyes != O.b_eyes) + P.r_eyes = O.r_eyes + P.g_eyes = O.g_eyes + P.b_eyes = O.b_eyes + P << "You feel lightheaded and drowsy..." + owner << "Your belly feels warm as your womb makes subtle changes to your captive's body." + P.update_body() + + if(TFmodify == 2 && P.r_hair != O.r_hair || P.g_hair != O.g_hair || P.b_hair != O.b_hair || P.r_skin != O.r_skin || P.g_skin != O.g_skin || P.b_skin != O.b_skin) + P.r_hair = O.r_hair + P.g_hair = O.g_hair + P.b_hair = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + + if(TFmodify == 3 && P.gender != FEMALE) + P.f_style = "Shaved" + P.gender = FEMALE + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_body() + + if(O.nutrition > 0) + O.nutrition -= 2 + if(P.nutrition < 400) + P.nutrition += 1 + return + +///////////////////////////// DM_TRANSFORM_KEEP_GENDER ///////////////////////////// + if(digest_mode == DM_TRANSFORM_KEEP_GENDER && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + var/TFchance = prob(10) + if(TFchance == 1) + + var/TFmodify = rand(1,2) + if(TFmodify == 1 && P.r_eyes != O.r_eyes || P.g_eyes != O.g_eyes || P.b_eyes != O.b_eyes) + P.r_eyes = O.r_eyes + P.g_eyes = O.g_eyes + P.b_eyes = O.b_eyes + P << "You feel lightheaded and drowsy..." + owner << "Your belly feels warm as your womb makes subtle changes to your captive's body." + P.update_body() + + if(TFmodify == 2 && P.r_hair != O.r_hair || P.g_hair != O.g_hair || P.b_hair != O.b_hair || P.r_skin != O.r_skin || P.g_skin != O.g_skin || P.b_skin != O.b_skin) + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + + if(O.nutrition > 0) + O.nutrition -= 2 + if(P.nutrition < 400) + P.nutrition += 1 + return + +///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES ///////////////////////////// + if(digest_mode == DM_TRANSFORM_CHANGE_SPECIES && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + var/TFchance = prob(10) + if(TFchance == 1) + var/TFmodify = rand(1,3) + if(TFmodify == 1 && P.r_eyes != O.r_eyes || P.g_eyes != O.g_eyes || P.b_eyes != O.b_eyes) + P.r_eyes = O.r_eyes + P.g_eyes = O.g_eyes + P.b_eyes = O.b_eyes + P << "You feel lightheaded and drowsy..." + owner << "Your belly feels warm as your womb makes subtle changes to your captive's body." + P.update_body() + + if(TFmodify == 2 && P.r_hair != O.r_hair || P.g_hair != O.g_hair || P.b_hair != O.b_hair || P.r_skin != O.r_skin || P.g_skin != O.g_skin || P.b_skin != O.b_skin) + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + //Omitted clause : P.race_icon != O.race_icon + //No idea how to work with that one, species system got changed a lot + //Also this makes it similar to the previous one until fixed + + if(TFmodify == 3 && P.r_hair != O.r_hair || P.g_hair != O.g_hair || P.b_hair != O.b_hair || P.r_skin != O.r_skin || P.g_skin != O.g_skin || P.b_skin != O.b_skin || P.taur != O.taur || P.r_taur != O.r_taur || P.g_taur != O.g_taur || P.b_taur != O.b_taur) + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P << "You lose sensation of your body, feeling only the warmth of the womb... " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body." + P.update_hair() + P.update_body() + P.update_tail_showing() + + if(O.nutrition > 0) + O.nutrition -= 2 + if(P.nutrition < 400) + P.nutrition += 1 + return + + +///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES_EGG ///////////////////////////// + if(digest_mode == DM_TRANSFORM_CHANGE_SPECIES_EGG && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + if(O.species.name == "Unathi") + var/obj/structure/closet/secure_closet/egg/unathi/J = new /obj/structure/closet/secure_closet/egg/unathi(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Tajara") + var/obj/structure/closet/secure_closet/egg/tajaran/J = new /obj/structure/closet/secure_closet/egg/tajaran(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Skrell") + var/obj/structure/closet/secure_closet/egg/skrell/J = new /obj/structure/closet/secure_closet/egg/skrell(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Sergal") + var/obj/structure/closet/secure_closet/egg/sergal/J = new /obj/structure/closet/secure_closet/egg/sergal(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Akula") + var/obj/structure/closet/secure_closet/egg/shark/J = new /obj/structure/closet/secure_closet/egg/shark(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Nevrean") + var/obj/structure/closet/secure_closet/egg/nevrean/J = new /obj/structure/closet/secure_closet/egg/nevrean(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Human") + var/obj/structure/closet/secure_closet/egg/human/J = new /obj/structure/closet/secure_closet/egg/human(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Slime Person") + var/obj/structure/closet/secure_closet/egg/slime/J = new /obj/structure/closet/secure_closet/egg/slime(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.taur = O.taur + P.r_taur = O.r_taur + P.g_taur = O.g_taur + P.b_taur = O.b_taur + P.h_style = "Bedhead" + P.species = O.species + P.custom_species = O.custom_species + P << "You lose sensation of your body, feeling only the warmth of the womb as you're encased in an egg. " + owner << "Your belly shifts as your womb makes dramatic changes to your captive's body as you encase them in an egg." + P.update_hair() + P.update_body() + P.update_tail_showing() + P.loc = J + J.name = "[defined_species] egg" + return + +///////////////////////////// DM_TRANSFORM_KEEP_GENDER_EGG ///////////////////////////// + if(digest_mode == DM_TRANSFORM_KEEP_GENDER_EGG && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + if(O.species.name == "Unathi") + var/obj/structure/closet/secure_closet/egg/unathi/J = new /obj/structure/closet/secure_closet/egg/unathi(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Tajara") + var/obj/structure/closet/secure_closet/egg/tajaran/J = new /obj/structure/closet/secure_closet/egg/tajaran(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Skrell") + var/obj/structure/closet/secure_closet/egg/skrell/J = new /obj/structure/closet/secure_closet/egg/skrell(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Sergal") + var/obj/structure/closet/secure_closet/egg/sergal/J = new /obj/structure/closet/secure_closet/egg/sergal(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Akula") + var/obj/structure/closet/secure_closet/egg/shark/J = new /obj/structure/closet/secure_closet/egg/shark(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Nevrean") + var/obj/structure/closet/secure_closet/egg/nevrean/J = new /obj/structure/closet/secure_closet/egg/nevrean(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Human") + var/obj/structure/closet/secure_closet/egg/human/J = new /obj/structure/closet/secure_closet/egg/human(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + + if(O.species.name == "Slime Person") + var/obj/structure/closet/secure_closet/egg/slime/J = new /obj/structure/closet/secure_closet/egg/slime(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P << "Your body tingles all over..." + owner << "Your belly tingles as your womb makes noticeable changes to your captive's body." + P.update_hair() + P.update_body() + P.loc = J + J.name = "[defined_species] egg" + return + +///////////////////////////// DM_TRANSFORM_MALE_EGG ///////////////////////////// + if(digest_mode == DM_TRANSFORM_MALE_EGG && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + if(O.species.name == "Unathi") + var/obj/structure/closet/secure_closet/egg/unathi/J = new /obj/structure/closet/secure_closet/egg/unathi(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Tajara") + var/obj/structure/closet/secure_closet/egg/tajaran/J = new /obj/structure/closet/secure_closet/egg/tajaran(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Skrell") + var/obj/structure/closet/secure_closet/egg/skrell/J = new /obj/structure/closet/secure_closet/egg/skrell(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Sergal") + var/obj/structure/closet/secure_closet/egg/sergal/J = new /obj/structure/closet/secure_closet/egg/sergal(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Akula") + var/obj/structure/closet/secure_closet/egg/shark/J = new /obj/structure/closet/secure_closet/egg/shark(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Nevrean") + var/obj/structure/closet/secure_closet/egg/nevrean/J = new /obj/structure/closet/secure_closet/egg/nevrean(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Human") + var/obj/structure/closet/secure_closet/egg/human/J = new /obj/structure/closet/secure_closet/egg/human(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Slime Person") + var/obj/structure/closet/secure_closet/egg/slime/J = new /obj/structure/closet/secure_closet/egg/slime(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = MALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + return + +///////////////////////////// DM_TRANSFORM_FEMALE_EGG ///////////////////////////// + if(digest_mode == DM_TRANSFORM_FEMALE_EGG && ishuman(owner)) + for (var/mob/living/carbon/human/P in internal_contents) + if(P.stat) + continue + + var/mob/living/carbon/human/O = owner + + if(O.species.name == "Unathi") + var/obj/structure/closet/secure_closet/egg/unathi/J = new /obj/structure/closet/secure_closet/egg/unathi(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Tajara") + var/obj/structure/closet/secure_closet/egg/tajaran/J = new /obj/structure/closet/secure_closet/egg/tajaran(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Skrell") + var/obj/structure/closet/secure_closet/egg/skrell/J = new /obj/structure/closet/secure_closet/egg/skrell(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Sergal") + var/obj/structure/closet/secure_closet/egg/sergal/J = new /obj/structure/closet/secure_closet/egg/sergal(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Akula") + var/obj/structure/closet/secure_closet/egg/shark/J = new /obj/structure/closet/secure_closet/egg/shark(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Nevrean") + var/obj/structure/closet/secure_closet/egg/nevrean/J = new /obj/structure/closet/secure_closet/egg/nevrean(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Human") + var/obj/structure/closet/secure_closet/egg/human/J = new /obj/structure/closet/secure_closet/egg/human(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + + if(O.species.name == "Slime Person") + var/obj/structure/closet/secure_closet/egg/slime/J = new /obj/structure/closet/secure_closet/egg/slime(O.loc) + if (O.custom_species) + var/defined_species = O.custom_species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + J.desc = "This egg has a very unique look to it." + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + else + var/defined_species = O.species + P.r_hair = O.r_hair + P.r_facial = O.r_hair + P.g_hair = O.g_hair + P.g_facial = O.g_hair + P.b_hair = O.b_hair + P.b_facial = O.b_hair + P.r_skin = O.r_skin + P.g_skin = O.g_skin + P.b_skin = O.b_skin + P.h_style = "Bedhead" + P.gender = FEMALE + P.loc = J + J.name = "[defined_species] egg" + P << "Your body feels very strange..." + owner << "Your belly feels strange as your womb alters your captive's gender." + P.update_hair() + P.update_body() + return + +*/ diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm new file mode 100644 index 00000000000..8124c818c19 --- /dev/null +++ b/code/modules/vore/eating/living_vr.dm @@ -0,0 +1,265 @@ +///////////////////// Mob Living ///////////////////// +/mob/living + var/digestable = 1 // Can the mob be digested inside a belly? + var/datum/belly/vore_selected // Default to no vore capability. + var/list/vore_organs = list() // List of vore containers inside a mob + var/absorbed = 0 // If a mob is absorbed into another + var/weight = 100 // Weight for mobs for weightgain system + +// +// Hook for generic creation of stuff on new creatures +// +/hook/living_new/proc/vore_setup(mob/living/M) + M.verbs += /mob/living/proc/insidePanel + M.verbs += /mob/living/proc/escapeOOC + + //Creates at least the typical 'stomach' on every mob. + spawn(20) //Wait a couple of seconds to make sure copy_to or whatever has gone + //In Polaris, when a character joins (not spawns), it creates some sort of 'Force' /mob/living/silicon/ai + //then immediately deletes it. I'm not sure why, but we should make sure M is still real 2 seconds later. + if(M && !M.vore_organs.len) + var/datum/belly/B = new /datum/belly(M) + B.immutable = 1 + B.name = "Stomach" + B.inside_flavor = "It appears to be rather warm and wet. Makes sense, considering it's inside \the [M.name]." + M.vore_organs[B.name] = B + M.vore_selected = B.name + + //Simple_animal gets emotes. move this to that hook instead? + if(istype(src,/mob/living/simple_animal)) + B.emote_lists[DM_HOLD] = list( + "The insides knead at you gently for a moment.", + "The guts glorp wetly around you as some air shifts.", + "Your predator takes a deep breath and sighs, shifting you somewhat.", + "The stomach squeezes you tight for a moment, then relaxes.", + "During a moment of quiet, breathing becomes the most audible thing.", + "The warm slickness surrounds and kneads on you.") + + B.emote_lists[DM_DIGEST] = list( + "The caustic acids eat away at your form.", + "The acrid air burns at your lungs.", + "Without a thought for you, the stomach grinds inwards painfully.", + "The guts treat you like food, squeezing to press more acids against you.", + "The onslaught against your body doesn't seem to be letting up; you're food now.", + "The insides work on you like they would any other food.") + + //Return 1 to hook-caller + return 1 + +// +// Handle being clicked, perhaps with something to devour +// +/mob/living/proc/vore_attackby(obj/item/I,mob/user) + //Things we can eat with vore code + var/list/vore_items = list( + /obj/item/weapon/grab, + /obj/item/weapon/holder) + + if(!(I.type in vore_items)) + return 0 + + switch(I.type) + //Handle case: /obj/item/weappn/grab + if(/obj/item/weapon/grab) + var/obj/item/weapon/grab/G = I + + //Has to be aggressive grab, has to be living click-er and non-silicon grabbed + if((G.state >= GRAB_AGGRESSIVE) && (isliving(user) && !issilicon(G.affecting))) + + var/mob/living/attacker = user // Typecast to living + + // src is the mob clicked on + // If grab clicked on grabber + if(src == G.assailant) + if (is_vore_predator(src)) + if (src.feed_grabbed_to_self(src, G.affecting)) + qdel(G) //Delete grab + return 1 //Return 1 to exit upper procs + else + log_debug("[attacker] attempted to feed [G.affecting] to [user] ([user.type]) but it is not predator-capable") + + // If grab clicked on grabbed + if((src == G.affecting) && (user.a_intent == I_GRAB) && (user.zone_sel.selecting == BP_TORSO)) + if (is_vore_predator(G.affecting)) + if (attacker.feed_self_to_grabbed(attacker, G.affecting)) + qdel(G) //Delete grab + return 1 //Return 1 to exit upper procs + else + log_debug("[attacker] attempted to feed [user] to [G.affecting] ([G.affecting.type]) but it is not predator-capable") + + // If grab clicked on anything else + else + if (is_vore_predator(src)) + if (attacker.feed_grabbed_to_other(attacker, G.affecting, src)) + qdel(G) //Delete grab + return 1 //Return 1 to exit upper procs + else + log_debug("[attacker] attempted to feed [G.affecting] to [src] ([src.type]) but it is not predator-capable") + + + //Handle case: /obj/item/weapon/holder + if(/obj/item/weapon/holder) + return 1 + + return 0 + + +// +// Proc for updating vore organs and digestion/healing/absorbing +// +/mob/living/proc/handle_internal_contents() + for (var/bellytype in vore_organs) + var/datum/belly/B = vore_organs[bellytype] + for(var/atom/movable/M in B.internal_contents) + if(M.loc != src) + B.internal_contents -= M + log_debug("Had to remove [M] from belly [B] in [src]") + B.process_Life() + +// +// Verb for saving vore preferences to save file +// +/mob/living/proc/save_vore_prefs() + set name = "Save Vore Prefs" + set category = "Vore" + + var/result = 0 + + if(client.prefs) + result = client.prefs.save_vore_preferences() + else + src << "You attempted to save your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev." + log_debug("[src] tried to save vore prefs but lacks a client.prefs var.") + + return result + +// +// Proc for applying vore preferences, given bellies +// +/mob/living/proc/apply_vore_prefs(var/list/bellies) + if(!bellies || bellies.len == 0) + log_debug("Tried to apply bellies to [src] and failed.") + +// +// OOC Escape code for pref-breaking or AFK preds +// +/mob/living/proc/escapeOOC() + set name = "OOC escape" + set category = "Vore" + + //You're in an animal! + if(istype(src.loc,/mob/living/simple_animal)) + var/mob/living/simple_animal/pred = src.loc + var/confirm = alert(src, "You're in a mob. Don't use this as a trick to get out of hostile animals. This is for escaping from preference-breaking and if you're otherwise unable to escape from endo. If you are in more than one pred, use this more than once.", "Confirmation", "Okay", "Cancel") + if(confirm == "Okay") + for(var/I in pred.vore_organs) + var/datum/belly/B = pred.vore_organs[I] + B.release_specific_contents(src) + + for(var/mob/living/simple_animal/SA in range(10)) + SA.prey_excludes += src + spawn(18000) + if(src && SA) + SA.prey_excludes -= src + + message_admins("[key_name(src)] used the OOC escape button to get out of [key_name(pred)] (MOB) ([pred ? "JMP" : "null"])") + pred.update_icons() + + //You're in a PC! + else if(istype(src.loc,/mob/living)) + var/mob/living/carbon/pred = src.loc + var/confirm = alert(src, "You're in a player-character. This is for escaping from preference-breaking and if your predator disconnects/AFKs. If you are in more than one pred, use this more than once. If your preferences were being broken, please admin-help as well.", "Confirmation", "Okay", "Cancel") + if(confirm == "Okay") + for(var/O in pred.vore_organs) + var/datum/belly/CB = pred.vore_organs[O] + CB.release_specific_contents(src) + message_admins("[key_name(src)] used the OOC escape button to get out of [key_name(pred)] (PC) ([pred ? "JMP" : "null"])") + +/* POLARISTODO - Depends on dogborgs + + //You're in a dogborg! + else if(istype(src.loc, /obj/item/device/dogborg/sleeper)) + var/mob/living/silicon/pred = src.loc.loc //Thing holding the belly! + var/obj/item/device/dogborg/sleeper/belly = src.loc //The belly! + + var/confirm = alert(src, "You're in a dogborg sleeper. This is for escaping from preference-breaking and if your predator disconnects/AFKs. If your preferences were being broken, please admin-help as well.", "Confirmation", "Okay", "Cancel") + if(confirm == "Okay") + message_admins("[key_name(src)] used the OOC escape button to get out of [key_name(pred)] (BORG) ([pred ? "JMP" : "null"])") + belly.go_out(src) //Just force-ejects from the borg as if they'd clicked the eject button. + +*/ + + else + src << "You aren't inside anyone, you clod." + +// +// Eating procs depending on who clicked what +// +/mob/living/proc/feed_grabbed_to_self(var/mob/living/user, var/mob/living/prey) + var/belly = user.vore_selected + return perform_the_nom(user, prey, user, belly) + +/mob/living/proc/eat_held_mob(var/mob/living/user, var/mob/living/prey, var/mob/living/pred) + var/belly + if(user != pred) + belly = input("Choose Belly") in pred.vore_organs + else + belly = pred.vore_selected + return perform_the_nom(user, prey, pred, belly) + +/mob/living/proc/feed_self_to_grabbed(var/mob/living/user, var/mob/living/pred) + var/belly = input("Choose Belly") in pred.vore_organs + return perform_the_nom(user, user, pred, belly) + +/mob/living/proc/feed_grabbed_to_other(var/mob/living/user, var/mob/living/prey, var/mob/living/pred) + var/belly = input("Choose Belly") in pred.vore_organs + return perform_the_nom(user, prey, pred, belly) + +// +// Master vore proc that actually does vore procedures +// +/mob/living/proc/perform_the_nom(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/belly) + //Sanity + if(!user || !prey || !pred || !belly || !(belly in pred.vore_organs)) + log_debug("[user] attempted to feed [prey] to [pred], via [belly] but it went wrong.") + return + + // The belly selected at the time of noms + var/datum/belly/belly_target = pred.vore_organs[belly] + var/attempt_msg = "ERROR: Vore message couldn't be created. Notify a dev. (at)" + var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)" + + // Prepare messages + if(user == pred) //Feeding someone to yourself + attempt_msg = text("[] is attemping to [] [] into their []!",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + success_msg = text("[] manages to [] [] into their []!",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + else //Feeding someone to another person + attempt_msg = text("[] is attempting to make [] [] [] into their []!",user,pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + success_msg = text("[] manages to make [] [] [] into their []!",user,pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + + // Announce that we start the attempt! + user.visible_message(attempt_msg) + + // Now give the prey time to escape... return if they did + var/swallow_time = istype(prey, /mob/living/carbon/human) ? belly_target.human_prey_swallow_time : belly_target.nonhuman_prey_swallow_time + /* POLARISTODO - Unnecessary? + if (!do_mob(user, prey)) + return 0; // User is not able to act upon prey + */ + if(!do_after(user, swallow_time)) + return 0 // Prey escpaed (or user disabled) before timer expired. + + // If we got this far, nom successful! Announce it! + user.visible_message(success_msg) + playsound(user, belly_target.vore_sound, 100, 1) + + // Actually shove prey into the belly. + belly_target.nom_mob(prey, user) + user.update_icons() + + // Inform Admins + if (pred == user) + msg_admin_attack("[key_name(pred)] ate [key_name(prey)]. ([pred ? "JMP" : "null"])") + else + msg_admin_attack("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)]. ([pred ? "JMP" : "null"])") + return 1 diff --git a/code/modules/vore/eating/simple_animal_vr.dm b/code/modules/vore/eating/simple_animal_vr.dm new file mode 100644 index 00000000000..b68ba316ddc --- /dev/null +++ b/code/modules/vore/eating/simple_animal_vr.dm @@ -0,0 +1,39 @@ +///////////////////// Simple Animal ///////////////////// +/mob/living/simple_animal + var/isPredator = 0 //Are they capable of performing and pre-defined vore actions for their species? + var/swallowTime = 30 //How long it takes to eat its prey in 1/10 of a second. The default is 3 seconds. + var/list/prey_excludes = list() //For excluding people from being eaten. + +// +// Simple nom proc for if you get ckey'd into a simple_animal mob! Avoids grabs. +// +/mob/living/proc/animal_nom(var/mob/living/T in oview(1)) + set name = "Animal Nom" + set category = "Vore" + set desc = "Since you can't grab, you get a verb!" + + feed_grabbed_to_self(src,T) + +// +// Simple proc for animals to have their digestion toggled on/off externally +// +/mob/living/simple_animal/verb/toggle_digestion() + set name = "Toggle Animal's Digestion" + set desc = "Enables digestion on this mob for 20 minutes." + set category = "Vore" + set src in oview(1) + + var/datum/belly/B = vore_organs[vore_selected] + if(faction != usr.faction) + usr << "\red This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you." + return + if(B.digest_mode == "Hold") + var/confirm = alert(usr, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will disable itself after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel") + if(confirm == "Enable") + B.digest_mode = "Digest" + spawn(12000) //12000=20 minutes + if(src) B.digest_mode = "Hold" + else + var/confirm = alert(usr, "This mob is currently set to digest all stomach contents. Do you want to disable this?", "Disabling [name]'s Digestion", "Disable", "Cancel") + if(confirm == "Disable") + B.digest_mode = "Hold" diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm new file mode 100644 index 00000000000..082a67c046f --- /dev/null +++ b/code/modules/vore/eating/vore_vr.dm @@ -0,0 +1,65 @@ + +/* +VVVVVVVV VVVVVVVV OOOOOOOOO RRRRRRRRRRRRRRRRR EEEEEEEEEEEEEEEEEEEEEE +V::::::V V::::::V OO:::::::::OO R::::::::::::::::R E::::::::::::::::::::E +V::::::V V::::::V OO:::::::::::::OO R::::::RRRRRR:::::R E::::::::::::::::::::E +V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEEEEE::::E + V:::::V V:::::V O::::::O O::::::O R::::R R:::::R E:::::E EEEEEE + V:::::V V:::::V O:::::O O:::::O R::::R R:::::R E:::::E + V:::::V V:::::V O:::::O O:::::O R::::RRRRRR:::::R E::::::EEEEEEEEEE + V:::::V V:::::V O:::::O O:::::O R:::::::::::::RR E:::::::::::::::E + V:::::V V:::::V O:::::O O:::::O R::::RRRRRR:::::R E:::::::::::::::E + V:::::V V:::::V O:::::O O:::::O R::::R R:::::R E::::::EEEEEEEEEE + V:::::V:::::V O:::::O O:::::O R::::R R:::::R E:::::E + V:::::::::V O::::::O O::::::O R::::R R:::::R E:::::E EEEEEE + V:::::::V O:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEEEE:::::E + V:::::V OO:::::::::::::OO R::::::R R:::::RE::::::::::::::::::::E + V:::V OO:::::::::OO R::::::R R:::::RE::::::::::::::::::::E + VVV OOOOOOOOO RRRRRRRR RRRRRRREEEEEEEEEEEEEEEEEEEEEE + +-Aro <3 */ + +// +// Overrides/additions to stock defines go here, as well as hooks. Sort them by +// the object they are overriding. So all /mob/living together, etc. +// +/datum/preferences + var/digestable = 1 + var/list/belly_prefs = list() + +/datum/configuration + var/items_survive_digestion = 1 //For configuring if the important_items survive digestion + +// +// Adding procs to types to support vore +// +/datum/preferences/proc/save_vore_preferences() + //POLARISTODO + return + +/datum/preferences/proc/load_vore_preferences() + //POLARISTODO + return + +// +// Check if an object is capable of eating things, based on vore_organs +// +/proc/is_vore_predator(var/mob/living/O) + if(istype(O,/mob/living)) + if(O.vore_organs.len > 0) + return 1 + + return 0 + +// +// Belly searching for simplifying other procs +// +/proc/check_belly(atom/movable/A) + if(istype(A.loc,/mob/living)) + var/mob/living/M = A.loc + for(var/I in M.vore_organs) + var/datum/belly/B = M.vore_organs[I] + if(A in B.internal_contents) + return(B) + + return 0 diff --git a/code/modules/vore/eating/vorehooks_vr.dm b/code/modules/vore/eating/vorehooks_vr.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 new file mode 100644 index 00000000000..907a2241d14 --- /dev/null +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -0,0 +1,508 @@ +// +// Vore management panel for players +// + +/mob/living/proc/insidePanel() + set name = "Vore Panel" + set category = "Vore" + + var/datum/vore_look/picker_holder = new() + picker_holder.loop = picker_holder + picker_holder.selected = vore_organs[vore_selected] + + var/dat = picker_holder.gen_ui(src) + + picker_holder.popup = new(src, "insidePanel","Inside!", 400, 600, picker_holder) + picker_holder.popup.set_content(dat) + picker_holder.popup.open() + +// +// Callback Handler for the Inside form +// +/datum/vore_look + var/datum/belly/selected + var/datum/browser/popup + var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action. + +/datum/vore_look/Topic(href,href_list[]) + if (vp_interact(href, href_list)) + popup.set_content(gen_ui(usr)) + usr << output(popup.get_content(), "insidePanel.browser") + +/datum/vore_look/proc/gen_ui(var/mob/living/user) + var/dat + + if (is_vore_predator(user.loc)) + var/vore/pred_capable/eater = user.loc + var/datum/belly/inside_belly + + //This big block here figures out where the prey is + for (var/bellytype in eater.vore_organs) + var/datum/belly/B = eater.vore_organs[bellytype] + for (var/mob/living/M in B.internal_contents) + if (M == user) + inside_belly = B + break + + //Don't display this part if we couldn't find the belly since could be held in hand. + if(inside_belly) + dat += "You are currently [user.absorbed ? "absorbed into " : "inside "] [eater]'s [inside_belly]!

" + + if(inside_belly.inside_flavor) + dat += "[inside_belly.inside_flavor]

" + + if (inside_belly.internal_contents.len > 1) + dat += "You can see the following around you:
" + for (var/atom/movable/O in inside_belly.internal_contents) + if(istype(O,/mob/living)) + var/mob/living/M = O + //That's just you + if(M == user) + continue + + //That's an absorbed person you're checking + if(M.absorbed) + if(user.absorbed) + dat += "[O]" + continue + else + continue + + //Anything else + dat += "[O]" + else + dat += "You aren't inside anyone." + + dat += "
" + + for(var/K in user.vore_organs) //Fuggin can't iterate over values + var/datum/belly/B = user.vore_organs[K] + if(B == selected) + dat += "[B.name]" + else + dat += "[B.name]" + + switch(B.digest_mode) + if(DM_HOLD) + dat += "" + if(DM_DIGEST) + dat += "" + if(DM_HEAL) + dat += "" + if(DM_ABSORB) + dat += "" + if(DM_TRANSFORM_MALE) + dat += "" + if(DM_TRANSFORM_FEMALE) + dat += "" + if(DM_TRANSFORM_KEEP_GENDER) + dat += "" + if(DM_TRANSFORM_CHANGE_SPECIES) + dat += "" + if(DM_TRANSFORM_CHANGE_SPECIES_EGG) + dat += "" + if(DM_TRANSFORM_KEEP_GENDER_EGG) + dat += "" + if(DM_TRANSFORM_MALE_EGG) + dat += "" + if(DM_TRANSFORM_FEMALE_EGG) + dat += "" + + else + dat += "" + + dat += " ([B.internal_contents.len])" + + if(user.vore_organs.len < 10) + dat += "New+" + + dat += "
" + + // Selected Belly (contents, configuration) + if(!selected) + dat += "No belly selected. Click one to select it." + else + if(selected.internal_contents.len > 0) + dat += "Contents: " + for(var/O in selected.internal_contents) + + //Mobs can be absorbed, so treat them separately from everything else + if(istype(O,/mob/living)) + var/mob/living/M = O + + //Absorbed gets special color OOoOOOOoooo + if(M.absorbed) + dat += "[O]" + continue + + //Anything else + dat += "[O]" + + //If there's more than one thing, add an [All] button + if(selected.internal_contents.len > 1) + dat += "\[All\]" + + dat += "
" + + //Belly Name Button + dat += "Name:" + dat += " '[selected.name]'" + + //Digest Mode Button + dat += "
Belly Mode:" + dat += " [selected.digest_mode]" + + //Belly verb + dat += "
Vore Verb:" + dat += " '[selected.vore_verb]'" + + //Inside flavortext + dat += "
Flavor Text:" + dat += " '[selected.inside_flavor]'" + + //Belly sound + dat += "
Set Vore Sound" + dat += "Test" + + //Belly messages + dat += "
Belly Messages" + + //Delete button + dat += "
Delete Belly" + + dat += "
" + + //Under the last HR, save and stuff. + dat += "Save Prefs" + dat += "Refresh" + + switch(user.digestable) + if(1) + dat += "Toggle Digestable" + if(0) + dat += "Toggle Digestable" + + //Returns the dat html to the vore_look + return dat + +/datum/vore_look/proc/vp_interact(href, href_list) + var/mob/living/user = usr + for(var/H in href_list) + + if(href_list["close"]) + del(src) // Cleanup + return + + if(href_list["outsidepick"]) + var/tgt = locate(href_list["outsidepick"]) + var/datum/belly/OB = locate(href_list["outsidebelly"]) + var/intent = "Examine" + + if(istype(tgt,/mob/living)) + var/mob/living/M = tgt + intent = alert("What do you want to do to them?","Query","Examine","Help Out","Devour") + switch(intent) + if("Examine") //Examine a mob inside another mob + M.examine(user) + + if("Help Out") //Help the inside-mob out + if(user.stat || user.absorbed || M.absorbed) + user << "You can't do that in your state!" + return 1 + + user << "You begin to push [M] to freedom!" + M << "[usr] begins to push you to freedom!" + M.loc << "Someone is trying to escape from inside you!" + sleep(50) + if(prob(33)) + OB.release_specific_contents(M) + usr << "You manage to help [M] to safety!" + M << "[user] pushes you free!" + M.loc << "[M] forces free of the confines of your body!" + else + user << "[M] slips back down inside despite your efforts." + M << " Even with [user]'s help, you slip back inside again." + M.loc << "Your body efficiently shoves [M] back where they belong." + + if("Devour") //Eat the inside mob + if(user.absorbed || user.stat) + user << "You can't do that in your state!" + return 1 + + if(!user.vore_selected) + user << "Pick a belly on yourself first!" + return 1 + + var/datum/belly/TB = user.vore_organs[user.vore_selected] + user << "You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!" + M << "[user] begins to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!" + M.loc << "Someone inside you is eating someone else!" + + sleep(TB.nonhuman_prey_swallow_time) + if((user in OB.internal_contents) && (M in OB.internal_contents)) + user << "You manage to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!" + M << "[user] manages to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!" + M.loc << "Someone inside you has eaten someone else!" + M.loc = user + TB.nom_mob(M) + OB.internal_contents -= M + + else if(istype(tgt,/obj/item)) + var/obj/item/T = tgt + intent = alert("What do you want to do to that?","Query","Examine","Use Hand") + switch(intent) + if("Examine") + T.examine(user) + + if("Use Hand") + if(user.stat) + user << "You can't do that in your state!" + return 1 + + user.ClickOn(T) + sleep(5) //Seems to exit too fast for the panel to update + + if(href_list["insidepick"]) + var/intent + + //Handle the [All] choice. Ugh inelegant. Someone make this pretty. + if(href_list["pickall"]) + intent = alert("Eject all, Move all?","Query","Eject all","Cancel","Move all") + switch(intent) + if("Cancel") + return 1 + + if("Eject all") + if(user.stat) + user << "You can't do that in your state!" + return 1 + + selected.release_all_contents() + playsound(user, 'sound/effects/splat.ogg', 50, 1) + + if("Move all") + if(user.stat) + user << "You can't do that in your state!" + return 1 + + var/choice = input("Move all where?","Select Belly") in user.vore_organs + "Cancel - Don't Move" + + if(choice == "Cancel - Don't Move") + return 1 + else + var/datum/belly/B = user.vore_organs[choice] + for(var/atom/movable/tgt in selected.internal_contents) + selected.internal_contents -= tgt + B.internal_contents += tgt + + tgt << "You're squished from [user]'s [selected] to their [B]!" + + for(var/mob/hearer in range(1,user)) + hearer << sound('sound/vore/squish2.ogg',volume=80) + return 1 + + + var/atom/movable/tgt = locate(href_list["insidepick"]) + intent = "Examine" + intent = alert("Examine, Eject, Move? Examine if you want to leave this box.","Query","Examine","Eject","Move") + switch(intent) + if("Examine") + tgt.examine(user) + + if("Eject") + if(user.stat) + user << "You can't do that in your state!" + return 1 + + selected.release_specific_contents(tgt) + playsound(user, 'sound/effects/splat.ogg', 50, 1) + + if("Move") + if(user.stat) + user << "You can't do that in your state!" + return 1 + + var/choice = input("Move [tgt] where?","Select Belly") in user.vore_organs + "Cancel - Don't Move" + + if(choice == "Cancel - Don't Move") + return 1 + else + var/datum/belly/B = user.vore_organs[choice] + selected.internal_contents -= tgt + B.internal_contents += tgt + + tgt << "You're squished from [user]'s [lowertext(selected.name)] to their [lowertext(B.name)]!" + for(var/mob/hearer in range(1,user)) + hearer << sound('sound/vore/squish2.ogg',volume=80) + + if(href_list["newbelly"]) + if(user.vore_organs.len >= 10) + return 1 + + var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null) + + if(length(new_name) > 12 || length(new_name) < 2) + usr << "Entered belly name is too long." + return 0 + if(new_name in user.vore_organs) + usr << "No duplicate belly names, please." + return 0 + + var/datum/belly/NB = new(user) + NB.name = new_name + user.vore_organs[new_name] = NB + selected = NB + + if(href_list["bellypick"]) + selected = locate(href_list["bellypick"]) + user.vore_selected = selected.name + + if(href_list["b_name"]) + var/new_name = html_encode(input(usr,"Belly's new name:","New Name") as text|null) + + if(length(new_name) > 12 || length(new_name) < 2) + usr << "Entered belly name length invalid (must be longer than 2, shorter than 12)." + return 0 + if(new_name in user.vore_organs) + usr << "No duplicate belly names, please." + return 0 + + user.vore_organs[new_name] = selected + user.vore_organs -= selected.name + selected.name = new_name + + if(href_list["b_mode"]) + var/list/menu_list = selected.digest_modes + if(istype(usr,/mob/living/carbon/human)) + menu_list += selected.transform_modes + + if(selected.digest_modes.len == 1) // Don't do anything + return 1 + if(selected.digest_modes.len == 2) // Just toggle... there's probably a more elegant way to do this... + var/index = selected.digest_modes.Find(selected.digest_mode) + switch(index) + if(1) + selected.digest_mode = selected.digest_modes[2] + if(2) + selected.digest_mode = selected.digest_modes[1] + else + selected.digest_mode = input("Choose Mode (currently [selected.digest_mode])") in menu_list + + if(href_list["b_desc"]) + var/new_desc = html_encode(input(usr,"Belly Description (1024 char limit):","New Description") as message|null) + new_desc = readd_quotes(new_desc) + + if(length(new_desc) > 1024) + usr << "Entered belly desc too long. 1024 character limit." + return 0 + + selected.inside_flavor = new_desc + + if(href_list["b_msgs"]) + var/list/messages = list( + "Digest Message (to prey)", + "Digest Message (to you)", + "Struggle Message (outside)", + "Struggle Message (inside)", + "Examine Message (when full)", + "Reset All To Default", + "Cancel - No Changes" + ) + + 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/choice = input(user,"Select a type to modify. Messages from each topic are pulled at random when needed.","Pick Type") in messages + 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." + + switch(choice) + if("Digest Message (to prey)") + var/new_message = input(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)",selected.get_messages("dmp")) as message + if(new_message) + selected.set_messages(new_message,"dmp") + + if("Digest Message (to you)") + var/new_message = input(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)",selected.get_messages("dmo")) as message + if(new_message) + selected.set_messages(new_message,"dmo") + + if("Struggle Message (outside)") + var/new_message = input(user,"These are sent to those nearby when prey struggles. Write them in 3rd person ('X's Y bulges')."+help,"Struggle Message (outside)",selected.get_messages("smo")) as message + if(new_message) + selected.set_messages(new_message,"smo") + + if("Struggle Message (inside)") + var/new_message = input(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)",selected.get_messages("smi")) as message + if(new_message) + selected.set_messages(new_message,"smi") + + if("Examine Message (when full)") + var/new_message = input(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging'). Do not use %pred or %prey in this type."+help,"Examine Message (when full)",selected.get_messages("em")) as message + if(new_message) + selected.set_messages(new_message,"em") + + if("Reset All To Default") + var/confirm = alert(user,"This will delete any custom messages. Are you sure?","Confirmation","DELETE","Cancel") + if(confirm == "DELETE") + selected.digest_messages_prey = initial(selected.digest_messages_prey) + selected.digest_messages_owner = initial(selected.digest_messages_owner) + selected.struggle_messages_outside = initial(selected.struggle_messages_outside) + selected.struggle_messages_inside = initial(selected.struggle_messages_inside) + + if("Cancel - No Changes") + return 1 + + if(href_list["b_verb"]) + var/new_verb = html_encode(input(usr,"New verb when eating (infinitive tense, e.g. nom or swallow):","New Verb") as text|null) + + if(length(new_verb) > 12 || length(new_verb) < 2) + usr << "Entered verb length invalid (must be longer than 2, shorter than 12)." + return 0 + + selected.vore_verb = new_verb + + if(href_list["b_sound"]) + var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") in vore_sounds + "Cancel - No Changes" + + if(choice == "Cancel") + return 1 + + selected.vore_sound = vore_sounds[choice] + + if(href_list["b_soundtest"]) + user << selected.vore_sound + + if(href_list["b_del"]) + if(selected.internal_contents.len) + usr << "Can't delete bellies with contents!" + else if(selected.immutable) + usr << "This belly is marked as undeletable." + else + var/alert = alert("Are you sure you want to delete [selected]?","Confirmation","Delete","Cancel") + if(alert == "Delete" && !selected.internal_contents.len) + user.vore_organs -= selected.name + user.vore_organs.Remove(selected) + selected = null + + if(href_list["saveprefs"]) + if(user.save_vore_prefs()) + user << "Saved belly preferences." + else + user << "ERROR: Could not save vore prefs." + log_debug("Could not save vore prefs on USER: [user].") + + if(href_list["toggledg"]) + var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable. Don't abuse this button by toggling it back and forth to extend a scene or whatever, or you'll make the admins cry. Digesting you is currently: [user.digestable ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion") + switch(choice) + if("Cancel") + return 1 + if("Allow Digestion") + user.digestable = 1 + if("Prevent Digestion") + user.digestable = 0 + + message_admins("[key_name(user)] toggled their digestability to [user.digestable] ([user ? "JMP" : "null"])") + + if(user.client.prefs) + user.client.prefs.digestable = user.digestable + + //Refresh when interacted with, returning 1 makes vore_look.Topic update + return 1 diff --git a/code/modules/vore/hook-defs_vr.dm b/code/modules/vore/hook-defs_vr.dm new file mode 100644 index 00000000000..5dd01eb3183 --- /dev/null +++ b/code/modules/vore/hook-defs_vr.dm @@ -0,0 +1,35 @@ +//The base hooks themselves + +//New() hooks +/hook/mob_new + +/hook/living_new + +/hook/carbon_new + +/hook/human_new + +/hook/simple_animal_new + +//Hooks for interactions +/hook/living_attackby + +// +//Hook helpers to expand hooks to others +// +/hook/mob_new/proc/chain_hooks(mob/M) + var/result = 1 + if(isliving(M)) + if(!hook_vr("living_new",args)) + result = 0 + + if(iscarbon(M)) + if(!hook_vr("carbon_new",args)) + result = 0 + + if(ishuman(M)) + if(!hook_vr("human_new",args)) + result = 0 + + //Return 1 to superhook + return result \ No newline at end of file diff --git a/code/modules/vore/trycatch_vr.dm b/code/modules/vore/trycatch_vr.dm new file mode 100644 index 00000000000..78e91e91ebe --- /dev/null +++ b/code/modules/vore/trycatch_vr.dm @@ -0,0 +1,62 @@ +/* +This file is for jamming single-line procs into Polaris procs. +It will prevent runtimes and allow their code to run if VOREStation's fails. +It will also log when we mess up our code rather than making it vague. + +Call it at the top of a stock proc with... + +if(attempt_vr(object,proc to call,args)) return + +...if you are replacing an entire proc. + +The proc you're attemping should return nonzero values on success. +*/ + +/proc/attempt_vr(callon, procname, list/args=null) + try + if(!callon || !procname) + error("attempt_vr: Invalid obj/proc: [callon]/[procname]") + return 0 + + var/result = call(callon,procname)(arglist(args)) + + return result + + catch(var/exception/e) + error("attempt_vr runtimed when calling [procname] on [callon].") + error("attempt_vr catch: [e] on [e.file]:[e.line]") + return 0 + +/* +This is the _vr version of calling hooks. +It's meant to have different messages, and also the try/catch block. +For when you want hooks and want to know when you ruin everything, +vs when Polaris ruins everything. + +Call it at the top of a stock proc with... + +if(hook_vr(proc,args)) return + +...if you are replacing an entire proc. + +The hooks you're calling should return nonzero values on success. +*/ +/proc/hook_vr(hook, list/args=null) + try + var/hook_path = text2path("/hook/[hook]") + if(!hook_path) + error("hook_vr: Invalid hook '/hook/[hook]' called.") + return 0 + + var/caller = new hook_path + var/status = 1 + for(var/P in typesof("[hook_path]/proc")) + if(!call(caller, P)(arglist(args))) + error("hook_vr: Hook '[P]' failed or runtimed.") + status = 0 + + return status + + catch(var/exception/e) + error("hook_vr itself failed or runtimed. Exception below.") + error("hook_vr catch: [e] on [e.file]:[e.line]") diff --git a/sound/vore/death1.ogg b/sound/vore/death1.ogg new file mode 100644 index 00000000000..34f4e189f54 Binary files /dev/null and b/sound/vore/death1.ogg differ diff --git a/sound/vore/death10.ogg b/sound/vore/death10.ogg new file mode 100644 index 00000000000..92ce0fd9bda Binary files /dev/null and b/sound/vore/death10.ogg differ diff --git a/sound/vore/death2.ogg b/sound/vore/death2.ogg new file mode 100644 index 00000000000..2476b0f08c9 Binary files /dev/null and b/sound/vore/death2.ogg differ diff --git a/sound/vore/death3.ogg b/sound/vore/death3.ogg new file mode 100644 index 00000000000..d8a666067da Binary files /dev/null and b/sound/vore/death3.ogg differ diff --git a/sound/vore/death4.ogg b/sound/vore/death4.ogg new file mode 100644 index 00000000000..4fce54da79b Binary files /dev/null and b/sound/vore/death4.ogg differ diff --git a/sound/vore/death5.ogg b/sound/vore/death5.ogg new file mode 100644 index 00000000000..371cf17155e Binary files /dev/null and b/sound/vore/death5.ogg differ diff --git a/sound/vore/death6.ogg b/sound/vore/death6.ogg new file mode 100644 index 00000000000..78fc1b0637f Binary files /dev/null and b/sound/vore/death6.ogg differ diff --git a/sound/vore/death7.ogg b/sound/vore/death7.ogg new file mode 100644 index 00000000000..419a5bedd55 Binary files /dev/null and b/sound/vore/death7.ogg differ diff --git a/sound/vore/death8.ogg b/sound/vore/death8.ogg new file mode 100644 index 00000000000..b15ab6a7d24 Binary files /dev/null and b/sound/vore/death8.ogg differ diff --git a/sound/vore/death9.ogg b/sound/vore/death9.ogg new file mode 100644 index 00000000000..3709541d602 Binary files /dev/null and b/sound/vore/death9.ogg differ diff --git a/sound/vore/digest1.ogg b/sound/vore/digest1.ogg new file mode 100644 index 00000000000..058ca78f7eb Binary files /dev/null and b/sound/vore/digest1.ogg differ diff --git a/sound/vore/digest10.ogg b/sound/vore/digest10.ogg new file mode 100644 index 00000000000..5db775ae29f Binary files /dev/null and b/sound/vore/digest10.ogg differ diff --git a/sound/vore/digest11.ogg b/sound/vore/digest11.ogg new file mode 100644 index 00000000000..d81ac72deaa Binary files /dev/null and b/sound/vore/digest11.ogg differ diff --git a/sound/vore/digest12.ogg b/sound/vore/digest12.ogg new file mode 100644 index 00000000000..6b44127cd8b Binary files /dev/null and b/sound/vore/digest12.ogg differ diff --git a/sound/vore/digest2.ogg b/sound/vore/digest2.ogg new file mode 100644 index 00000000000..0e8bef1db85 Binary files /dev/null and b/sound/vore/digest2.ogg differ diff --git a/sound/vore/digest3.ogg b/sound/vore/digest3.ogg new file mode 100644 index 00000000000..2077f31399c Binary files /dev/null and b/sound/vore/digest3.ogg differ diff --git a/sound/vore/digest4.ogg b/sound/vore/digest4.ogg new file mode 100644 index 00000000000..27a786bc401 Binary files /dev/null and b/sound/vore/digest4.ogg differ diff --git a/sound/vore/digest5.ogg b/sound/vore/digest5.ogg new file mode 100644 index 00000000000..849c1335be1 Binary files /dev/null and b/sound/vore/digest5.ogg differ diff --git a/sound/vore/digest6.ogg b/sound/vore/digest6.ogg new file mode 100644 index 00000000000..5f0cc86eb16 Binary files /dev/null and b/sound/vore/digest6.ogg differ diff --git a/sound/vore/digest7.ogg b/sound/vore/digest7.ogg new file mode 100644 index 00000000000..f224cc3fa3a Binary files /dev/null and b/sound/vore/digest7.ogg differ diff --git a/sound/vore/digest8.ogg b/sound/vore/digest8.ogg new file mode 100644 index 00000000000..04b742bd491 Binary files /dev/null and b/sound/vore/digest8.ogg differ diff --git a/sound/vore/digest9.ogg b/sound/vore/digest9.ogg new file mode 100644 index 00000000000..866c95b8742 Binary files /dev/null and b/sound/vore/digest9.ogg differ diff --git a/sound/vore/gulp.ogg b/sound/vore/gulp.ogg new file mode 100644 index 00000000000..b463e7fb182 Binary files /dev/null and b/sound/vore/gulp.ogg differ diff --git a/sound/vore/insert.ogg b/sound/vore/insert.ogg new file mode 100644 index 00000000000..0574733d4df Binary files /dev/null and b/sound/vore/insert.ogg differ diff --git a/sound/vore/insertion1.ogg b/sound/vore/insertion1.ogg new file mode 100644 index 00000000000..a026591f074 Binary files /dev/null and b/sound/vore/insertion1.ogg differ diff --git a/sound/vore/insertion2.ogg b/sound/vore/insertion2.ogg new file mode 100644 index 00000000000..b682e3aaf8e Binary files /dev/null and b/sound/vore/insertion2.ogg differ diff --git a/sound/vore/insertion3.ogg b/sound/vore/insertion3.ogg new file mode 100644 index 00000000000..7dabf3f0776 Binary files /dev/null and b/sound/vore/insertion3.ogg differ diff --git a/sound/vore/schlorp.ogg b/sound/vore/schlorp.ogg new file mode 100644 index 00000000000..c9cd5a34132 Binary files /dev/null and b/sound/vore/schlorp.ogg differ diff --git a/sound/vore/squish1.ogg b/sound/vore/squish1.ogg new file mode 100644 index 00000000000..8a87758048f Binary files /dev/null and b/sound/vore/squish1.ogg differ diff --git a/sound/vore/squish2.ogg b/sound/vore/squish2.ogg new file mode 100644 index 00000000000..c8f96fc6e27 Binary files /dev/null and b/sound/vore/squish2.ogg differ diff --git a/sound/vore/squish3.ogg b/sound/vore/squish3.ogg new file mode 100644 index 00000000000..60e364c80a3 Binary files /dev/null and b/sound/vore/squish3.ogg differ diff --git a/sound/vore/squish4.ogg b/sound/vore/squish4.ogg new file mode 100644 index 00000000000..e9bd8e7bf56 Binary files /dev/null and b/sound/vore/squish4.ogg differ diff --git a/vorestation.dme b/vorestation.dme index f2e73e092e1..6df9398b994 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -21,6 +21,7 @@ #include "code\__defines\admin.dm" #include "code\__defines\appearance.dm" #include "code\__defines\atmos.dm" +#include "code\__defines\belly_modes_vr.dm" #include "code\__defines\chemistry.dm" #include "code\__defines\damage_organs.dm" #include "code\__defines\dna.dm" @@ -46,6 +47,7 @@ #include "code\_helpers\files.dm" #include "code\_helpers\game.dm" #include "code\_helpers\global_lists.dm" +#include "code\_helpers\global_lists_vr.dm" #include "code\_helpers\icons.dm" #include "code\_helpers\lists.dm" #include "code\_helpers\logging.dm" @@ -55,9 +57,11 @@ #include "code\_helpers\names.dm" #include "code\_helpers\sanitize_values.dm" #include "code\_helpers\text.dm" +#include "code\_helpers\text_vr.dm" #include "code\_helpers\time.dm" #include "code\_helpers\turfs.dm" #include "code\_helpers\type2type.dm" +#include "code\_helpers\type2type_vr.dm" #include "code\_helpers\unsorted.dm" #include "code\_helpers\vector.dm" #include "code\_onclick\adjacent.dm" @@ -1871,6 +1875,15 @@ #include "code\modules\virus2\helpers.dm" #include "code\modules\virus2\isolator.dm" #include "code\modules\virus2\items_devices.dm" +#include "code\modules\vore\hook-defs_vr.dm" +#include "code\modules\vore\trycatch_vr.dm" +#include "code\modules\vore\eating\belly_vr.dm" +#include "code\modules\vore\eating\bellymodes_vr.dm" +#include "code\modules\vore\eating\living_vr.dm" +#include "code\modules\vore\eating\simple_animal_vr.dm" +#include "code\modules\vore\eating\vore_vr.dm" +#include "code\modules\vore\eating\vorehooks_vr.dm" +#include "code\modules\vore\eating\vorepanel_vr.dm" #include "code\modules\xgm\xgm_gas_data.dm" #include "code\modules\xgm\xgm_gas_mixture.dm" #include "code\unit_tests\loadout_tests.dm"