Citadel's folder's end (#5828)

* ERP, miscreants, clothing

* github pls

* guns, dogborg, areas, vendor

* finishes moving around the last of the stuffs

* cleaned up shit. italics on subtle messages

vore code to modular_citadel too

* updates codeowners and recompiles tgui

because it's a healthy thing to do

* reee, I had that spawner set byond

* cleans up a bad pipe

does the thing I've been meaning to do for a while now as well.

* bumps up xenobio console requirements

inb4 reee

* snowflake commenting
This commit is contained in:
Poojawa
2018-03-06 17:40:48 -06:00
committed by GitHub
parent a1416622d2
commit 86b11050b6
140 changed files with 2963 additions and 9703 deletions
-162
View File
@@ -1,162 +0,0 @@
// THIS IS NOW MERELY LEGACY, because memes. hopefully it won't be dumb.
//
// 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.
//
// If you change what variables are on this, then you need to update the copy() proc.
//
// Parent type of all the various "belly" varieties.
//
/datum/belly
var/name // Name of this location
var/inside_flavor // Flavor text description of inside sight/sound/smells/feels.
var/vore_sound = 'sound/vore/pred/swallow_01.ogg' // Sound when ingesting someone
var/vore_verb = "ingest" // Verb for eating with this in messages
var/human_prey_swallow_time = 10 SECONDS // Time in deciseconds to swallow /mob/living/carbon/human
var/nonhuman_prey_swallow_time = 5 SECONDS // Time in deciseconds to swallow anything else
var/emoteTime = 30 SECONDS // How long between stomach emotes at prey
var/digest_brute = 0 // Brute damage per tick in digestion mode
var/digest_burn = 1 // Burn damage per tick in digestion mode
var/digest_tickrate = 9 // Modulus this of air controller tick number to iterate gurgles on
var/immutable = FALSE // Prevents this belly from being deleted
var/escapable = FALSE // Belly can be resisted out of at any time
var/escapetime = 60 SECONDS // Deciseconds, how long to escape this belly
var/digestchance = 0 // % Chance of stomach beginning to digest if prey struggles
// var/silenced = FALSE // Will the heartbeat/fleshy internal loop play?
var/escapechance = 0 // % Chance of prey beginning to escape if prey struggles.
var/datum/belly/transferlocation = null // Location that the prey is released if they struggle and get dropped off.
var/transferchance = 0 // % Chance of prey being transferred to transfer location when resisting
var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location
var/autotransferwait = 10 // Time between trying to transfer.
var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone.
var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest.
var/tmp/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY) // Possible digest modes
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/emotePend = FALSE // If there's already a spawned thing counting for the next emote
var/swallow_time = 10 SECONDS // for mob transfering automation
var/vore_capacity = 1 // The capacity (in people) this person can hold
// 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.
//List has indexes that are the digestion mode strings, and keys that are lists of strings.
var/list/emote_lists = list()
//OLD: This only exists for legacy conversion purposes
//It's called whenever an old datum-style belly is loaded
/datum/belly/proc/copy(obj/belly/new_belly)
//// Non-object variables
new_belly.name = name
new_belly.desc = inside_flavor
new_belly.vore_sound = vore_sound
new_belly.vore_verb = vore_verb
new_belly.human_prey_swallow_time = human_prey_swallow_time
new_belly.nonhuman_prey_swallow_time = nonhuman_prey_swallow_time
new_belly.emote_time = emoteTime
new_belly.digest_brute = digest_brute
new_belly.digest_burn = digest_burn
new_belly.immutable = immutable
new_belly.can_taste = can_taste
new_belly.escapable = escapable
new_belly.escapetime = escapetime
new_belly.digestchance = digestchance
new_belly.escapechance = escapechance
new_belly.transferchance = transferchance
new_belly.transferlocation = transferlocation
//// Object-holding variables
//struggle_messages_outside - strings
new_belly.struggle_messages_outside.Cut()
for(var/I in struggle_messages_outside)
new_belly.struggle_messages_outside += I
//struggle_messages_inside - strings
new_belly.struggle_messages_inside.Cut()
for(var/I in struggle_messages_inside)
new_belly.struggle_messages_inside += I
//digest_messages_owner - strings
new_belly.digest_messages_owner.Cut()
for(var/I in digest_messages_owner)
new_belly.digest_messages_owner += I
//digest_messages_prey - strings
new_belly.digest_messages_prey.Cut()
for(var/I in digest_messages_prey)
new_belly.digest_messages_prey += I
//examine_messages - strings
new_belly.examine_messages.Cut()
for(var/I in examine_messages)
new_belly.examine_messages += I
//emote_lists - index: digest mode, key: list of strings
new_belly.emote_lists.Cut()
for(var/K in emote_lists)
new_belly.emote_lists[K] = list()
for(var/I in emote_lists[K])
new_belly.emote_lists[K] += I
return new_belly
// // // // // // // // // // // //
// // // LEGACY USE ONLY!! // // //
// // // // // // // // // // // //
// See top of file! //
// // // // // // // // // // // //
-655
View File
@@ -1,655 +0,0 @@
//#define VORE_SOUND_FALLOFF 0.05
//
// Belly system 2.0, now using objects instead of datums because EH at datums.
// How many times have I rewritten bellies and vore now? -Aro
//
// If you change what variables are on this, then you need to update the copy() proc.
//
// Parent type of all the various "belly" varieties.
//
/obj/belly
name = "belly" // Name of this location
desc = "It's a belly! You're in it!" // Flavor text description of inside sight/sound/smells/feels.
var/vore_sound = 'sound/vore/pred/swallow_01.ogg' // Sound when ingesting someone
var/vore_verb = "ingest" // Verb for eating with this in messages
var/release_sound = 'sound/effects/splat.ogg'
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/emote_time = 60 SECONDS // How long between stomach emotes at prey
var/digest_brute = 2 // Brute damage per tick in digestion mode
var/digest_burn = 2 // Burn damage per tick in digestion mode
var/immutable = FALSE // Prevents this belly from being deleted
var/escapable = TRUE // Belly can be resisted out of at any time
var/escapetime = 20 SECONDS // Deciseconds, how long to escape this belly
var/digestchance = 0 // % Chance of stomach beginning to digest if prey struggles
var/absorbchance = 0 // % Chance of stomach beginning to absorb if prey struggles
var/escapechance = 100 // % Chance of prey beginning to escape if prey struggles.
var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone.
var/bulge_size = 0.25 // The minimum size the prey has to be in order to show up on examine.
// var/shrink_grow_size = 1 // This horribly named variable determines the minimum/maximum size it will shrink/grow prey to.
var/silent = FALSE
var/transferlocation = null // Location that the prey is released if they struggle and get dropped off.
var/transferchance = 0 // % Chance of prey being transferred to transfer location when resisting
var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location
var/autotransferwait = 10 // Time between trying to transfer.
var/swallow_time = 10 SECONDS // for mob transfering automation
var/vore_capacity = 1 // simple animal nom capacity
//I don't think we've ever altered these lists. making them static until someone actually overrides them somewhere.
var/tmp/static/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY) // Possible digest modes
var/tmp/mob/living/owner // The mob whose belly this is.
var/tmp/digest_mode = DM_HOLD // Current mode the belly is set to from digest_modes (+transform_modes if human)
var/tmp/next_process = 0 // Waiting for this SSbellies times_fired to process again.
var/tmp/list/items_preserved = list() // Stuff that wont digest so we shouldn't process it again.
var/tmp/next_emote = 0 // When we're supposed to print our next emote, as a belly controller tick #
var/tmp/recent_sound = FALSE // Prevent audio spam
// 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.
//List has indexes that are the digestion mode strings, and keys that are lists of strings.
var/tmp/list/emote_lists = list()
//For serialization, keep this updated, required for bellies to save correctly.
/obj/belly/vars_to_save()
return ..() + list(
"name",
"desc",
"vore_sound",
"vore_verb",
"release_sound",
"human_prey_swallow_time",
"nonhuman_prey_swallow_time",
"emote_time",
"digest_brute",
"digest_burn",
"immutable",
"can_taste",
"escapable",
"escapetime",
"digestchance",
"absorbchance",
"escapechance",
"transferchance",
"transferlocation",
"bulge_size",
"struggle_messages_outside",
"struggle_messages_inside",
"digest_messages_owner",
"digest_messages_prey",
"examine_messages",
"emote_lists",
"silent"
)
//ommitted list
// "shrink_grow_size",
/obj/belly/New(var/newloc)
. = ..(newloc)
//If not, we're probably just in a prefs list or something.
if(isliving(newloc))
owner = loc
owner.vore_organs |= src
SSbellies.belly_list += src
/obj/belly/Destroy()
SSbellies.belly_list -= src
if(owner)
owner.vore_organs -= src
owner = null
. = ..()
// Called whenever an atom enters this belly
/obj/belly/Entered(var/atom/movable/thing,var/atom/OldLoc)
if(OldLoc in contents)
return //Someone dropping something (or being stripdigested)
//Generic entered message
to_chat(owner,"<span class='notice'>[thing] slides into your [lowertext(name)].</span>")
//Sound w/ antispam flag setting
if(!silent && !recent_sound)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(owner),"[src.vore_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
recent_sound = TRUE
//Messages if it's a mob
if(isliving(thing))
var/mob/living/M = thing
if(desc)
to_chat(M, "<span class='notice'><B>[desc]</B></span>")
var/taste
if(can_taste && (taste = M.get_taste_message(FALSE)))
to_chat(owner, "<span class='notice'>[M] tastes of [taste].</span>")
// 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.
/obj/belly/proc/release_all_contents(var/include_absorbed = FALSE)
var/atom/destination = drop_location()
var/count = 0
for(var/thing in contents)
var/atom/movable/AM = thing
if(isliving(AM))
var/mob/living/L = AM
if(L.absorbed && !include_absorbed)
continue
L.absorbed = FALSE
for(var/mob/living/W in AM)
W.stop_sound_channel(CHANNEL_PREYLOOP)
AM.forceMove(destination) // Move the belly contents into the same location as belly's owner.
count++
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(owner),"[src.release_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
items_preserved.Cut()
owner.visible_message("<font color='green'><b>[owner] expels everything from their [lowertext(name)]!</b></font>")
owner.update_icons()
return count
// 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.
/obj/belly/proc/release_specific_contents(var/atom/movable/M)
if (!(M in contents))
return FALSE // They weren't in this belly anyway
M.forceMove(drop_location()) // Move the belly contents into the same location as belly's owner.
items_preserved -= M
for(var/mob/living/P in M)
P.stop_sound_channel(CHANNEL_PREYLOOP)
if(release_sound)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(owner),"[src.release_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
if(istype(M,/mob/living))
var/mob/living/ML = M
var/mob/living/OW = owner
if(ML.absorbed)
ML.absorbed = FALSE
if(ishuman(M) && ishuman(OW))
var/mob/living/carbon/human/Prey = M
var/mob/living/carbon/human/Pred = OW
var/absorbed_count = 2 //Prey that we were, plus the pred gets a portion
for(var/mob/living/P in contents)
if(P.absorbed)
absorbed_count++
Pred.reagents.trans_to(Prey, Pred.reagents.total_volume / absorbed_count)
owner.visible_message("<font color='green'><b>[owner] expels [M] from their [lowertext(name)]!</b></font>")
owner.update_icons()
return TRUE
// 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.
/obj/belly/proc/nom_mob(var/mob/prey, var/mob/user)
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
if(owner.stat == DEAD)
return
if (prey.buckled)
prey.buckled.unbuckle_mob(prey,TRUE)
prey.forceMove(src)
prey.playsound_local(loc,preyloop,70,0, channel = CHANNEL_PREYLOOP)
owner.updateVRPanel()
for(var/mob/living/M in contents)
M.updateVRPanel()
// Setup the autotransfer checks if needed
if(transferlocation && autotransferchance > 0)
addtimer(CALLBACK(src, /obj/belly/.proc/check_autotransfer, prey), autotransferwait)
/obj/belly/proc/check_autotransfer(var/mob/prey)
// Some sanity checks
if(transferlocation && (autotransferchance > 0) && (prey in contents))
if(prob(autotransferchance))
// Double check transferlocation isn't insane
if(verify_transferlocation())
transfer_contents(prey, transferlocation)
else
// Didn't transfer, so wait before retrying
addtimer(CALLBACK(src, /obj/belly/.proc/check_autotransfer, prey), autotransferwait)
/obj/belly/proc/verify_transferlocation()
for(var/I in owner.vore_organs)
var/obj/belly/B = owner.vore_organs[I]
if(B == transferlocation)
return TRUE
for(var/I in owner.vore_organs)
var/obj/belly/B = owner.vore_organs[I]
if(B == transferlocation)
transferlocation = B
return TRUE
return FALSE
// 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.
/obj/belly/proc/get_examine_msg()
if(contents.len && examine_messages.len)
var/formatted_message
var/raw_message = pick(examine_messages)
var/total_bulge = 0
formatted_message = replacetext(raw_message,"%belly",lowertext(name))
formatted_message = replacetext(formatted_message,"%pred",owner)
formatted_message = replacetext(formatted_message,"%prey",english_list(contents))
for(var/mob/living/P in contents)
if(!P.absorbed) //This is required first, in case there's a person absorbed and not absorbed in a stomach.
total_bulge += P.mob_size
if(total_bulge >= bulge_size && bulge_size != 0)
return("<span class='warning'>[formatted_message]</span><BR>")
else
return ""
// The next function gets the messages set on the belly, in human-readable format.
// This is useful in customization boxes and such. The delimiter right now is \n\n so
// in message boxes, this looks nice and is easily delimited.
/obj/belly/proc/get_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.
/obj/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)
testing("[owner] tried to set [lowertext(name)] with 11+ messages")
for(var/i = 1, i <= raw_list.len, i++)
if(length(raw_list[i]) > 160 || length(raw_list[i]) < 10) //160 is fudged value due to htmlencoding increasing the size
raw_list.Cut(i,i)
testing("[owner] tried to set [lowertext(name)] with >121 or <10 char message")
else
raw_list[i] = readd_quotes(raw_list[i])
//Also fix % sign for var replacement
raw_list[i] = replacetext(raw_list[i],"&#37;","%")
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.
/obj/belly/proc/digestion_death(var/mob/living/M)
//M.death(1) // "Stop it he's already dead..." Basically redundant and the reason behind screaming mouse carcasses.
if(M.ckey)
message_admins("[key_name(owner)] has digested [key_name(M)] in their [lowertext(name)] ([owner ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[owner.x];Y=[owner.y];Z=[owner.z]'>JMP</a>" : "null"])")
log_attack("[key_name(owner)] digested [key_name(M)].")
// If digested prey is also a pred... anyone inside their bellies gets moved up.
if(is_vore_predator(M))
for(var/belly in M.vore_organs)
var/obj/belly/B = belly
for(var/thing in B)
var/atom/movable/AM = thing
AM.forceMove(owner.loc)
if(isliving(AM))
to_chat(AM,"As [M] melts away around you, you find yourself in [owner]'s [lowertext(name)]")
//Drop all items into the belly
for(var/obj/item/W in M)
if(!M.dropItemToGround(W))
qdel(W)
/* //Reagent transfer //maybe someday
if(ishuman(owner))
var/mob/living/carbon/human/Pred = owner
if(ishuman(M))
var/mob/living/carbon/human/Prey = M
Prey.bloodstr.del_reagent("numbenzyme")
Prey.bloodstr.trans_to_holder(Pred.bloodstr, Prey.bloodstr.total_volume, 0.5, TRUE) // Copy=TRUE because we're deleted anyway
Prey.ingested.trans_to_holder(Pred.bloodstr, Prey.ingested.total_volume, 0.5, TRUE) // Therefore don't bother spending cpu
Prey.touching.trans_to_holder(Pred.bloodstr, Prey.touching.total_volume, 0.5, TRUE) // On updating the prey's reagents
else if(M.reagents)
M.reagents.trans_to_holder(Pred.bloodstr, M.reagents.total_volume, 0.5, TRUE) */
// Delete the digested mob
qdel(M)
// Handle a mob being absorbed
/obj/belly/proc/absorb_living(var/mob/living/M)
M.absorbed = TRUE
to_chat(M,"<span class='notice'>[owner]'s [lowertext(name)] absorbs your body, making you part of them.</span>")
to_chat(owner,"<span class='notice'>Your [lowertext(name)] absorbs [M]'s body, making them part of you.</span>")
// Reagent sharing is neat, but eh. I'll figure it out later
/* if(ishuman(M) && ishuman(owner))
var/mob/living/carbon/human/Prey = M
var/mob/living/carbon/human/Pred = owner
//Reagent sharing for absorbed with pred - Copy so both pred and prey have these reagents.
Prey.bloodstr.trans_to_holder(Pred.bloodstr, Prey.bloodstr.total_volume, copy = TRUE)
Prey.ingested.trans_to_holder(Pred.bloodstr, Prey.ingested.total_volume, copy = TRUE)
Prey.touching.trans_to_holder(Pred.bloodstr, Prey.touching.total_volume, copy = TRUE)
// TODO - Find a way to make the absorbed prey share the effects with the pred.
// Currently this is infeasible because reagent containers are designed to have a single my_atom, and we get
// problems when A absorbs B, and then C absorbs A, resulting in B holding onto an invalid reagent container.
*/
//This is probably already the case, but for sub-prey, it won't be.
if(M.loc != src)
M.forceMove(src)
//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/belly in M.vore_organs)
var/obj/belly/B = belly
for(var/mob/living/Mm in B)
if(Mm.absorbed)
absorb_living(Mm)
//Update owner
owner.updateVRPanel()
//Digest a single item
//Receives a return value from digest_act that's how much nutrition
//the item should be worth
/obj/belly/proc/digest_item(var/obj/item/item)
var/digested = item.digest_act(src, owner)
if(!digested)
items_preserved |= item
else
// owner.nutrition += (5 * digested) // haha no.
if(iscyborg(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += (50 * digested)
//Determine where items should fall out of us into.
//Typically just to the owner's location.
/obj/belly/drop_location()
//Should be the case 99.99% of the time
if(owner)
return owner.loc
//Sketchy fallback for safety, put them somewhere safe.
else if(ismob(src))
testing("[src] (\ref[src]) doesn't have an owner, and dropped someone at a latespawn point!")
SSjob.SendToLateJoin(src)
// wew lad. let's see if this never gets used, hopefully
else
qdel(src) //final option, I guess.
testing("[src] (\ref[src]) was QDEL'd for not having a drop_location!")
//Handle a mob struggling
// Called from /mob/living/carbon/relaymove()
/obj/belly/proc/relay_resist(var/mob/living/R)
if (!(R in contents))
return // User is not in this belly
R.setClickCooldown(50)
if(owner.stat || !owner.client && R.a_intent != INTENT_HELP) //If owner is stat (dead, KO) we can actually escape
to_chat(R,"<span class='warning'>You attempt to climb out of \the [lowertext(name)]. (This will take around 5 seconds.)</span>")
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
if(do_after(R, 50, owner))
if(owner.stat && (R in contents) && R.a_intent != INTENT_HELP) //Can still escape and want to?
release_specific_contents(R)
return
else if(!(R in contents)) //Aren't even in the belly. Quietly fail.
return
else //Belly became inescapable or mob revived
to_chat(R,"<span class='warning'>Your attempt to escape [lowertext(name)] has failed!</span>")
to_chat(owner,"<span class='notice'>The attempt to escape from your [lowertext(name)] has failed!</span>")
return
return
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",R)
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",R)
struggle_user_message = replacetext(struggle_user_message,"%belly",lowertext(name))
struggle_outer_message = "<span class='alert'>" + struggle_outer_message + "</span>"
struggle_user_message = "<span class='alert'>" + struggle_user_message + "</span>"
for(var/mob/M in get_hearers_in_view(3, get_turf(owner)))
M.show_message(struggle_outer_message, 2) // hearable
to_chat(R,struggle_user_message)
if(!silent)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(owner),"struggle_sound",35,0,-5,1,ignore_walls = FALSE,channel=CHANNEL_PRED)
R.stop_sound_channel(CHANNEL_PRED)
var/sound/prey_struggle = sound(get_sfx("prey_struggle"))
R.playsound_local(get_turf(R),prey_struggle,45,0)
if(R.a_intent != INTENT_HELP) //If on non help intent
to_chat(R,"<span class='warning'>You start to climb out of \the [lowertext(name)].</span>")
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
if(do_after(R, escapetime, owner))
if((owner.stat || !owner.client || escapable) && (R in contents))
release_specific_contents(R)
to_chat(R,"<span class='warning'>You climb out of \the [lowertext(name)].</span>")
to_chat(owner,"<span class='warning'>[R] climbs out of your [lowertext(name)]!</span>")
for(var/mob/M in hearers(4, owner))
M.show_message("<span class='warning'>[R] climbs out of [owner]'s [lowertext(name)]!</span>", 2)
return
else if(!istype(loc, /obj/belly)) //Aren't even in the belly. Quietly fail.
return
else //Belly became inescapable.
to_chat(R,"<span class='warning'>Your attempt to escape [lowertext(name)] has failed!</span>")
to_chat(owner,"<span class='notice'>The attempt to escape from your [lowertext(name)] has failed!</span>")
return
else if(prob(transferchance) && transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started.
var/obj/belly/dest_belly
for(var/belly in owner.vore_organs)
var/obj/belly/B = belly
if(B.name == transferlocation)
dest_belly = B
break
if(!dest_belly)
to_chat(owner, "<span class='warning'>Something went wrong with your belly transfer settings. Your <b>[lowertext(name)]</b> has had it's transfer chance and transfer location cleared as a precaution.</span>")
transferchance = 0
transferlocation = null
return
to_chat(R,"<span class='warning'>Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!</span>")
to_chat(owner,"<span class='warning'>Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!</span>")
transfer_contents(R, dest_belly)
return
/*
else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance.
to_chat(R,"<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to cling more tightly...</span>")
to_chat(owner,"<span class='warning'>You feel your [lowertext(name)] start to cling onto its contents...</span>")
digest_mode = DM_ABSORB
return
else if(prob(digestchance) && digest_mode != DM_ITEMWEAK && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance.
to_chat(R,"<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to get more active...</span>")
to_chat(owner,"<span class='warning'>You feel your [lowertext(name)] beginning to become active!</span>")
digest_mode = DM_ITEMWEAK
return
else if(prob(digestchance) && digest_mode == DM_ITEMWEAK) //Oh god it gets even worse if you fail twice!
to_chat(R,"<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to get even more active!</span>")
to_chat(owner,"<span class='warning'>You feel your [lowertext(name)] beginning to become even more active!</span>")
digest_mode = DM_DIGEST
return */
else if(prob(digestchance)) //Finally, let's see if it should run the digest chance.)
to_chat(R, "<span class='warning'>In response to your struggling, \the [name] begins to get more active...</span>")
to_chat(owner, "<span class='warning'>You feel your [name] beginning to become active!</span>")
digest_mode = DM_DIGEST
return
else //Nothing interesting happened.
to_chat(R,"<span class='warning'>You make no progress in escaping [owner]'s [lowertext(name)].</span>")
to_chat(owner,"<span class='warning'>Your prey appears to be unable to make any progress in escaping your [lowertext(name)].</span>")
return
//Transfers contents from one belly to another
/obj/belly/proc/transfer_contents(var/atom/movable/content, var/obj/belly/target, silent = FALSE)
if(!(content in src) || !istype(target))
return
target.nom_mob(content, target.owner)
if(!silent)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(owner),"[src.vore_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
owner.updateVRPanel()
for(var/mob/living/M in contents)
M.updateVRPanel()
// Belly copies and then returns the copy
// Needs to be updated for any var changes
/obj/belly/proc/copy(mob/new_owner)
var/obj/belly/dupe = new /obj/belly(new_owner)
//// Non-object variables
dupe.name = name
dupe.desc = desc
dupe.vore_sound = vore_sound
dupe.vore_verb = vore_verb
dupe.release_sound = release_sound
dupe.human_prey_swallow_time = human_prey_swallow_time
dupe.nonhuman_prey_swallow_time = nonhuman_prey_swallow_time
dupe.emote_time = emote_time
dupe.digest_brute = digest_brute
dupe.digest_burn = digest_burn
dupe.immutable = immutable
dupe.can_taste = can_taste
dupe.escapable = escapable
dupe.escapetime = escapetime
dupe.digestchance = digestchance
dupe.absorbchance = absorbchance
dupe.escapechance = escapechance
dupe.transferchance = transferchance
dupe.transferlocation = transferlocation
dupe.bulge_size = bulge_size
// dupe.shrink_grow_size = shrink_grow_size
//// Object-holding variables
//struggle_messages_outside - strings
dupe.struggle_messages_outside.Cut()
for(var/I in struggle_messages_outside)
dupe.struggle_messages_outside += I
//struggle_messages_inside - strings
dupe.struggle_messages_inside.Cut()
for(var/I in struggle_messages_inside)
dupe.struggle_messages_inside += I
//digest_messages_owner - strings
dupe.digest_messages_owner.Cut()
for(var/I in digest_messages_owner)
dupe.digest_messages_owner += I
//digest_messages_prey - strings
dupe.digest_messages_prey.Cut()
for(var/I in digest_messages_prey)
dupe.digest_messages_prey += I
//examine_messages - strings
dupe.examine_messages.Cut()
for(var/I in examine_messages)
dupe.examine_messages += I
//emote_lists - index: digest mode, key: list of strings
dupe.emote_lists.Cut()
for(var/K in emote_lists)
dupe.emote_lists[K] = list()
for(var/I in emote_lists[K])
dupe.emote_lists[K] += I
dupe.silent = silent
return dupe
-186
View File
@@ -1,186 +0,0 @@
// Process the predator's effects upon the contents of its belly (i.e digestion/transformation etc)
/obj/belly/proc/process_belly(var/times_fired,var/wait) //Passed by controller
if((times_fired < next_process) || !contents.len)
recent_sound = FALSE
return SSBELLIES_IGNORED
if(loc != owner)
if(istype(owner))
loc = owner
else
qdel(src)
return SSBELLIES_PROCESSED
next_process = times_fired + (6 SECONDS/wait) //Set up our next process time.
/////////////////////////// Auto-Emotes ///////////////////////////
if(contents.len && next_emote <= times_fired)
next_emote = times_fired + round(emote_time/wait,1)
var/list/EL = emote_lists[digest_mode]
for(var/mob/living/M in contents)
if(M.digestable || !(digest_mode == DM_DIGEST)) // don't give digesty messages to indigestible people
to_chat(M,"<span class='notice'>[pick(EL)]</span>")
/////////////////////////// Exit Early ////////////////////////////
var/list/touchable_items = contents - items_preserved
if(!length(touchable_items))
return SSBELLIES_PROCESSED
////////////////////////// Sound vars /////////////////////////////
var/sound/prey_digest = sound(get_sfx("digest_prey"))
var/sound/prey_death = sound(get_sfx("death_prey"))
///////////////////////////// DM_HOLD /////////////////////////////
if(digest_mode == DM_HOLD)
return SSBELLIES_PROCESSED
//////////////////////////// DM_DIGEST ////////////////////////////
else if(digest_mode == DM_DIGEST)
for (var/mob/living/M in contents)
if(prob(25))
M.stop_sound_channel(CHANNEL_DIGEST)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"digest_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(CHANNEL_DIGEST)
M.playsound_local(get_turf(M), prey_digest, 45)
//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
to_chat(owner, "<span class='warning'>[digest_alert_owner]</span>")
to_chat(M, "<span class='warning'>[digest_alert_prey]</span>")
M.visible_message("<span class='notice'>You watch as [owner]'s form loses its additions.</span>")
owner.nutrition += 400 // so eating dead mobs gives you *something*.
M.stop_sound_channel(DIGESTION_NOISES)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"death_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(DIGESTION_NOISES)
M.stop_sound_channel(CHANNEL_PREYLOOP)
M.playsound_local(get_turf(M), prey_death, 65)
digestion_death(M)
owner.update_icons()
continue
// Deal digestion damage (and feed the pred)
if(!(M.status_flags & GODMODE))
M.adjustFireLoss(digest_burn)
owner.nutrition += 1
//Contaminate or gurgle items
var/obj/item/T = pick(touchable_items)
if(istype(T))
if(istype(T,/obj/item/reagent_containers/food) || istype(T,/obj/item/organ))
digest_item(T)
owner.updateVRPanel()
///////////////////////////// DM_HEAL /////////////////////////////
if(digest_mode == DM_HEAL)
for (var/mob/living/M in contents)
if(prob(25))
M.stop_sound_channel(CHANNEL_DIGEST)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"digest_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(CHANNEL_DIGEST)
M.playsound_local(get_turf(M), prey_digest, 65)
if(M.stat != DEAD)
if(owner.nutrition >= NUTRITION_LEVEL_STARVING && (M.health < M.maxHealth))
M.adjustBruteLoss(-3)
M.adjustFireLoss(-3)
owner.nutrition -= 5
return
////////////////////////// DM_NOISY /////////////////////////////////
//for when you just want people to squelch around
if(digest_mode == DM_NOISY)
for (var/mob/living/M in contents)
if(prob(35))
M.stop_sound_channel(CHANNEL_DIGEST)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"digest_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local(get_turf(M), prey_digest, 65)
//////////////////////////DM_DRAGON /////////////////////////////////////
//because dragons need snowflake guts
if(digest_mode == DM_DRAGON)
for (var/mob/living/M in contents)
if(prob(25))
M.stop_sound_channel(CHANNEL_DIGEST)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"digest_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(CHANNEL_DIGEST)
M.playsound_local(get_turf(M), prey_digest, 65)
//No digestion protection for megafauna.
//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
to_chat(owner, "<span class='warning'>[digest_alert_owner]</span>")
to_chat(M, "<span class='warning'>[digest_alert_prey]</span>")
M.visible_message("<span class='notice'>You watch as [owner]'s guts loudly rumble as it finishes off a meal.</span>")
M.stop_sound_channel(CHANNEL_DIGEST)
for(var/mob/H in get_hearers_in_view(5, get_turf(owner)))
if(H.client && H.client.prefs.toggles & DIGESTION_NOISES)
playsound(get_turf(owner),"death_pred",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_DIGEST)
M.stop_sound_channel(CHANNEL_DIGEST)
M.playsound_local(get_turf(M), prey_death, 65)
M.spill_organs(FALSE,TRUE,TRUE)
M.stop_sound_channel(CHANNEL_PREYLOOP)
digestion_death(M)
owner.update_icons()
continue
// Deal digestion damage (and feed the pred)
if(!(M.status_flags & GODMODE))
M.adjustFireLoss(digest_burn)
M.adjustToxLoss(2) // something something plasma based acids
M.adjustCloneLoss(1) // eventually this'll kill you if you're healing everything else, you nerds.
//Contaminate or gurgle items
var/obj/item/T = pick(touchable_items)
if(istype(T))
if(istype(T,/obj/item/reagent_containers/food) || istype(T,/obj/item/organ))
digest_item(T)
owner.updateVRPanel()
-119
View File
@@ -1,119 +0,0 @@
//Please make sure to:
//return FALSE: You are not going away, stop asking me to digest.
//return non-negative integer: Amount of nutrition/charge gained (scaled to nutrition, other end can multiply for charge scale).
// Ye default implementation.
/obj/item/proc/digest_act(var/atom/movable/item_storage = null)
for(var/obj/item/O in contents)
if(istype(O,/obj/item/storage/internal)) //Dump contents from dummy pockets.
for(var/obj/item/SO in O)
if(item_storage)
SO.forceMove(item_storage)
qdel(O)
else if(item_storage)
O.forceMove(item_storage)
qdel(src)
return w_class
/////////////
// Some indigestible stuff
/////////////
/obj/item/hand_tele/digest_act(...)
return FALSE
/obj/item/card/id/digest_act(...)
return FALSE
/obj/item/aicard/digest_act(...)
return FALSE
/obj/item/paicard/digest_act(...)
return FALSE
/obj/item/pinpointer/digest_act(...)
return FALSE
/obj/item/disk/nuclear/digest_act(...)
return FALSE
/obj/item/device/perfect_tele_beacon/digest_act(...)
return FALSE //Sorta important to not digest your own beacons.
/obj/item/device/pda/digest_act(...)
return FALSE
/obj/item/gun/digest_act(...)
return FALSE
/obj/item/clothing/shoes/magboots/digest_act(...)
return FALSE
/obj/item/clothing/head/helmet/space/digest_act(...)
return FALSE
/obj/item/clothing/suit/space/digest_act(...)
return FALSE
/obj/item/reagent_containers/hypospray/CMO/digest_act(...)
return FALSE
/obj/item/tank/jetpack/oxygen/captain/digest_act(...)
return FALSE
/obj/item/clothing/accessory/medal/gold/captain/digest_act(...)
return FALSE
/obj/item/clothing/suit/armor/digest_act(...)
return FALSE
/obj/item/documents/digest_act(...)
return FALSE
/obj/item/nuke_core/digest_act(...)
return FALSE
/obj/item/nuke_core_container/digest_act(...)
return FALSE
/obj/item/areaeditor/blueprints/digest_act(...)
return FALSE
/obj/item/documents/syndicate/digest_act(...)
return FALSE
/obj/item/bombcore/digest_act(...)
return FALSE
/obj/item/grenade/digest_act(...)
return FALSE
/obj/item/storage/digest_act(...)
return FALSE
/////////////
// Some special treatment
/////////////
/*
//PDAs need to lose their ID to not take it with them, so we can get a digested ID
/obj/item/device/pda/digest_act(var/atom/movable/item_storage = null)
if(id)
id = null
. = ..()
*/
/obj/item/reagent_containers/food/digest_act(var/atom/movable/item_storage = null)
if(isbelly(item_storage))
var/obj/belly/B = item_storage
if(ishuman(B.owner))
var/mob/living/carbon/human/H = B.owner
reagents.trans_to(H, (reagents.total_volume * 0.3), 1, 0)
else if(iscyborg(B.owner))
var/mob/living/silicon/robot/R = B.owner
R.cell.charge += 150
. = ..()
/*
/obj/item/holder/digest_act(var/atom/movable/item_storage = null)
for(var/mob/living/M in contents)
if(item_storage)
M.forceMove(item_storage)
held_mob = null
. = ..() */
/obj/item/organ/digest_act(var/atom/movable/item_storage = null)
if((. = ..()))
. += 70 //Organs give a little more
/obj/item/storage/digest_act(var/atom/movable/item_storage = null)
for(var/obj/item/I in contents)
I.screen_loc = null
. = ..()
/////////////
// Some more complicated stuff
/////////////
/obj/item/device/mmi/digital/posibrain/digest_act(var/atom/movable/item_storage = null)
//Replace this with a VORE setting so all types of posibrains can/can't be digested on a whim
return FALSE
-459
View File
@@ -1,459 +0,0 @@
///////////////////// Mob Living /////////////////////
/mob/living
var/digestable = TRUE // Can the mob be digested inside a belly?
var/obj/belly/vore_selected // Default to no vore capability.
var/list/vore_organs = list() // List of vore containers inside a mob
var/devourable = FALSE // Can the mob be vored at all?
// var/feeding = FALSE // Are we going to feed someone else?
var/vore_taste = null // What the character tastes like
var/no_vore = FALSE // If the character/mob can vore.
var/openpanel = 0 // Is the vore panel open?
var/noisy = FALSE // tummies are rumbly?
var/absorbed = FALSE //are we absorbed?
//
// Hook for generic creation of stuff on new creatures
//
/hook/living_new/proc/vore_setup(mob/living/M)
M.verbs += /mob/living/proc/preyloop_refresh
M.verbs += /mob/living/proc/lick
if(M.no_vore) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
return 1
M.verbs += /mob/living/proc/insidePanel
//Tries to load prefs if a client is present otherwise gives freebie stomach
if(!M.vore_organs || !M.vore_organs.len)
spawn(20) //Wait a couple of seconds to make sure copy_to or whatever has gone
if(!M) return
if(M.client && M.client.prefs_vr)
if(!M.copy_from_prefs_vr())
to_chat(M,"<span class='warning'>ERROR: You seem to have saved vore prefs, but they couldn't be loaded.</span>")
return 0
if(M.vore_organs && M.vore_organs.len)
M.vore_selected = M.vore_organs[1]
if(!M.vore_organs || !M.vore_organs.len)
if(!M.vore_organs)
M.vore_organs = list()
var/obj/belly/B = new /obj/belly(M)
M.vore_selected = B
B.immutable = TRUE
B.name = "Stomach"
B.desc = "It appears to be rather warm and wet. Makes sense, considering it's inside \the [M.name]."
B.can_taste = FALSE
//Return 1 to hook-caller
return 1
/*
// Hide vore organs in contents
//
/datum/proc/view_variables_filter_contents(list/L)
return 0
/mob/living/view_variables_filter_contents(list/L)
. = ..()
var/len_before = L.len
L -= vore_organs
. += len_before - L.len*/
// Handle being clicked, perhaps with something to devour
//
// Refactored to use centralized vore code system - Leshana
// Critical adjustments due to TG grab changes - Poojawa
/mob/living/proc/vore_attack(var/mob/living/user, var/mob/living/prey)
if(!user || !prey)
return
if(prey == src && user.zone_selected == "mouth") //you click your target
// if(!feeding(src))
// return
if(!is_vore_predator(prey))
to_chat(user, "<span class='notice'>They aren't voracious enough.</span>")
return
feed_self_to_grabbed(user, src)
if(user == src) //you click yourself
if(!is_vore_predator(src))
to_chat(user, "<span class='notice'>You aren't voracious enough.</span>")
return
user.feed_grabbed_to_self(src, prey)
else // click someone other than you/prey
// if(!feeding(src))
// return
if(!is_vore_predator(src))
to_chat(user, "<span class='notice'>They aren't voracious enough.</span>")
return
feed_grabbed_to_other(user, prey, src)
//
// 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)
return//disabled until I can make that toggle work
var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, prey, pred, belly)
//Dragon noms need to be faster
/mob/living/proc/dragon_feeding(var/mob/living/user, var/mob/living/prey)
var/belly = user.vore_selected
return perform_dragon(user, prey, user, belly)
/mob/living/proc/perform_dragon(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/obj/belly/belly, swallow_time = 20)
//Sanity
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs))
testing("[user] attempted to feed [prey] to [pred], via [lowertext(belly.name)] but it went wrong.")
return
// The belly selected at the time of noms
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)"
/* //Final distance check. Time has passed, menus have come and gone. Can't use do_after adjacent because doesn't behave for held micros
var/user_to_pred = get_dist(get_turf(user),get_turf(pred))
var/user_to_prey = get_dist(get_turf(user),get_turf(prey)) */
// Prepare messages
if(user == pred) //Feeding someone to yourself
attempt_msg = text("<span class='warning'>[] starts to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
success_msg = text("<span class='warning'>[] manages to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
// Announce that we start the attempt!
user.visible_message(attempt_msg)
if(!do_mob(src, user, swallow_time))
return FALSE // Prey escaped (or user disabled) before timer expired.
// If we got this far, nom successful! Announce it!
user.visible_message(success_msg)
playsound(get_turf(user), "[belly.vore_sound]",75,0,-6,0)
// Actually shove prey into the belly.
belly.nom_mob(prey, user)
if (pred == user)
message_admins("[key_name(pred)] ate [key_name(prey)].")
log_attack("[key_name(pred)] ate [key_name(prey)]")
return TRUE
//
// 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/obj/belly/belly, var/delay)
//Sanity
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs))
testing("[user] attempted to feed [prey] to [pred], via [lowertext(belly.name)] but it went wrong.")
return
if (!prey.devourable)
to_chat(user, "This can't be eaten!")
return
// The belly selected at the time of noms
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)"
/* //Final distance check. Time has passed, menus have come and gone. Can't use do_after adjacent because doesn't behave for held micros
var/user_to_pred = get_dist(get_turf(user),get_turf(pred))
var/user_to_prey = get_dist(get_turf(user),get_turf(prey)) */
// Prepare messages
if(user == pred) //Feeding someone to yourself
attempt_msg = text("<span class='warning'>[] is attemping to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
success_msg = text("<span class='warning'>[] manages to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
else //Feeding someone to another person
attempt_msg = text("<span class='warning'>[] is attempting to make [] [] [] into their []!</span>",user,pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
success_msg = text("<span class='warning'>[] manages to make [] [] [] into their []!</span>",user,pred,lowertext(belly.vore_verb),prey,lowertext(belly.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 = delay || ishuman(prey) ? belly.human_prey_swallow_time : belly.nonhuman_prey_swallow_time
if(!do_mob(src, user, swallow_time))
return FALSE // Prey escaped (or user disabled) before timer expired.
// If we got this far, nom successful! Announce it!
user.visible_message(success_msg)
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(user),"[belly.vore_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
// Actually shove prey into the belly.
belly.nom_mob(prey, user)
// user.update_icons()
stop_pulling()
// Flavor handling
if(belly.can_taste && prey.get_taste_message(FALSE))
to_chat(belly.owner, "<span class='notice'>[prey] tastes of [prey.get_taste_message(FALSE)].</span>")
// Inform Admins
var/prey_braindead
var/prey_stat
if(prey.ckey)
prey_stat = prey.stat//only return this if they're not an unmonkey or whatever
if(!prey.client)//if they disconnected, tell us
prey_braindead = 1
if (pred == user)
message_admins("[ADMIN_LOOKUPFLW(pred)] ate [ADMIN_LOOKUPFLW(prey)][!prey_braindead ? "" : " (BRAINDEAD)"][prey_stat ? " (DEAD/UNCONSCIOUS)" : ""].")
log_attack("[key_name(pred)] ate [key_name(prey)]")
else
message_admins("[ADMIN_LOOKUPFLW(user)] forced [ADMIN_LOOKUPFLW(pred)] to eat [ADMIN_LOOKUPFLW(prey)].")
log_attack("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)].")
return TRUE
//
//End vore code.
/*
//Handle case: /obj/item/holder
if(/obj/item/holder/micro)
var/obj/item/holder/H = I
if(!isliving(user)) return 0 // Return 0 to continue upper procs
var/mob/living/attacker = user // Typecast to living
if (is_vore_predator(src))
for (var/mob/living/M in H.contents)
attacker.eat_held_mob(attacker, M, src)
return 1 //Return 1 to exit upper procs
else
log_attack("[attacker] attempted to feed [H.contents] to [src] ([src.type]) but it failed.")
// I just can't imagine this not being complained about
//Handle case: /obj/item/device/radio/beacon
if(/obj/item/device/radio/beacon)
var/confirm = alert(user, "[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]", "Confirmation", "Yes!", "Cancel")
if(confirm == "Yes!")
var/bellychoice = input("Which belly?","Select A Belly") in src.vore_organs
var/datum/belly/B = src.vore_organs[bellychoice]
src.visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [bellychoice]!</span>","<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
if(do_after(user,30,src))
user.drop_item()
I.loc = src
B.internal_contents += I
src.visible_message("<span class='warning'>[src] is fed the beacon!</span>","You're fed the beacon!")
playsound(get_turf(src), B.vore_sound,50,0,-6,0)
return 1
else
return 1 //You don't get to hit someone 'later'
return 0
*/
//
// Release everything in every vore organ
//
/mob/living/proc/release_vore_contents(var/include_absorbed = TRUE)
for(var/belly in vore_organs)
var/obj/belly/B = belly
B.release_all_contents(include_absorbed)
//
// Custom resist catches for /mob/living
//
/mob/living/proc/vore_process_resist()
//Are we resisting from inside a belly?
if(isbelly(loc))
var/obj/belly/B = loc
B.relay_resist(src)
return TRUE //resist() on living does this TRUE thing.
//Other overridden resists go here
return FALSE
// internal slimy button in case the loop stops playing but the player wants to hear it
/mob/living/proc/preyloop_refresh()
set name = "Internal loop refresh"
set category = "Vore"
if(istype(src.loc, /obj/belly))
src.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
src.playsound_local(get_turf(src),preyloop,80,0, channel = CHANNEL_PREYLOOP)
else
to_chat(src, "<span class='alert'>You aren't inside anything, you clod.</span>")
// OOC Escape code for pref-breaking or AFK preds
//
/mob/living/proc/escapeOOC()
set name = "Animal 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. Use this as a trick to get out of hostile animals. 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/obj/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
pred.update_icons()
else
to_chat(src, "<span class='alert'>You aren't inside anything, you clod.</span>")
//
// Verb for saving vore preferences to save file
//
/mob/living/proc/save_vore_prefs()
if(!(client || client.prefs_vr))
return FALSE
if(!copy_to_prefs_vr())
return FALSE
if(!client.prefs_vr.save_vore())
return FALSE
return TRUE
/mob/living/proc/apply_vore_prefs()
if(!(client || client.prefs_vr))
return FALSE
if(!client.prefs_vr.load_vore())
return FALSE
if(!copy_from_prefs_vr())
return FALSE
return TRUE
/mob/living/proc/copy_to_prefs_vr()
if(!client || !client.prefs_vr)
src << "<span class='warning'>You attempted to save your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.</span>"
return FALSE
var/datum/vore_preferences/P = client.prefs_vr
P.digestable = src.digestable
P.devourable = src.devourable
P.vore_taste = src.vore_taste
var/list/serialized = list()
for(var/belly in src.vore_organs)
var/obj/belly/B = belly
serialized += list(B.serialize()) //Can't add a list as an object to another list in Byond. Thanks.
P.belly_prefs = serialized
return TRUE
//
// Proc for applying vore preferences, given bellies
//
/mob/living/proc/copy_from_prefs_vr()
if(!client || !client.prefs_vr)
src << "<span class='warning'>You attempted to apply your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.</span>"
return FALSE
var/datum/vore_preferences/P = client.prefs_vr
digestable = P.digestable
devourable = P.devourable
vore_taste = P.vore_taste
vore_organs.Cut()
for(var/entry in P.belly_prefs)
list_to_object(entry,src)
return TRUE
//
// Returns examine messages for bellies
//
/mob/living/proc/examine_bellies()
if(!show_pudge()) //Some clothing or equipment can hide this.
return ""
var/message = ""
for (var/belly in vore_organs)
var/obj/belly/B = belly
message += B.get_examine_msg()
return message
//
// Whether or not people can see our belly messages
//
/mob/living/proc/show_pudge()
return TRUE //Can override if you want.
/mob/living/carbon/human/show_pudge()
//A uniform could hide it.
if(istype(w_uniform,/obj/item/clothing))
var/obj/item/clothing/under = w_uniform
if(under.hides_bulges)
return FALSE
//We return as soon as we find one, no need for 'else' really.
if(istype(wear_suit,/obj/item/clothing))
var/obj/item/clothing/suit = wear_suit
if(suit.hides_bulges)
return FALSE
return ..()
//
// Clearly super important. Obviously.
//
/mob/living/proc/lick(var/mob/living/tasted in oview(1))
set name = "Lick Someone"
set category = "Vore"
set desc = "Lick someone nearby!"
if(!istype(tasted))
return
if(src == stat)
return
src.setClickCooldown(50)
src.visible_message("<span class='warning'>[src] licks [tasted]!</span>","<span class='notice'>You lick [tasted]. They taste rather like [tasted.get_taste_message()].</span>","<b>Slurp!</b>")
/mob/living/proc/get_taste_message(allow_generic = TRUE, datum/species/mrace)
if(!vore_taste && !allow_generic)
return FALSE
var/taste_message = ""
if(vore_taste && (vore_taste != ""))
taste_message += "[vore_taste]"
else
if(ishuman(src))
taste_message += "they haven't bothered to set their flavor text"
else
taste_message += "a plain old normal [src]"
/* if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.touching.reagent_list.len) //Just the first one otherwise I'll go insane.
var/datum/reagent/R = H.touching.reagent_list[1]
taste_message += " You also get the flavor of [R.taste_description] from something on them"*/
return taste_message
@@ -1,44 +0,0 @@
///////////////////// Simple Animal /////////////////////
/mob/living/simple_animal
var/isPredator = FALSE //Are they capable of performing and pre-defined vore actions for their species?
var/swallowTime = 5 SECONDS //How long it takes to eat its prey in 1/10 of a second. The default is 5 seconds.
var/list/prey_excludes = list() //For excluding people from being eaten.
//
// 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 = "Object"
set src in oview(1)
var/datum/belly/B = vore_organs[vore_selected]
if(faction != usr.faction)
to_chat(usr,"<span class='warning'>This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you.</span>")
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"
sleep(20 MINUTES) //12000=20 minutes
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"
//
// Simple nom proc for if you get ckey'd into a simple_animal mob! Avoids grabs.
//
/mob/living/simple_animal/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!"
if (stat != CONSCIOUS)
return
if (T.devourable == FALSE)
to_chat(usr, "<span class='warning'>You can't eat this!</span>")
return
return feed_grabbed_to_self(src,T)
-168
View File
@@ -1,168 +0,0 @@
/*
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.
//
//
// The datum type bolted onto normal preferences datums for storing Vore stuff
//
/client
var/datum/vore_preferences/prefs_vr
/hook/client_new/proc/add_prefs_vr(client/C)
C.prefs_vr = new/datum/vore_preferences(C)
if(C.prefs_vr)
return TRUE
return FALSE
/datum/vore_preferences
//Actual preferences
var/digestable = TRUE
var/devourable = FALSE
// var/allowmobvore = TRUE
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
// var/can_be_drop_prey = FALSE
// var/can_be_drop_pred = FALSE
//Mechanically required
var/path
var/slot
var/client/client
var/client_ckey
/datum/vore_preferences/New(client/C)
if(istype(C))
client = C
client_ckey = C.ckey
load_vore()
//
// 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 TRUE
return FALSE
//
// Belly searching for simplifying other procs
// Mostly redundant now with belly-objects and isbelly(loc)
//
/proc/check_belly(atom/movable/A)
return isbelly(A.loc)
//
// Save/Load Vore Preferences
//
/datum/vore_preferences/proc/load_path(ckey,slot,filename="character",ext="json")
if(!ckey || !slot) return
path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/vore/[filename][slot].[ext]"
/datum/vore_preferences/proc/load_vore()
if(!client || !client_ckey)
return FALSE //No client, how can we save?
if(!client.prefs || !client.prefs.default_slot)
return FALSE //Need to know what character to load!
slot = client.prefs.default_slot
load_path(client_ckey,slot)
if(!path) return FALSE //Path couldn't be set?
if(!fexists(path)) //Never saved before
save_vore() //Make the file first
return TRUE
var/list/json_from_file = json_decode(file2text(path))
if(!json_from_file)
return FALSE //My concern grows
var/version = json_from_file["version"]
json_from_file = patch_version(json_from_file,version)
digestable = json_from_file["digestable"]
devourable = json_from_file["devourable"]
// allowmobvore = json_from_file["allowmobvore"]
vore_taste = json_from_file["vore_taste"]
// can_be_drop_prey = json_from_file["can_be_drop_prey"]
// can_be_drop_prey = json_from_file["can_be_drop_pred"]
belly_prefs = json_from_file["belly_prefs"]
//Quick sanitize
if(isnull(digestable))
digestable = TRUE
if(isnull(devourable))
devourable = FALSE
/* if(isnull(allowmobvore))
allowmobvore = TRUE
if(isnull(can_be_drop_prey))
allowmobvore = FALSE
if(isnull(can_be_drop_pred))
allowmobvore = FALSE */
if(isnull(belly_prefs))
belly_prefs = list()
return TRUE
/datum/vore_preferences/proc/save_vore()
if(!path) return FALSE
var/version = 1 //For "good times" use in the future
var/list/settings_list = list(
"version" = version,
"digestable" = digestable,
"devourable" = devourable,
"vore_taste" = vore_taste,
"belly_prefs" = belly_prefs,
)
/* commented out list things
"allowmobvore" = allowmobvore,
"can_be_drop_prey" = can_be_drop_prey,
"can_be_drop_pred" = can_be_drop_pred, */
//List to JSON
var/json_to_file = json_encode(settings_list)
if(!json_to_file)
testing("Saving: [path] failed jsonencode")
return FALSE
//Write it out
if(fexists(path))
fdel(path) //Byond only supports APPENDING to files, not replacing.
text2file(json_to_file,path)
if(!fexists(path))
testing("Saving: [path] failed file write")
return FALSE
return TRUE
//Can do conversions here
/datum/vore_preferences/proc/patch_version(var/list/json_from_file,var/version)
return json_from_file
-62
View File
@@ -1,62 +0,0 @@
// -------------- Sickshot -------------
/obj/item/gun/energy/sickshot
name = "\improper MPA6 \'Sickshot\'"
desc = "A device that can trigger convusions in specific areas to eject foreign material from a host. Must be used very close to a target. Not for Combat usage."
icon_state = "dragnet"
item_state = "dragnet"
ammo_x_offset = 1
ammo_type = list(/obj/item/ammo_casing/energy/sickshot)
/obj/item/ammo_casing/energy/sickshot
projectile_type = /obj/item/projectile/sickshot
e_cost = 100
//Projectile
/obj/item/projectile/sickshot
name = "sickshot pulse"
icon_state = "e_netting"
damage = 0
damage_type = STAMINA
range = 2
/obj/item/projectile/sickshot/on_hit(var/atom/movable/target, var/blocked = 0)
if(iscarbon(target))
var/mob/living/carbon/H = target
if(prob(5))
for(var/X in H.vore_organs)
H.release_vore_contents()
H.visible_message("<span class='danger'>[H] contracts strangely, spewing out contents on the floor!</span>", \
"<span class='userdanger'>You spew out everything inside you on the floor!</span>")
return
////////////////////////// Anti-Noms Drugs //////////////////////////
/*
/datum/reagent/medicine/ickypak
name = "Ickypak"
id = "ickypak"
description = "A foul-smelling green liquid, for inducing muscle contractions to expel accidentally ingested things."
reagent_state = LIQUID
color = "#0E900E"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
/datum/reagent/medicine/ickypak/on_mob_life(var/mob/living/M, method=INGEST)
if(prob(10))
M.visible_message("<span class='danger'>[M] retches!</span>", \
"<span class='userdanger'>You don't feel good...</span>")
for(var/I in M.vore_organs)
var/datum/belly/B = M.vore_organs[I]
for(var/atom/movable/A in B.internal_contents)
if(prob(55))
playsound(M, 'sound/effects/splat.ogg', 50, 1)
B.release_specific_contents(A)
M.visible_message("<span class='danger'>[M] contracts strangely, spewing out something!</span>", \
"<span class='userdanger'>You spew out something from inside you!</span>")
return ..()
/datum/chemical_reaction/ickypak
name = "Ickypak"
id = "ickypak"
results = list("ickypak" = 2)
required_reagents = list("chlorine" = 2 , "oil" = 1) */
-721
View File
@@ -1,721 +0,0 @@
//
// Vore management panel for players
//
#define BELLIES_MAX 20
#define BELLIES_NAME_MIN 2
#define BELLIES_NAME_MAX 12
#define BELLIES_DESC_MAX 1024
#define FLAVOR_MAX 40
/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_selected
var/dat = picker_holder.gen_vui(src)
picker_holder.popup = new(src, "insidePanel","Vore Panel", 400, 600, picker_holder)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
/mob/living/proc/updateVRPanel() //Panel popup update call from belly events.
if(src.openpanel == 1)
var/datum/vore_look/picker_holder = new()
picker_holder.loop = picker_holder
picker_holder.selected = vore_selected
var/dat = picker_holder.gen_vui(src)
picker_holder.popup = new(src, "insidePanel","Vore Panel", 400, 600, picker_holder)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
//
// Callback Handler for the Inside form
//
/datum/vore_look
var/obj/belly/selected
var/show_interacts = TRUE
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/Destroy()
loop = null
selected = null
return QDEL_HINT_HARDDEL
/datum/vore_look/Topic(href,href_list[])
if (vp_interact(href, href_list))
popup.set_content(gen_vui(usr))
usr << output(popup.get_content(), "insidePanel.browser")
/datum/vore_look/proc/gen_vui(var/mob/living/user)
var/dat
var/atom/userloc = user.loc
if (isbelly(userloc))
var/obj/belly/inside_belly = userloc
var/mob/living/eater = inside_belly.owner
//Don't display this part if we couldn't find the belly since could be held in hand.
if(inside_belly)
dat += "<font color = 'green'>You are currently [user.absorbed ? "absorbed into " : "inside "]</font> <font color = 'yellow'>[eater]'s</font> <font color = 'red'>[inside_belly]</font>!<br><br>"
if(inside_belly.desc)
dat += "[inside_belly.desc]<br><br>"
if (inside_belly.contents.len > 1)
dat += "You can see the following around you:<br>"
for (var/atom/movable/O in inside_belly)
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 += "<a href='?src=\ref[src];outsidepick=\ref[O];outsidebelly=\ref[inside_belly]'><span style='color:purple;'>[O]</span></a>"
continue
else
continue
//Anything else
dat += "<a href='?src=\ref[src];outsidepick=\ref[O];outsidebelly=\ref[inside_belly]'>[O]&#8203;</a>"
//Zero-width space, for wrapping
dat += "&#8203;"
else
dat += "You aren't inside anyone."
dat += "<HR>"
dat += "<ol style='list-style: none; padding: 0; overflow: auto;'>"
for(var/belly in user.vore_organs)
var/obj/belly/B = belly
if(B == selected)
dat += "<li style='float: left'><a href='?src=\ref[src];bellypick=\ref[B]'><b>[B.name]</b>"
else
dat += "<li style='float: left'><a href='?src=\ref[src];bellypick=\ref[B]'>[B.name]"
var/spanstyle
switch(B.digest_mode)
if(DM_HOLD)
spanstyle = ""
if(DM_DIGEST)
spanstyle = "color:red;"
if(DM_HEAL)
spanstyle = "color:green;"
if(DM_NOISY)
spanstyle = "color:purple;"
dat += "<span style='[spanstyle]'> ([B.contents.len])</span></a></li>"
if(user.vore_organs.len < BELLIES_MAX)
dat += "<li style='float: left'><a href='?src=\ref[src];newbelly=1'>New+</a></li>"
dat += "</ol>"
dat += "<HR>"
// Selected Belly (contents, configuration)
if(!selected)
dat += "No belly selected. Click one to select it."
else
if(selected.contents.len)
dat += "<b>Contents:</b> "
for(var/O in selected)
//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 += "<a href='?src=\ref[src];insidepick=\ref[O]'><span style='color:purple;'>[O]</span></a>"
continue
//Anything else
dat += "<a href='?src=\ref[src];insidepick=\ref[O]'>[O]</a>"
//Zero-width space, for wrapping
dat += "&#8203;"
//If there's more than one thing, add an [All] button
if(selected.contents.len > 1)
dat += "<a href='?src=\ref[src];insidepick=1;pickall=1'>\[All\]</a>"
dat += "<HR>"
//Belly Name Button
dat += "<a href='?src=\ref[src];b_name=\ref[selected]'>Name:</a>"
dat += " '[selected.name]'"
//Digest Mode Button
dat += "<br><a href='?src=\ref[src];b_mode=\ref[selected]'>Belly Mode:</a>"
dat += " [selected.digest_mode]"
//Belly verb
dat += "<br><a href='?src=\ref[src];b_verb=\ref[selected]'>Vore Verb:</a>"
dat += " '[selected.vore_verb]'"
//Inside flavortext
dat += "<br><a href='?src=\ref[src];b_desc=\ref[selected]'>Flavor Text:</a>"
dat += " '[selected.desc]'"
//Belly sound
dat += "<br><a href='?src=\ref[src];b_sound=\ref[selected]'>Set Vore Sound</a>"
dat += "<a href='?src=\ref[src];b_soundtest=\ref[selected]'>Test</a>"
//Release sound
dat += "<br><a href='?src=\ref[src];b_release=\ref[selected]'>Set Release Sound</a>"
dat += "<a href='?src=\ref[src];b_releasesoundtest=\ref[selected]'>Test</a>"
//Belly messages
dat += "<br><a href='?src=\ref[src];b_msgs=\ref[selected]'>Belly Messages</a>"
//Can belly taste?
dat += "<br><a href='?src=\ref[src];b_tastes=\ref[selected]'>Can Taste:</a>"
dat += " [selected.can_taste ? "Yes" : "No"]"
//Minimum size prey must be to show up.
dat += "<br><a href='?src=\ref[src];b_bulge_size=\ref[selected]'>Required examine size:</a>"
dat += " [selected.bulge_size*100]%"
//Belly escapability
dat += "<br><a href='?src=\ref[src];b_escapable=\ref[selected]'>Belly Interactions ([selected.escapable ? "On" : "Off"])</a>"
if(selected.escapable)
dat += "<a href='?src=\ref[src];show_int=\ref[selected]'>[show_interacts ? "Hide" : "Show"]</a>"
if(show_interacts && selected.escapable)
dat += "<HR>"
dat += "Interaction Settings <a href='?src=\ref[src];int_help=\ref[selected]'>?</a>"
dat += "<br><a href='?src=\ref[src];b_escapechance=\ref[selected]'>Set Belly Escape Chance</a>"
dat += " [selected.escapechance]%"
dat += "<br><a href='?src=\ref[src];b_escapetime=\ref[selected]'>Set Belly Escape Time</a>"
dat += " [selected.escapetime/10]s"
//Special <br> here to add a gap
dat += "<br style='line-height:5px;'>"
dat += "<br><a href='?src=\ref[src];b_transferchance=\ref[selected]'>Set Belly Transfer Chance</a>"
dat += " [selected.transferchance]%"
dat += "<br><a href='?src=\ref[src];b_transferlocation=\ref[selected]'>Set Belly Transfer Location</a>"
dat += " [selected.transferlocation ? selected.transferlocation : "Disabled"]"
//Special <br> here to add a gap
dat += "<br style='line-height:5px;'>"
dat += "<br><a href='?src=\ref[src];b_digestchance=\ref[selected]'>Set Belly Digest Chance</a>"
dat += " [selected.digestchance]%"
dat += "<HR>"
// Belly Silence
dat += "<br><a href='?src=\ref[src];b_silent=\ref[selected]'>Belly Silence (for not belly bellies):</a>"
dat += " [selected.silent ? "Yes" : "No"]"
//Delete button
dat += "<br><a style='background:#990000;' href='?src=\ref[src];b_del=\ref[selected]'>Delete Belly</a>"
dat += "<a href='?src=\ref[src];setflavor=1'>Set Flavor</a>"
dat += "<a href='?src=\ref[src];togglenoisy=1'>Toggle Hunger Noises</a>"
dat += "<HR>"
//Under the last HR, save and stuff.
dat += "<a href='?src=\ref[src];saveprefs=1'>Save Prefs</a>"
dat += "<a href='?src=\ref[src];refresh=1'>Refresh</a>"
dat += "<HR>"
switch(user.digestable)
if(TRUE)
dat += "<a href='?src=\ref[src];toggledg=1'>Toggle Digestable (Currently: ON)</a>"
if(FALSE)
dat += "<a href='?src=\ref[src];toggledg=1'>Toggle Digestable (Currently: OFF)</a>"
switch(user.devourable)
if(TRUE)
dat += "<a href='?src=\ref[src];toggledvor=1'>Toggle Devourable (Currently: ON)</a>"
if(FALSE)
dat += "<a href='?src=\ref[src];toggledvor=1'>Toggle Devourable (Currently: OFF)</a>"
//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"])
qdel(src) // Cleanup
return
if(href_list["show_int"])
show_interacts = !show_interacts
return TRUE //Force update
if(href_list["int_help"])
to_chat(usr,"These control how your belly responds to someone using 'resist' while inside you. The percent chance to trigger each is listed below, \
and you can change them to whatever you see fit. Setting them to 0% will disable the possibility of that interaction. \
These only function as long as interactions are turned on in general. Keep in mind, the 'belly mode' interactions (digest) \
will affect all prey in that belly, if one resists and triggers digestion. If multiple trigger at the same time, \
only the first in the order of 'Escape > Transfer > Digest' will occur.")
return TRUE //Force update
if(href_list["outsidepick"])
var/atom/movable/tgt = locate(href_list["outsidepick"])
var/obj/belly/OB = locate(href_list["outsidebelly"])
if(!(tgt in OB)) //Aren't here anymore, need to update menu.
return TRUE
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)
to_chat(user,"<span class='warning'>You can't do that in your state!</span>")
return 1
to_chat(user,"<font color='green'>You begin to push [M] to freedom!</font>")
to_chat(M,"[usr] begins to push you to freedom!")
to_chat(M.loc,"<span class='warning'>Someone is trying to escape from inside you!</span>")
sleep(50)
if(prob(33))
OB.release_specific_contents(M)
to_chat(usr,"<font color='green'>You manage to help [M] to safety!</font>")
to_chat(M,"<font color='green'>[user] pushes you free!</font>")
to_chat(OB.owner,"<span class='alert'>[M] forces free of the confines of your body!</span>")
else
to_chat(user,"<span class='alert'>[M] slips back down inside despite your efforts.</span>")
to_chat(M,"<span class='alert'> Even with [user]'s help, you slip back inside again.</span>")
to_chat(OB.owner,"<font color='green'>Your body efficiently shoves [M] back where they belong.</font>")
if("Devour") //Eat the inside mob
if(user.absorbed || user.stat)
to_chat(user,"<span class='warning'>You can't do that in your state!</span>")
return 1
if(!user.vore_selected)
to_chat(user,"<span class='warning'>Pick a belly on yourself first!</span>")
return 1
var/obj/belly/TB = user.vore_selected
to_chat(user,"<span class='warning'>You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!</span>")
to_chat(M,"<span class='warning'>[user] begins to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!</span>")
to_chat(OB.owner,"<span class='warning'>Someone inside you is eating someone else!</span>")
sleep(TB.nonhuman_prey_swallow_time) //Can't do after, in a stomach, weird things abound.
if((user in OB) && (M in OB)) //Make sure they're still here.
to_chat(user,"<span class='warning'>You manage to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!</span>")
to_chat(M,"<span class='warning'>[user] manages to [lowertext(TB.vore_verb)] you into their [lowertext(TB.name)]!</span>")
to_chat(OB.owner,"<span class='warning'>Someone inside you has eaten someone else!</span>")
TB.nom_mob(M)
else if(istype(tgt,/obj/item))
var/obj/item/T = tgt
if(!(tgt in OB.contents))
//Doesn't exist anymore, update.
return TRUE
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)
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
return
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
if("Eject all")
if(user.stat)
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
return
selected.release_all_contents()
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(user),'sound/vore/pred/escape.ogg',50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
to_chat(user.loc,"<span class='danger'>Everything is released from [user]!</span>")
if("Move all")
if(user.stat)
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
return FALSE
var/obj/belly/choice = input("Move all where?","Select Belly") as null|anything in user.vore_organs
if(!choice)
return FALSE
for(var/atom/movable/tgt in selected)
selected.transfer_contents(tgt, choice, 1)
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(user),'sound/vore/pred/stomachmove.ogg',50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
to_chat(tgt,"<span class='warning'>You're squished from [user]'s [lowertext(selected)] to their [lowertext(choice.name)]!</span>")
var/atom/movable/tgt = locate(href_list["insidepick"])
if(!(tgt in selected)) //Old menu, needs updating because they aren't really there.
return TRUE//Forces update
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)
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
return FALSE
selected.release_specific_contents(tgt)
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(user),'sound/vore/pred/escape.ogg',50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
user.loc << "<span class='danger'>[tgt] is released from [user]!</span>"
if("Move")
if(user.stat)
to_chat(user,"<span class='warning'>You can't do that in your state!</span>")
return 0
var/obj/belly/choice = input("Move [tgt] where?","Select Belly") as null|anything in user.vore_organs
if(!choice || !(tgt in selected))
return 0
to_chat(tgt,"<span class='warning'>You're squished from [user]'s [lowertext(selected.name)] to their [lowertext(choice.name)]!</span>")
selected.transfer_contents(tgt, choice)
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.toggles & EATING_NOISES)
playsound(get_turf(user),'sound/vore/pred/stomachmove.ogg',50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
if(href_list["newbelly"])
if(user.vore_organs.len >= BELLIES_MAX)
return 0
var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)
var/failure_msg
if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
// else if(whatever) //Next test here.
else
for(var/belly in user.vore_organs)
var/obj/belly/B = belly
if(lowertext(new_name) == lowertext(B.name))
failure_msg = "No duplicate belly names, please."
break
if(failure_msg) //Something went wrong.
alert(user,failure_msg,"Error!")
return 0
var/obj/belly/NB = new(user)
NB.name = new_name
selected = NB
if(href_list["bellypick"])
selected = locate(href_list["bellypick"])
user.vore_selected = selected
////
//Please keep these the same order they are on the panel UI for ease of coding
////
if(href_list["b_name"])
var/new_name = html_encode(input(usr,"Belly's new name:","New Name") as text|null)
var/failure_msg
if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
failure_msg = "Entered belly name length invalid (must be longer than [BELLIES_NAME_MIN], no more than than [BELLIES_NAME_MAX])."
// else if(whatever) //Next test here.
else
for(var/belly in user.vore_organs)
var/obj/belly/B = belly
if(lowertext(new_name) == lowertext(B.name))
failure_msg = "No duplicate belly names, please."
break
if(failure_msg) //Something went wrong.
alert(user,failure_msg,"Error!")
return 0
selected.name = new_name
if(href_list["b_mode"])
var/list/menu_list = selected.digest_modes
var/new_mode = input("Choose Mode (currently [selected.digest_mode])") as null|anything in menu_list
if(!new_mode)
return 0
selected.digest_mode = new_mode
if(href_list["b_desc"])
var/new_desc = html_encode(input(usr,"Belly Description ([BELLIES_DESC_MAX] char limit):","New Description",selected.desc) as message|null)
if(new_desc)
new_desc = readd_quotes(new_desc)
if(length(new_desc) > BELLIES_DESC_MAX)
alert("Entered belly desc too long. [BELLIES_DESC_MAX] character limit.","Error")
return FALSE
selected.desc = new_desc
else //Returned null
return FALSE
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"
)
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") as null|anything 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')."+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(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) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
alert("Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
return 0
selected.vore_verb = new_verb
if(href_list["b_release"])
var/choice = input(user,"Currently set to [selected.release_sound]","Select Sound") as null|anything in GLOB.release_sound
if(!choice)
return
selected.release_sound = GLOB.release_sound[choice]
if(href_list["b_releasesoundtest"])
var/soundfile = GLOB.release_sound[selected.release_sound]
if(soundfile)
user << soundfile
if(href_list["b_sound"])
var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.pred_vore_sounds
if(!choice)
return
selected.vore_sound = GLOB.pred_vore_sounds[choice]
if(href_list["b_soundtest"])
var/soundfile = GLOB.pred_vore_sounds[selected.vore_sound]
if(soundfile)
user << soundfile
if(href_list["b_tastes"])
selected.can_taste = !selected.can_taste
if(href_list["b_bulge_size"])
var/new_bulge = input(user, "Choose the required size prey must be to show up on examine, ranging from 25% to 200% Set this to 0 for no text on examine.", "Set Belly Examine Size.") as num|null
if(new_bulge == null)
return
if(new_bulge == 0) //Disable.
selected.bulge_size = 0
to_chat(user,"<span class='notice'>Your stomach will not be seen on examine.</span>")
else if (!IsInRange(new_bulge,25,200))
selected.bulge_size = 0.25 //Set it to the default.
to_chat(user,"<span class='notice'>Invalid size.</span>")
else if(new_bulge)
selected.bulge_size = (new_bulge/100)
if(href_list["b_escapable"])
if(selected.escapable == FALSE) //Possibly escapable and special interactions.
selected.escapable = TRUE
to_chat(usr,"<span class='warning'>Prey now have special interactions with your [selected.name] depending on your settings.</span>")
else if(selected.escapable == TRUE) //Never escapable.
selected.escapable = FALSE
to_chat(usr,"<span class='warning'>Prey will not be able to have special interactions with your [selected.name].</span>")
show_interacts = FALSE //Force the hiding of the panel
else
to_chat(usr,"<span class='warning'>Something went wrong. Your stomach will now not have special interactions. Press the button enable them again and tell a dev.") //If they somehow have a varable that's not 0 or 1
selected.escapable = TRUE
show_interacts = FALSE //Force the hiding of the panel
if(href_list["b_escapechance"])
var/escape_chance_input = input(user, "Set prey escape chance on resist (as %)", "Prey Escape Chance") as num|null
if(!isnull(escape_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options
selected.escapechance = sanitize_integer(escape_chance_input, 0, 100, initial(selected.escapechance))
if(href_list["b_escapetime"])
var/escape_time_input = input(user, "Set number of seconds for prey to escape on resist (1-60)", "Prey Escape Time") as num|null
if(!isnull(escape_time_input))
selected.escapetime = sanitize_integer(escape_time_input*10, 10, 600, initial(selected.escapetime))
if(href_list["b_transferchance"])
var/transfer_chance_input = input(user, "Set belly transfer chance on resist (as %). You must also set the location for this to have any effect.", "Prey Escape Time") as num|null
if(!isnull(transfer_chance_input))
selected.transferchance = sanitize_integer(transfer_chance_input, 0, 100, initial(selected.transferchance))
if(href_list["b_transferlocation"])
var/choice = input("Where do you want your [selected.name] to lead if prey resists?","Select Belly") as null|anything in (user.vore_organs + "None - Remove" - selected.name)
if(!choice) //They cancelled, no changes
return FALSE
else if(choice == "None - Remove")
selected.transferlocation = null
else
selected.transferlocation = user.vore_organs[choice]
if(href_list["b_absorbchance"])
var/absorb_chance_input = input(user, "Set belly absorb mode chance on resist (as %)", "Prey Absorb Chance") as num|null
if(!isnull(absorb_chance_input))
selected.absorbchance = sanitize_integer(absorb_chance_input, 0, 100, initial(selected.absorbchance))
if(href_list["b_digestchance"])
var/digest_chance_input = input(user, "Set belly digest mode chance on resist (as %)", "Prey Digest Chance") as num|null
if(!isnull(digest_chance_input))
selected.digestchance = sanitize_integer(digest_chance_input, 0, 100, initial(selected.digestchance))
if(href_list["b_silent"])
selected.silent = !selected.silent
if(href_list["b_del"])
var/alert = alert("Are you sure you want to delete your [lowertext(selected.name)]?","Confirmation","Delete","Cancel")
if(!alert == "Delete")
return FALSE
var/failure_msg = ""
var/dest_for //Check to see if it's the destination of another vore organ.
for(var/belly in user.vore_organs)
var/obj/belly/B = belly
if(B.transferlocation == selected)
dest_for = B.name
failure_msg += "This is the destiantion for at least '[dest_for]' belly transfers. Remove it as the destination from any bellies before deleting it. "
break
if(selected.contents.len)
failure_msg += "You cannot delete bellies with contents! " //These end with spaces, to be nice looking. Make sure you do the same.
if(selected.immutable)
failure_msg += "This belly is marked as undeletable. "
if(user.vore_organs.len == 1)
failure_msg += "You must have at least one belly. "
if(failure_msg)
alert(user,failure_msg,"Error!")
return FALSE
qdel(selected)
selected = user.vore_organs[1]
user.vore_selected = user.vore_organs[1]
if(href_list["saveprefs"])
if(!user.save_vore_prefs())
to_chat(user, "<span class='warning'>Belly Preferences not saved!</span>")
else
to_chat(user, "<span class='notice'>Belly Preferences were saved!</span>")
log_admin("Could not save vore prefs on USER: [user].")
if(href_list["setflavor"])
var/new_flavor = html_encode(input(usr,"What your character tastes like (40ch limit). This text will be printed to the pred after 'X tastes of...' so just put something like 'strawberries and cream':","Character Flavor",user.vore_taste) as text|null)
if(!new_flavor)
return 0
new_flavor = readd_quotes(new_flavor)
if(length(new_flavor) > FLAVOR_MAX)
alert("Entered flavor/taste text too long. [FLAVOR_MAX] character limit.","Error!")
return 0
user.vore_taste = new_flavor
if(href_list["toggledg"])
var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable to all mobs. Digesting you is currently: [user.digestable ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion")
switch(choice)
if("Cancel")
return
if("Allow Digestion")
user.digestable = TRUE
if("Prevent Digestion")
user.digestable = FALSE
if(user.client.prefs_vr)
user.client.prefs_vr.digestable = user.digestable
if(href_list["toggledvor"])
var/choice = alert(user, "This button is for those who don't like vore at all. Devouring you is currently: [user.devourable ? "Allowed" : "Prevented"]", "", "Allow Devourment", "Cancel", "Prevent Devourment")
switch(choice)
if("Cancel")
return
if("Allow Devourment")
user.devourable = TRUE
if("Prevent Devourment")
user.devourable = FALSE
if(user.client.prefs_vr)
user.client.prefs_vr.devourable = user.devourable
if(href_list["togglenoisy"])
var/choice = alert(user, "Toggle audible hunger noises. Currently: [user.noisy ? "Enabled" : "Disabled"]", "", "Enable audible hunger", "Cancel", "Disable audible hunger")
switch(choice)
if("Cancel")
return 0
if("Enable audible hunger")
user.noisy = TRUE
if("Disable audible hunger")
user.noisy = FALSE
//Refresh when interacted with, returning 1 makes vore_look.Topic update
return 1