Vore system updates (#2864)
* Tasting, digest/transfer chance, improvements * more vague for defaults * Actually let's hold off on silenced mode 'cuz broke * make sure it's all commented out * reverts vorepanel updater, buggy af. Adds mob vore Ian can eat you now. \o/
This commit is contained in:
@@ -95,6 +95,9 @@
|
||||
real_name = name
|
||||
if(!loc)
|
||||
stack_trace("Simple animal being instantiated in nullspace")
|
||||
if(vore_active)
|
||||
init_belly()
|
||||
verbs |= /mob/living/proc/animal_nom
|
||||
|
||||
|
||||
/mob/living/simple_animal/Login()
|
||||
|
||||
@@ -2,3 +2,71 @@
|
||||
// List of targets excluded (for now) from being eaten by this mob.
|
||||
var/list/prey_exclusions = list()
|
||||
devourable = FALSE //insurance because who knows.
|
||||
var/vore_active = FALSE // If vore behavior is enabled for this mob
|
||||
|
||||
var/vore_capacity = 1 // The capacity (in people) this person can hold
|
||||
var/vore_default_mode = DM_DIGEST // Default bellymode (DM_DIGEST, DM_HOLD, DM_ABSORB)
|
||||
var/vore_digest_chance = 25 // Chance to switch to digest mode if resisted
|
||||
var/vore_absorb_chance = 0 // Chance to switch to absorb mode if resisted
|
||||
var/vore_escape_chance = 25 // Chance of resisting out of mob
|
||||
|
||||
var/vore_stomach_name // The name for the first belly if not "stomach"
|
||||
var/vore_stomach_flavor // The flavortext for the first belly if not the default
|
||||
|
||||
|
||||
// Release belly contents beforey being gc'd!
|
||||
/mob/living/simple_animal/Destroy()
|
||||
for(var/I in vore_organs)
|
||||
var/datum/belly/B = vore_organs[I]
|
||||
B.release_all_contents() // When your stomach is empty
|
||||
prey_excludes.Cut()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/death()
|
||||
for(var/I in vore_organs)
|
||||
var/datum/belly/B = vore_organs[I]
|
||||
B.release_all_contents() // When your stomach is empty
|
||||
..() // then you have my permission to die.
|
||||
|
||||
// Simple animals have only one belly. This creates it (if it isn't already set up)
|
||||
/mob/living/simple_animal/proc/init_belly()
|
||||
if(vore_organs.len)
|
||||
return
|
||||
if(no_vore) //If it can't vore, let's not give it a stomach.
|
||||
return
|
||||
|
||||
var/datum/belly/B = new /datum/belly(src)
|
||||
B.immutable = TRUE
|
||||
B.name = vore_stomach_name ? vore_stomach_name : "stomach"
|
||||
B.inside_flavor = vore_stomach_flavor ? vore_stomach_flavor : "Your surroundings are warm, soft, and slimy. Makes sense, considering you're inside \the [name]."
|
||||
B.digest_mode = vore_default_mode
|
||||
B.escapable = vore_escape_chance > 0
|
||||
B.escapechance = vore_escape_chance
|
||||
B.digestchance = vore_digest_chance
|
||||
B.human_prey_swallow_time = swallowTime
|
||||
B.nonhuman_prey_swallow_time = swallowTime
|
||||
B.vore_verb = "swallow"
|
||||
// TODO - Customizable per mob
|
||||
B.emote_lists[DM_HOLD] = list( // We need more that aren't repetitive. I suck at endo. -Ace
|
||||
"The insides knead at you gently for a moment.",
|
||||
"The guts glorp wetly around you as some air shifts.",
|
||||
"The predator takes a deep breath and sighs, shifting you somewhat.",
|
||||
"The stomach squeezes you tight for a moment, then relaxes harmlessly.",
|
||||
"The predator's calm breathing and thumping heartbeat pulses around you.",
|
||||
"The warm walls kneads harmlessly against you.",
|
||||
"The liquids churn around you, though there doesn't seem to be much effect.",
|
||||
"The sound of bodily movements drown out everything for a moment.",
|
||||
"The predator's movements gently force you into a different position.")
|
||||
B.emote_lists[DM_DIGEST] = list(
|
||||
"The burning acids eat away at your form.",
|
||||
"The muscular stomach flesh grinds harshly against you.",
|
||||
"The caustic air stings your chest when you try to breathe.",
|
||||
"The slimy guts squeeze inward to help the digestive juices soften you up.",
|
||||
"The onslaught against your body doesn't seem to be letting up; you're food now.",
|
||||
"The predator's body ripples and crushes against you as digestive enzymes pull you apart.",
|
||||
"The juices pooling beneath you sizzle against your sore skin.",
|
||||
"The churning walls slowly pulverize you into meaty nutrients.",
|
||||
"The stomach glorps and gurgles as it tries to work you into slop.")
|
||||
src.vore_organs[B.name] = B
|
||||
src.vore_selected = B.name
|
||||
|
||||
|
||||
@@ -13,16 +13,21 @@
|
||||
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 = 100 // Time in deciseconds to swallow /mob/living/carbon/human
|
||||
var/nonhuman_prey_swallow_time = 60 // Time in deciseconds to swallow anything else
|
||||
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 = 300 // 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 = TRUE // Belly can be resisted out of at any time
|
||||
var/escapetime = 200 // Deciseconds, how long to escape this belly
|
||||
var/escapechance = 45 // % Chance of prey beginning to escape if prey struggles.
|
||||
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/transferchance = 0 // % Chance of prey being
|
||||
var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone.
|
||||
var/datum/belly/transferlocation = null // Location that the prey is released if they struggle and get dropped off.
|
||||
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.
|
||||
@@ -125,7 +130,7 @@
|
||||
|
||||
M.forceMove(owner.loc) // Move the belly contents into the same location as belly's owner.
|
||||
M << sound(null, repeat = 0, wait = 0, volume = 80, channel = CHANNEL_PREYLOOP)
|
||||
src.internal_contents.Add(M) // Remove from the belly contents
|
||||
src.internal_contents.Remove(M) // Remove from the belly contents
|
||||
var/datum/belly/B = check_belly(owner)
|
||||
if(B)
|
||||
B.internal_contents.Add(M)
|
||||
@@ -143,10 +148,13 @@
|
||||
|
||||
prey.forceMove(owner)
|
||||
internal_contents.Add(prey)
|
||||
|
||||
// var/datum/belly/B = check_belly(owner)
|
||||
// if(B.silenced == FALSE) //this needs more testing later
|
||||
prey << sound('sound/vore/prey/loop.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_PREYLOOP)
|
||||
|
||||
if(inside_flavor)
|
||||
prey << "<span class='notice'><B>[inside_flavor]</B></span>"
|
||||
to_chat(prey, "<span class='warning'><B>[src.inside_flavor]</B></span>")
|
||||
|
||||
// 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,
|
||||
@@ -158,6 +166,8 @@
|
||||
var/raw_message = pick(examine_messages)
|
||||
|
||||
formatted_message = replacetext(raw_message,"%belly",lowertext(name))
|
||||
formatted_message = replacetext(formatted_message,"%pred",owner)
|
||||
formatted_message = replacetext(formatted_message,"%prey",english_list(internal_contents))
|
||||
|
||||
return("<span class='warning'>[formatted_message]</span><BR>")
|
||||
|
||||
@@ -226,8 +236,8 @@
|
||||
internal_contents.Remove(M)
|
||||
M << sound(null, repeat = 0, wait = 0, volume = 80, channel = CHANNEL_PREYLOOP)
|
||||
// If digested prey is also a pred... anyone inside their bellies gets moved up.
|
||||
if (is_vore_predator(M))
|
||||
for (var/bellytype in M.vore_organs)
|
||||
if(is_vore_predator(M))
|
||||
for(var/bellytype in M.vore_organs)
|
||||
var/datum/belly/belly = M.vore_organs[bellytype]
|
||||
for (var/obj/thing in belly.internal_contents)
|
||||
thing.loc = owner
|
||||
@@ -237,7 +247,7 @@
|
||||
internal_contents.Add(subprey)
|
||||
to_chat(subprey, "As [M] melts away around you, you find yourself in [owner]'s [name]")
|
||||
|
||||
//Drop all items into the belly.
|
||||
//Drop all items into the belly/floor.
|
||||
for(var/obj/item/W in M)
|
||||
if(!M.dropItemToGround(W))
|
||||
qdel(W)
|
||||
@@ -312,12 +322,57 @@
|
||||
to_chat(owner, "<span class='notice'>The attempt to escape from your [name] has failed!/span>")
|
||||
return
|
||||
|
||||
else if(prob(transferchance) && istype(transferlocation)) //Next, let's have it see if they end up getting into an even bigger mess then when they started.
|
||||
var/location_found = FALSE
|
||||
var/name_found = FALSE
|
||||
for(var/I in owner.vore_organs)
|
||||
var/datum/belly/B = owner.vore_organs[I]
|
||||
if(B == transferlocation)
|
||||
location_found = TRUE
|
||||
break
|
||||
|
||||
if(!location_found)
|
||||
for(var/I in owner.vore_organs)
|
||||
var/datum/belly/B = owner.vore_organs[I]
|
||||
if(B.name == transferlocation.name)
|
||||
name_found = TRUE
|
||||
transferlocation = B
|
||||
break
|
||||
|
||||
if(!location_found && !name_found)
|
||||
to_chat(owner, "<span class='warning'>Something went wrong with your belly transfer settings.</span>")
|
||||
transferlocation = null
|
||||
return
|
||||
|
||||
to_chat(R, "<span class='warning'>Your attempt to escape [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 [name]!</span>")
|
||||
transfer_contents(R, transferlocation)
|
||||
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'>But make no progress in escaping [owner]'s [name].</span>")
|
||||
to_chat(owner, "<span class='warning'>But appears to be unable to make any progress in escaping your [name].</span>")
|
||||
return
|
||||
else
|
||||
//Transfers contents from one belly to another
|
||||
/datum/belly/proc/transfer_contents(var/atom/movable/content, var/datum/belly/target, silent = 0)
|
||||
if(!(content in internal_contents))
|
||||
return
|
||||
internal_contents.Remove(content)
|
||||
target.internal_contents.Add(content)
|
||||
if(isliving(content))
|
||||
var/mob/living/M = content
|
||||
if(target.inside_flavor)
|
||||
to_chat(M, "<span class='notice'><B>[target.inside_flavor]</B></span>")
|
||||
if(target.can_taste && M.get_taste_message(0))
|
||||
to_chat(owner, "<span class='notice'>[M] tastes of [M.get_taste_message(0)].</span>")
|
||||
if(!silent)
|
||||
for(var/mob/hearer in range(1,owner))
|
||||
hearer << sound(target.vore_sound,volume=80)
|
||||
|
||||
// Belly copies and then returns the copy
|
||||
// Needs to be updated for any var changes
|
||||
@@ -336,8 +391,13 @@
|
||||
dupe.digest_burn = digest_burn
|
||||
dupe.digest_tickrate = digest_tickrate
|
||||
dupe.immutable = immutable
|
||||
dupe.can_taste = can_taste
|
||||
dupe.escapable = escapable
|
||||
dupe.escapetime = escapetime
|
||||
dupe.digestchance = digestchance
|
||||
dupe.escapechance = escapechance
|
||||
dupe.transferchance = transferchance
|
||||
dupe.transferlocation = transferlocation
|
||||
|
||||
//// Object-holding variables
|
||||
//struggle_messages_outside - strings
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//////////////////////////// DM_DIGEST ////////////////////////////
|
||||
if(digest_mode == DM_DIGEST)
|
||||
for (var/mob/living/M in internal_contents)
|
||||
if(prob(15))
|
||||
if(prob(25))
|
||||
M.stop_sound_channel(CHANNEL_PRED)
|
||||
playsound(get_turf(owner),"digest_pred",50,0,-6,0,channel=CHANNEL_PRED)
|
||||
M.stop_sound_channel(CHANNEL_PRED)
|
||||
@@ -62,14 +62,14 @@
|
||||
|
||||
// Deal digestion damage (and feed the pred)
|
||||
if(!(M.status_flags & GODMODE))
|
||||
M.adjustFireLoss(1)
|
||||
M.adjustFireLoss(digest_burn)
|
||||
owner.nutrition += 1
|
||||
return
|
||||
|
||||
///////////////////////////// DM_HEAL /////////////////////////////
|
||||
if(digest_mode == DM_HEAL)
|
||||
for (var/mob/living/M in internal_contents)
|
||||
if(prob(15))
|
||||
if(prob(25))
|
||||
M.stop_sound_channel(CHANNEL_PRED)
|
||||
playsound(get_turf(owner),"digest_pred",35,0,-6,0,channel=CHANNEL_PRED)
|
||||
M.stop_sound_channel(CHANNEL_PRED)
|
||||
|
||||
@@ -5,14 +5,20 @@
|
||||
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?
|
||||
|
||||
//
|
||||
// Hook for generic creation of stuff on new creatures
|
||||
//
|
||||
/hook/living_new/proc/vore_setup(mob/living/M)
|
||||
M.verbs += /mob/living/proc/insidePanel
|
||||
M.verbs += /mob/living/proc/escapeOOC
|
||||
M.verbs += /mob/living/proc/lick
|
||||
if(M.no_vore) //If the mob isn's supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
|
||||
M << "<span class='warning'>The creature that you are can not eat others.</span>"
|
||||
return TRUE
|
||||
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)
|
||||
@@ -32,7 +38,8 @@
|
||||
var/datum/belly/B = new /datum/belly(M)
|
||||
B.immutable = TRUE
|
||||
B.name = "Stomach"
|
||||
B.inside_flavor = "It appears to be rather warm and wet. Makes sense, considering it's inside \the [M.name]."
|
||||
B.inside_flavor = "It appears to be rather warm and wet. Makes sense, considering it's inside \the [M.name]"
|
||||
B.can_taste = TRUE
|
||||
M.vore_organs[B.name] = B
|
||||
M.vore_selected = B.name
|
||||
|
||||
@@ -302,6 +309,7 @@
|
||||
P.digestable = src.digestable
|
||||
P.devourable = src.devourable
|
||||
P.belly_prefs = src.vore_organs
|
||||
P.vore_taste = src.vore_taste
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -318,9 +326,48 @@
|
||||
src.digestable = P.digestable
|
||||
src.devourable = P.devourable
|
||||
src.vore_organs = list()
|
||||
src.vore_taste = P.vore_taste
|
||||
|
||||
for(var/I in P.belly_prefs)
|
||||
var/datum/belly/Bp = P.belly_prefs[I]
|
||||
src.vore_organs[Bp.name] = Bp.copy(src)
|
||||
|
||||
return TRUE
|
||||
//
|
||||
// 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 += "normal, like a critter should"
|
||||
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,19 +1,9 @@
|
||||
///////////////////// Simple Animal /////////////////////
|
||||
/mob/living/simple_animal
|
||||
var/isPredator = 0 //Are they capable of performing and pre-defined vore actions for their species?
|
||||
var/swallowTime = 30 //How long it takes to eat its prey in 1/10 of a second. The default is 3 seconds.
|
||||
var/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 nom proc for if you get ckey'd into a simple_animal mob! Avoids grabs.
|
||||
/*
|
||||
/mob/living/proc/animal_nom(var/mob/living/T in oview(1))
|
||||
set name = "Animal Nom"
|
||||
set category = "Vore"
|
||||
set desc = "Since you can't grab, you get a verb!"
|
||||
|
||||
feed_grabbed_to_self(src,T)
|
||||
*/
|
||||
//
|
||||
// Simple proc for animals to have their digestion toggled on/off externally
|
||||
//
|
||||
@@ -25,15 +15,30 @@
|
||||
|
||||
var/datum/belly/B = vore_organs[vore_selected]
|
||||
if(faction != usr.faction)
|
||||
usr << "<span class='warning'>This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you.</span>"
|
||||
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"
|
||||
spawn(12000) //12000=20 minutes
|
||||
if(src) B.digest_mode = "Hold"
|
||||
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"
|
||||
B.digest_mode = "Hold"
|
||||
|
||||
//
|
||||
// Simple nom proc for if you get ckey'd into a simple_animal mob! Avoids grabs.
|
||||
//
|
||||
/mob/living/proc/animal_nom(var/mob/living/T in oview(1))
|
||||
set name = "Animal Nom"
|
||||
set category = "Vore"
|
||||
set desc = "Since you can't grab, you get a verb!"
|
||||
|
||||
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)
|
||||
@@ -41,6 +41,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
var/digestable = TRUE
|
||||
var/devourable = FALSE
|
||||
var/list/belly_prefs = list()
|
||||
var/vore_taste
|
||||
|
||||
//Mechanically required
|
||||
var/path
|
||||
@@ -101,6 +102,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
S["digestable"] >> digestable
|
||||
S["devourable"] >> devourable
|
||||
S["belly_prefs"] >> belly_prefs
|
||||
S["vore_taste"] >> vore_taste
|
||||
|
||||
if(isnull(digestable))
|
||||
digestable = TRUE
|
||||
@@ -121,6 +123,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
WRITE_FILE(S["digestable"], digestable)
|
||||
WRITE_FILE(S["devourable"], devourable)
|
||||
WRITE_FILE(S["belly_prefs"], belly_prefs)
|
||||
WRITE_FILE(S["vore_taste"], vore_taste)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
// 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"
|
||||
@@ -21,9 +27,15 @@
|
||||
//
|
||||
/datum/vore_look
|
||||
var/datum/belly/selected
|
||||
var/show_interacts = FALSE
|
||||
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))
|
||||
@@ -55,6 +67,8 @@
|
||||
continue
|
||||
//Anything else
|
||||
dat += "<a href='?src=\ref[src];outsidepick=\ref[O];outsidebelly=\ref[inside_belly]'>[O]</a>"
|
||||
//Zero-width space, for wrapping
|
||||
dat += "​"
|
||||
else
|
||||
dat += "You aren't inside anyone."
|
||||
|
||||
@@ -79,7 +93,7 @@
|
||||
|
||||
dat += "<span style='[spanstyle]'> ([B.internal_contents.len])</span></a></li>"
|
||||
|
||||
if(user.vore_organs.len < 10)
|
||||
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>"
|
||||
@@ -93,6 +107,8 @@
|
||||
for(var/O in selected.internal_contents)
|
||||
dat += "<a href='?src=\ref[src];insidepick=\ref[O]'>[O]</a>"
|
||||
|
||||
//Zero-width space, for wrapping
|
||||
dat += "​"
|
||||
//If there's more than one thing, add an [All] button
|
||||
if(selected.internal_contents.len > 1)
|
||||
dat += "<a href='?src=\ref[src];insidepick=1;pickall=1'>\[All\]</a>"
|
||||
@@ -119,9 +135,44 @@
|
||||
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>"
|
||||
|
||||
// //Belly silence
|
||||
// dat += "<br><a href='?src=\ref[src];silenced=\ref[selected]'>Belly Silence ([selected.silenced ? "Silenced" : "Noisy"])</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"]"
|
||||
|
||||
//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>"
|
||||
|
||||
//Delete button
|
||||
dat += "<br><a style='background:#990000;' href='?src=\ref[src];b_del=\ref[selected]'>Delete Belly</a>"
|
||||
|
||||
@@ -130,7 +181,9 @@
|
||||
//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];setflavor=1'>Set Flavor</a>"
|
||||
|
||||
dat += "<HR>"
|
||||
switch(user.digestable)
|
||||
if(TRUE)
|
||||
dat += "<a href='?src=\ref[src];toggledg=1'>Toggle Digestable (Currently: ON)</a>"
|
||||
@@ -151,12 +204,26 @@
|
||||
for(var/H in href_list)
|
||||
|
||||
if(href_list["close"])
|
||||
del(src) // Cleanup
|
||||
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/tgt = locate(href_list["outsidepick"])
|
||||
var/atom/movable/tgt = locate(href_list["outsidepick"])
|
||||
var/datum/belly/OB = locate(href_list["outsidebelly"])
|
||||
if(!(tgt in OB.internal_contents)) //Aren't here anymore, need to update menu.
|
||||
return TRUE
|
||||
var/intent = "Examine"
|
||||
|
||||
if(istype(tgt,/mob/living))
|
||||
@@ -184,7 +251,7 @@
|
||||
if("Devour") //Eat the inside mob
|
||||
if(!user.vore_selected)
|
||||
to_chat(user, "<span class='warning'>Pick a belly on yourself first!</span>")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
var/datum/belly/TB = user.vore_organs[user.vore_selected]
|
||||
to_chat(user, "<span class='warning'>You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!</span>")
|
||||
@@ -202,6 +269,9 @@
|
||||
|
||||
else if(istype(tgt,/obj/item))
|
||||
var/obj/item/T = tgt
|
||||
if(!(tgt in OB.internal_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")
|
||||
@@ -210,7 +280,7 @@
|
||||
if("Use Hand")
|
||||
if(user.stat)
|
||||
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
user.ClickOn(T)
|
||||
sleep(5) //Seems to exit too fast for the panel to update
|
||||
@@ -223,40 +293,38 @@
|
||||
intent = alert("Eject all, Move all?","Query","Eject all","Cancel","Move all")
|
||||
switch(intent)
|
||||
if("Cancel")
|
||||
return 1
|
||||
return
|
||||
|
||||
if("Eject all")
|
||||
if(user.stat)
|
||||
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
selected.release_all_contents()
|
||||
playsound(user, 'sound/vore/pred/escape.ogg', volume=80)
|
||||
user.loc << "<span class='danger'>Everything is released from [user]!</span>"
|
||||
playsound(user, 'sound/vore/pred/escape.ogg', vol=80)
|
||||
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 TRUE
|
||||
return
|
||||
|
||||
var/choice = input("Move all where?","Select Belly") in user.vore_organs + "Cancel - Don't Move"
|
||||
|
||||
if(choice == "Cancel - Don't Move")
|
||||
return TRUE
|
||||
return
|
||||
else
|
||||
var/datum/belly/B = user.vore_organs[choice]
|
||||
for(var/atom/movable/tgt in selected.internal_contents)
|
||||
selected.internal_contents -= tgt
|
||||
B.internal_contents += tgt
|
||||
|
||||
to_chat(tgt, "<span class='warning'>You're squished from [user]'s [selected] to their [B]!</span>")
|
||||
selected.transfer_contents(tgt, B, 1)
|
||||
|
||||
for(var/mob/hearer in range(1,user))
|
||||
hearer << sound('sound/vore/pred/stomachmove.ogg',volume=80)
|
||||
return TRUE
|
||||
|
||||
|
||||
var/atom/movable/tgt = locate(href_list["insidepick"])
|
||||
if(!(tgt in selected.internal_contents)) //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)
|
||||
@@ -266,7 +334,7 @@
|
||||
if("Eject")
|
||||
if(user.stat)
|
||||
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
selected.release_specific_contents(tgt)
|
||||
playsound(user, 'sound/effects/splat.ogg', 50, 1)
|
||||
@@ -275,28 +343,28 @@
|
||||
if("Move")
|
||||
if(user.stat)
|
||||
to_chat(user, "<span class='warning'>You can't do that in your state!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
var/choice = input("Move [tgt] where?","Select Belly") in user.vore_organs + "Cancel - Don't Move"
|
||||
|
||||
if(choice == "Cancel - Don't Move")
|
||||
return TRUE
|
||||
return
|
||||
else
|
||||
var/datum/belly/B = user.vore_organs[choice]
|
||||
selected.internal_contents -= tgt
|
||||
B.internal_contents += tgt
|
||||
|
||||
to_chat(tgt, "<span class='warning'>You're squished from [user]'s [lowertext(selected.name)] to their [lowertext(B.name)]!</span>")
|
||||
if (!(tgt in selected.internal_contents))
|
||||
return FALSE
|
||||
to_chat(tgt, "<span class='warning'>You're moved from [user]'s [lowertext(selected.name)] to their [lowertext(B.name)]!</span>")
|
||||
for(var/mob/hearer in range(1,user))
|
||||
hearer << sound('sound/vore/pred/stomachmove.ogg',volume=80)
|
||||
selected.transfer_contents(tgt, B)
|
||||
|
||||
if(href_list["newbelly"])
|
||||
if(user.vore_organs.len >= 10)
|
||||
if(user.vore_organs.len >= BELLIES_MAX)
|
||||
return TRUE
|
||||
|
||||
var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)
|
||||
|
||||
if(length(new_name) > 12 || length(new_name) < 2)
|
||||
if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
|
||||
to_chat(usr, "<span class='warning'>Entered belly name is too long.</span>")
|
||||
return FALSE
|
||||
if(new_name in user.vore_organs)
|
||||
@@ -313,10 +381,13 @@
|
||||
selected = locate(href_list["bellypick"])
|
||||
user.vore_selected = selected.name
|
||||
|
||||
////
|
||||
//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)
|
||||
|
||||
if(length(new_name) > 12 || length(new_name) < 2)
|
||||
if(length(new_name) > BELLIES_NAME_MAX || length(new_name) < BELLIES_NAME_MIN)
|
||||
to_chat(usr, "<span class='warning'>Entered belly name length invalid (must be longer than 2, shorter than 12).</span>")
|
||||
return FALSE
|
||||
if(new_name in user.vore_organs)
|
||||
@@ -344,14 +415,16 @@
|
||||
|
||||
if(href_list["b_desc"])
|
||||
var/new_desc = html_encode(input(usr,"Belly Description (1024 char limit):","New Description",selected.inside_flavor) as message|null)
|
||||
new_desc = readd_quotes(new_desc)
|
||||
if(new_desc)
|
||||
new_desc = readd_quotes(new_desc)
|
||||
if(length(new_desc) > BELLIES_DESC_MAX)
|
||||
to_chat(usr, "<span class='warning'>Entered belly desc too long. [BELLIES_DESC_MAX] character limit.</span>")
|
||||
return FALSE
|
||||
|
||||
if(length(new_desc) > 1024)
|
||||
to_chat(usr, "<span class='warning'>Entered belly desc too long. 1024 character limit.</span>")
|
||||
selected.inside_flavor = new_desc
|
||||
else //Returned null
|
||||
return FALSE
|
||||
|
||||
selected.inside_flavor = new_desc
|
||||
|
||||
if(href_list["b_msgs"])
|
||||
var/list/messages = list(
|
||||
"Digest Message (to prey)",
|
||||
@@ -389,7 +462,7 @@
|
||||
selected.set_messages(new_message,"smi")
|
||||
|
||||
if("Examine Message (when full)")
|
||||
var/new_message = input(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging'). Do not use %pred or %prey in this type."+help,"Examine Message (when full)",selected.get_messages("em")) as message
|
||||
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")
|
||||
|
||||
@@ -402,13 +475,13 @@
|
||||
selected.struggle_messages_inside = initial(selected.struggle_messages_inside)
|
||||
|
||||
if("Cancel - No Changes")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
if(href_list["b_verb"])
|
||||
var/new_verb = html_encode(input(usr,"New verb when eating (infinitive tense, e.g. nom or swallow):","New Verb") as text|null)
|
||||
|
||||
if(length(new_verb) > 12 || length(new_verb) < 2)
|
||||
to_chat(usr, "<span class='warning'>Entered verb length invalid (must be longer than 2, shorter than 12).</span>")
|
||||
if(length(new_verb) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
|
||||
to_chat(usr, "<span class='warning'>Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).</span>")
|
||||
return FALSE
|
||||
|
||||
selected.vore_verb = new_verb
|
||||
@@ -417,20 +490,90 @@
|
||||
var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") in GLOB.pred_vore_sounds + "Cancel - No Changes"
|
||||
|
||||
if(choice == "Cancel")
|
||||
return 1
|
||||
return
|
||||
|
||||
selected.vore_sound = GLOB.pred_vore_sounds[choice]
|
||||
|
||||
if(href_list["b_soundtest"])
|
||||
user << selected.vore_sound
|
||||
/*
|
||||
if(href_list["silenced"])
|
||||
if(selected.silenced == FALSE)
|
||||
selected.silenced = TRUE
|
||||
to_chat(usr,"<span class='warning'>The [selected.name] is now silenced, it will not play the internal loop to prey within it.</span>")
|
||||
else if(selected.silenced == TRUE)
|
||||
selected.silenced = FALSE
|
||||
to_chat(usr,"<span class='warning'>The [selected.name] will play the internal loop to prey within it.</span>")
|
||||
*/
|
||||
if(href_list["b_tastes"])
|
||||
selected.can_taste = !selected.can_taste
|
||||
|
||||
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 = FALSE
|
||||
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
|
||||
else if(choice == "None - Remove")
|
||||
selected.transferlocation = null
|
||||
else
|
||||
selected.transferlocation = user.vore_organs[choice]
|
||||
|
||||
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_del"])
|
||||
var/dest_for = FALSE //Check to see if it's the destination of another vore organ.
|
||||
for(var/I in user.vore_organs)
|
||||
var/datum/belly/B = user.vore_organs[I]
|
||||
if(B.transferlocation == selected)
|
||||
dest_for = B.name
|
||||
break
|
||||
|
||||
if(dest_for)
|
||||
alert("This is the destiantion for at least '[dest_for]' belly transfers. Remove it as the destination from any bellies before deleting it.","Error")
|
||||
return TRUE
|
||||
else if(selected.internal_contents.len)
|
||||
alert("Can't delete bellies with contents!","Error")
|
||||
return TRUE
|
||||
if(selected.internal_contents.len)
|
||||
to_chat(usr, "<span class='warning'>Can't delete bellies with contents!</span>")
|
||||
return
|
||||
else if(selected.immutable)
|
||||
to_chat(usr, "<span class='warning'>This belly is marked as undeletable.</span>")
|
||||
return
|
||||
else if(user.vore_organs.len == 1)
|
||||
to_chat(usr, "<span class='warning'>You must have at least one belly.</span>")
|
||||
return
|
||||
else
|
||||
var/alert = alert("Are you sure you want to delete [selected]?","Confirmation","Delete","Cancel")
|
||||
if(alert == "Delete" && !selected.internal_contents.len)
|
||||
@@ -438,6 +581,7 @@
|
||||
user.vore_organs.Remove(selected)
|
||||
selected = user.vore_organs[1]
|
||||
user.vore_selected = user.vore_organs[1]
|
||||
to_chat(usr,"<span class='warning'>Note: If you had this organ selected as a transfer location, please remove the transfer location by selecting Cancel - None - Remove on this stomach.</span>")
|
||||
|
||||
if(href_list["saveprefs"])
|
||||
if(user.save_vore_prefs())
|
||||
@@ -447,12 +591,23 @@
|
||||
to_chat(user, "<span class='warning'>ERROR: Belly Preferences were not 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)
|
||||
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 FALSE
|
||||
user.vore_taste = new_flavor
|
||||
else //Returned null
|
||||
return FALSE
|
||||
|
||||
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 1
|
||||
return
|
||||
if("Allow Digestion")
|
||||
user.digestable = TRUE
|
||||
if("Prevent Digestion")
|
||||
@@ -465,7 +620,7 @@
|
||||
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 1
|
||||
return
|
||||
if("Allow Devourment")
|
||||
user.devourable = TRUE
|
||||
if("Prevent Devourment")
|
||||
@@ -475,4 +630,4 @@
|
||||
user.client.prefs_vr.devourable = user.devourable
|
||||
|
||||
//Refresh when interacted with, returning 1 makes vore_look.Topic update
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
Reference in New Issue
Block a user