Vore fixes and a few additions (#6032)

* Fixes saving memes, Adds absorbing and OOC escape

Also allows for people to reload from a slot if they fuck up and delete a belly

* makes sure travis won't flip the fuck out

* fixes some sound issues

* cleaning up some extra sounds, also dragon vore sound settings

* fixes resisting out of guts

* BRACKETS

* Prey now become blind after being eaten.

Use the audible subtle message to continue roleplaying with them!

* Actually make bulges show up in examine

* Fixes cases where transfering between bellies would blind twice

Because, y'know, that make sense. Also added self reminders if any changes happen to JSONs
This commit is contained in:
Poojawa
2018-03-26 04:46:50 -05:00
committed by GitHub
parent bf63fa766a
commit c579d81f4c
8 changed files with 221 additions and 152 deletions

View File

@@ -4,6 +4,8 @@
#define DM_HEAL "Heal"
#define DM_NOISY "Noisy"
#define DM_DRAGON "Dragon"
#define DM_ABSORB "Absorb"
#define DM_UNABSORB "Un-absorb"
#define isbelly(A) istype(A, /obj/belly)
@@ -51,12 +53,13 @@ GLOBAL_LIST_INIT(death_pred, list(
'sound/vore/pred/death_10.ogg'))
*/
GLOBAL_LIST_INIT(pred_vore_sounds, list(
GLOBAL_LIST_INIT(vore_sounds, list(
"Gulp" = 'sound/vore/pred/swallow_01.ogg',
"Swallow" = 'sound/vore/pred/swallow_02.ogg',
"Insertion1" = 'sound/vore/pred/insertion_01.ogg',
"Insertion2" = 'sound/vore/pred/insertion_02.ogg',
"Tauric Swallow" = 'sound/vore/pred/taurswallow.ogg',
"Stomach Move" = 'sound/vore/pred/stomachmove.ogg',
"Schlorp" = 'sound/vore/pred/schlorp.ogg',
"Squish1" = 'sound/vore/pred/squish_01.ogg',
"Squish2" = 'sound/vore/pred/squish_02.ogg',
@@ -75,7 +78,7 @@ GLOBAL_LIST_INIT(pred_struggle_sounds, list(
"Struggle3" = 'sound/vore/pred/struggle_03.ogg',
"Struggle4" = 'sound/vore/pred/struggle_04.ogg',
"Struggle5" = 'sound/vore/pred/struggle_05.ogg'))
*/
GLOBAL_LIST_INIT(prey_vore_sounds, list(
"Gulp" = 'sound/vore/prey/swallow_01.ogg',
"Swallow" = 'sound/vore/prey/swallow_02.ogg',
@@ -88,7 +91,7 @@ GLOBAL_LIST_INIT(prey_vore_sounds, list(
"Squish3" = 'sound/vore/prey/squish_03.ogg',
"Squish4" = 'sound/vore/prey/squish_04.ogg'))
/*
GLOBAL_LIST_INIT(prey_struggle_sounds, list(
"Struggle1" = 'sound/vore/prey/struggle_01.ogg',
"Struggle2" = 'sound/vore/prey/struggle_02.ogg',
@@ -129,7 +132,7 @@ GLOBAL_LIST_INIT(death_prey, list(
"death10" = 'sound/vore/prey/death_10.ogg'))
*/
GLOBAL_LIST_INIT(release_sound, list(
GLOBAL_LIST_INIT(release_sounds, list(
"rustle (cloth)" = 'sound/effects/rustle1.ogg',
"rustle2 (cloth)" = 'sound/effects/rustle2.ogg',
"rustle3 (cloth)" = 'sound/effects/rustle3.ogg',

View File

@@ -96,6 +96,8 @@
for(var/obj/item/organ/genital/dicc in internal_organs)
if(istype(dicc) && dicc.is_exposed())
msg += "[dicc.desc]\n"
msg += attempt_vr(src,"examine_bellies",args) //vore Code
//END OF CIT CHANGES
//Status effects
msg += status_effect_examines()

View File

@@ -23,7 +23,7 @@
name = "maw"
desc = "The maw of the dreaded Ash drake closes around you, engulfing you into a swelteringly hot, disgusting enviroment. The acidic saliva tingles over your form while that tongue pushes you further back...towards the dark gullet beyond."
vore_verb = "scoop"
vore_sound = 'sound/vore/pred/taurswallow.ogg'
vore_sound = "Stomach Move"
swallow_time = 20
escapechance = 25
// From above, will transfer into gullet
@@ -36,6 +36,7 @@
desc = "A ripple of muscle and arching of the tongue pushes you down like any other food. No choice in the matter, you're simply consumed. The dark ambiance of the outside world is replaced with working, wet flesh. Your only light being what you brought with you."
swallow_time = 60 // costs extra time to eat directly to here
escapechance = 5
vore_sound = "Squish2"
// From above, will transfer into gut
transferchance = 25
autotransferchance = 50
@@ -44,6 +45,7 @@
/obj/belly/megafauna/dragon/gut
name = "stomach"
vore_capacity = 5 //I doubt this many people will actually last in the gut, but...
vore_sound = "Tauric Swallow"
desc = "With a rush of burning ichor greeting you, you're introduced to the Drake's stomach. Wrinkled walls greedily grind against you, acidic slimes working into your body as you become fuel and nutriton for a superior predator. All that's left is your body's willingness to resist your destiny."
digest_mode = DM_DRAGON
digest_burn = 5

View File

@@ -13,9 +13,9 @@
/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_sound = "Gulp" // Sound when ingesting someone
var/vore_verb = "ingest" // Verb for eating with this in messages
var/release_sound = 'sound/effects/splat.ogg'
var/release_sound = "Splatter"
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
@@ -40,7 +40,7 @@
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/static/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY,DM_ABSORB,DM_UNABSORB) // 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)
@@ -103,7 +103,7 @@
//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.
//For serialization, keep this updated AND IN ORDER OF VARS LISTED ABOVE AND IN DUPE AT THE BOTTOM!!, required for bellies to save correctly.
/obj/belly/vars_to_save()
return ..() + list(
"name",
@@ -117,22 +117,22 @@
"digest_brute",
"digest_burn",
"immutable",
"can_taste",
"escapable",
"escapetime",
"digestchance",
"absorbchance",
"escapechance",
"can_taste",
"bulge_size",
"silent",
"transferchance",
"transferlocation",
"bulge_size",
"struggle_messages_outside",
"struggle_messages_inside",
"digest_messages_owner",
"digest_messages_prey",
"examine_messages",
"emote_lists",
"silent"
"emote_lists"
)
//ommitted list
@@ -172,9 +172,6 @@
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.
@@ -189,8 +186,8 @@
if(L.absorbed && !include_absorbed)
continue
L.absorbed = FALSE
for(var/mob/living/W in AM)
W.stop_sound_channel(CHANNEL_PREYLOOP)
L.stop_sound_channel(CHANNEL_PREYLOOP)
L.cure_blind("belly_[REF(src)]")
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)))
@@ -211,8 +208,6 @@
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.cit_toggles & EATING_NOISES)
@@ -221,6 +216,8 @@
if(istype(M,/mob/living))
var/mob/living/ML = M
var/mob/living/OW = owner
ML.stop_sound_channel(CHANNEL_PREYLOOP)
ML.cure_blind("belly_[REF(src)]")
if(ML.absorbed)
ML.absorbed = FALSE
if(ishuman(M) && ishuman(OW))
@@ -252,6 +249,9 @@
for(var/mob/living/M in contents)
M.updateVRPanel()
M.become_blind("belly_[REF(src)]")
// Setup the autotransfer checks if needed
if(transferlocation && autotransferchance > 0)
@@ -400,6 +400,8 @@
// Delete the digested mob
qdel(M)
//Update owner
owner.updateVRPanel()
// Handle a mob being absorbed
/obj/belly/proc/absorb_living(var/mob/living/M)
@@ -464,6 +466,10 @@
qdel(src) //final option, I guess.
testing("[src] (\ref[src]) was QDEL'd for not having a drop_location!")
//Yes, it's ""safe"" to drop items here
/obj/belly/AllowDrop()
return TRUE
//Handle a mob struggling
// Called from /mob/living/carbon/relaymove()
/obj/belly/proc/relay_resist(var/mob/living/R)
@@ -471,22 +477,6 @@
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)
@@ -501,9 +491,32 @@
struggle_outer_message = "<span class='alert'>" + struggle_outer_message + "</span>"
struggle_user_message = "<span class='alert'>" + struggle_user_message + "</span>"
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_mob(R,owner,50))
return
if(!(R in contents)) //Aren't even in the belly. Quietly fail.
return
if(R.a_intent != INTENT_HELP) //still want to?
release_specific_contents(R)
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
else //failsafe to make sure people are able to struggle out. friendly ERP should be on help intent.
to_chat(R,"<span class='warning'>You attempt to climb out of [lowertext(name)]. (This will take around [escapetime] seconds.)</span>")
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
if(!do_mob(R,owner,escapetime))
return
release_specific_contents(R)
return
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)
M.show_message(struggle_outer_message, 1) // visible
to_chat(R,struggle_user_message)
if(!silent)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
@@ -513,24 +526,6 @@
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)
@@ -548,24 +543,24 @@
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(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 && 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) && 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>")
@@ -581,6 +576,8 @@
/obj/belly/proc/transfer_contents(var/atom/movable/content, var/obj/belly/target, silent = FALSE)
if(!(content in src) || !istype(target))
return
for(var/mob/living/M in contents)
M.cure_blind("belly_[REF(src)]")
target.nom_mob(content, target.owner)
if(!silent)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
@@ -591,7 +588,7 @@
M.updateVRPanel()
// Belly copies and then returns the copy
// Needs to be updated for any var changes
// Needs to be updated for any var changes AND KEPT IN ORDER OF THE VARS ABOVE AS WELL!
/obj/belly/proc/copy(mob/new_owner)
var/obj/belly/dupe = new /obj/belly(new_owner)
@@ -607,16 +604,20 @@
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.can_taste = can_taste
dupe.bulge_size = bulge_size
// dupe.shrink_grow_size = shrink_grow_size
dupe.silent = silent
dupe.transferlocation = transferlocation
dupe.transferchance = transferchance
dupe.autotransferchance = autotransferchance
dupe.autotransferwait = autotransferwait
dupe.swallow_time = swallow_time
dupe.vore_capacity = vore_capacity
//// Object-holding variables
//struggle_messages_outside - strings
@@ -650,6 +651,4 @@
dupe.emote_lists[K] = list()
for(var/I in emote_lists[K])
dupe.emote_lists[K] += I
dupe.silent = silent
return dupe

View File

@@ -26,6 +26,11 @@
if(!length(touchable_items))
return SSBELLIES_PROCESSED
//////////////////////// Absorbed Handling ////////////////////////
for(var/mob/living/M in contents)
if(M.absorbed)
M.Stun(5)
////////////////////////// Sound vars /////////////////////////////
var/sound/prey_digest = sound(get_sfx("digest_prey"))
var/sound/prey_death = sound(get_sfx("death_prey"))
@@ -126,6 +131,39 @@
M.playsound_local(get_turf(M), prey_digest, 65)
//////////////////////////// DM_ABSORB ////////////////////////////
else if(digest_mode == DM_ABSORB)
for (var/mob/living/M in contents)
if(prob(10)) //Less often than gurgles. People might leave this on forever.
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)
if(M.absorbed)
continue
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
owner.nutrition += oldnutrition
else if(M.nutrition < 100) //When they're finally drained.
absorb_living(M)
//////////////////////////// DM_UNABSORB ////////////////////////////
else if(digest_mode == DM_UNABSORB)
for (var/mob/living/M in contents)
if(M.absorbed && owner.nutrition >= 100)
M.absorbed = 0
to_chat(M,"<span class='notice'>You suddenly feel solid again </span>")
to_chat(owner,"<span class='notice'>You feel like a part of you is missing.</span>")
owner.nutrition -= 100
//////////////////////////DM_DRAGON /////////////////////////////////////
//because dragons need snowflake guts
if(digest_mode == DM_DRAGON)

View File

@@ -17,35 +17,44 @@
/hook/living_new/proc/vore_setup(mob/living/M)
M.verbs += /mob/living/proc/preyloop_refresh
M.verbs += /mob/living/proc/lick
M.verbs += /mob/living/proc/escapeOOC
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
spawn(20 SECONDS) // long delay because the server delays in its startup. just on the safe side.
M.init_vore()
//Return 1 to hook-caller
return 1
/mob/living/proc/init_vore()
//Something else made organs, meanwhile.
if(LAZYLEN(vore_organs))
return TRUE
//We'll load our client's organs if we have one
if(client && client.prefs_vr)
if(!copy_from_prefs_vr())
to_chat(src,"<span class='warning'>ERROR: You seem to have saved vore prefs, but they couldn't be loaded.</span>")
return FALSE
if(LAZYLEN(vore_organs))
vore_selected = vore_organs[1]
return TRUE
//Or, we can create a basic one for them
if(!LAZYLEN(vore_organs))
LAZYINITLIST(vore_organs)
var/obj/belly/B = new /obj/belly(src)
vore_selected = B
B.immutable = 1
B.name = "Stomach"
B.desc = "It appears to be rather warm and wet. Makes sense, considering it's inside [name]."
B.can_taste = 1
return TRUE
/*
// Hide vore organs in contents
//
@@ -287,7 +296,7 @@
/mob/living/proc/preyloop_refresh()
set name = "Internal loop refresh"
set category = "Vore"
if(istype(src.loc, /obj/belly))
if(isbelly(loc))
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)
@@ -297,28 +306,38 @@
// OOC Escape code for pref-breaking or AFK preds
//
/mob/living/proc/escapeOOC()
set name = "Animal Escape"
set name = "OOC Escape"
set category = "Vore"
//You're in an animal!
if(istype(src.loc,/mob/living/simple_animal))
var/mob/living/simple_animal/pred = src.loc
var/confirm = alert(src, "You're in a mob. 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)
//You're in a belly!
if(isbelly(loc))
var/obj/belly/B = loc
var/confirm = alert(src, "You're in a mob. If you're otherwise unable to escape from a pred AFK for a long time, use this.", "Confirmation", "Okay", "Cancel")
if(!confirm == "Okay" || loc != B)
return
//Actual escaping
forceMove(get_turf(src)) //Just move me up to the turf, let's not cascade through bellies, there's been a problem, let's just leave.
if(is_blind(src) && !has_trait(TRAIT_BLIND))
src.adjust_blindness(-1)
src.stop_sound_channel(CHANNEL_PREYLOOP)
for(var/mob/living/simple_animal/SA in range(10))
SA.prey_excludes[src] = world.time
for(var/mob/living/simple_animal/SA in range(10))
SA.prey_excludes += src
spawn(18000)
if(src && SA)
SA.prey_excludes -= src
if(isanimal(B.owner))
var/mob/living/simple_animal/SA = B.owner
SA.update_icons()
pred.update_icons()
//You're in a dogborg!
else if(istype(loc, /obj/item/device/dogborg/sleeper))
var/obj/item/device/dogborg/sleeper/belly = loc //The belly!
var/confirm = alert(src, "You're in a dogborg sleeper. This is for escaping from preference-breaking or if your predator disconnects/AFKs. You can also resist out naturally too.", "Confirmation", "Okay", "Cancel")
if(!confirm == "Okay" || loc != belly)
return
//Actual escaping
belly.go_out(src) //Just force-ejects from the borg as if they'd clicked the eject button.
else
to_chat(src, "<span class='alert'>You aren't inside anything, you clod.</span>")
to_chat(src,"<span class='alert'>You aren't inside anyone, though, is the thing.</span>")
//
// Verb for saving vore preferences to save file

View File

@@ -108,10 +108,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
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
@@ -119,16 +116,21 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
digestable = TRUE
if(isnull(devourable))
devourable = FALSE
/* if(isnull(allowmobvore))
if(isnull(belly_prefs))
belly_prefs = list()
return TRUE
/*
allowmobvore = json_from_file["allowmobvore"]
can_be_drop_prey = json_from_file["can_be_drop_prey"]
can_be_drop_prey = json_from_file["can_be_drop_pred"]
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
@@ -142,11 +144,6 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
"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)
@@ -163,6 +160,11 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
return TRUE
/* commented out list things
"allowmobvore" = allowmobvore,
"can_be_drop_prey" = can_be_drop_prey,
"can_be_drop_pred" = can_be_drop_pred, */
//Can do conversions here
/datum/vore_preferences/proc/patch_version(var/list/json_from_file,var/version)
return json_from_file

View File

@@ -113,6 +113,8 @@
spanstyle = "color:green;"
if(DM_NOISY)
spanstyle = "color:purple;"
if(DM_ABSORB)
spanstyle = "color:purple;"
dat += "<span style='[spanstyle]'> ([B.contents.len])</span></a></li>"
@@ -199,6 +201,10 @@
dat += "<br><a href='?src=\ref[src];b_escapetime=\ref[selected]'>Set Belly Escape Time</a>"
dat += " [selected.escapetime/10]s"
dat += "<br style='line-height:5px;'>"
dat += "<br><a href='?src=\ref[src];b_absorbchance=\ref[selected]'>Set Belly Absorb Chance</a>"
dat += " [selected.absorbchance]%"
//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>"
@@ -228,6 +234,7 @@
//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 += "<a href='?src=\ref[src];applyprefs=1'>Reload Slot Prefs</a>"
dat += "<HR>"
switch(user.digestable)
@@ -262,7 +269,7 @@
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.")
only the first in the order of 'Escape > Transfer > Absorb > Digest' will occur.")
return TRUE //Force update
if(href_list["outsidepick"])
@@ -282,11 +289,11 @@
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
return
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>")
to_chat(OB.owner,"<span class='warning'>Someone is trying to escape from inside you!</span>")
sleep(50)
if(prob(33))
OB.release_specific_contents(M)
@@ -302,11 +309,11 @@
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
return
if(!user.vore_selected)
to_chat(user,"<span class='warning'>Pick a belly on yourself first!</span>")
return 1
return
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>")
@@ -354,9 +361,6 @@
return
selected.release_all_contents()
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
if(M.client && M.client.prefs.cit_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")
@@ -370,9 +374,6 @@
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.cit_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"])
@@ -390,9 +391,6 @@
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.cit_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")
@@ -406,9 +404,6 @@
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.cit_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)
@@ -540,28 +535,28 @@
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
var/choice = input(user,"Currently set to [selected.release_sound]","Select Sound") as null|anything in GLOB.release_sounds
if(!choice)
return
selected.release_sound = GLOB.release_sound[choice]
selected.release_sound = GLOB.release_sounds[choice]
if(href_list["b_releasesoundtest"])
var/soundfile = GLOB.release_sound[selected.release_sound]
var/soundfile = 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
var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.vore_sounds
if(!choice)
return
selected.vore_sound = GLOB.pred_vore_sounds[choice]
selected.vore_sound = GLOB.vore_sounds[choice]
if(href_list["b_soundtest"])
var/soundfile = GLOB.pred_vore_sounds[selected.vore_sound]
var/soundfile = selected.vore_sound
if(soundfile)
user << soundfile
@@ -670,6 +665,15 @@
to_chat(user, "<span class='notice'>Belly Preferences were saved!</span>")
log_admin("Could not save vore prefs on USER: [user].")
if(href_list["applyprefs"])
var/alert = alert("Are you sure you want to reload character slot preferences? This will remove your current vore organs and eject their contents.","Confirmation","Reload","Cancel")
if(!alert == "Reload")
return 0
if(!user.apply_vore_prefs())
alert("ERROR: Vore preferences failed to apply!","Error")
else
to_chat(user,"<span class='notice'>Vore preferences applied from active slot!</span>")
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)