Cleanup vore code

This commit is contained in:
ShadowLarkens
2020-03-19 21:17:24 -07:00
parent b009a606c1
commit d5d5385b76
21 changed files with 723 additions and 1043 deletions

View File

@@ -15,9 +15,7 @@
var/content = ""
var/title_buttons = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
user = nuser
window_id = nwindow_id
if (ntitle)
@@ -33,6 +31,14 @@
return
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
//VOREStation Edit - Allow browser datums to be garbage collected
/datum/browser/Destroy()
close()
ref = null
user = null
. = ..()
//VOREStation Edit End - Allow browser datums to be garbage collected
/datum/browser/proc/set_title(ntitle)
title = format_text(ntitle)

View File

@@ -57,7 +57,6 @@
for(var/organ in organs)
qdel(organ)
QDEL_NULL(nif) //VOREStation Add
QDEL_LIST_NULL(vore_organs) //VOREStation Add
return ..()
/mob/living/carbon/human/Stat()

View File

@@ -32,6 +32,8 @@
if(buckled)
buckled.unbuckle_mob(src, TRUE)
qdel(selected_image)
QDEL_NULL(vorePanel) //VOREStation Add
QDEL_LIST_NULL(vore_organs) //VOREStation Add
return ..()
//mob verbs are faster than object verbs. See mob/verb/examine.

View File

@@ -121,7 +121,7 @@
/mob/living/simple_mob/vore/aggressive/corrupthound/space/Process_Spacemove(var/check_drift = 0)
return TRUE
/mob/living/simple_mob/vore/hostile/corrupthound/init_vore()
/mob/living/simple_mob/vore/aggressive/corrupthound/init_vore()
..()
var/obj/belly/B = vore_selected
B.name = "fuel processor"
@@ -143,7 +143,7 @@
"The longer you spend stewing away in the pool of hot, clingy juices surrounding you, the weaker and weaker you seem to feel!",
"'FU3L mE A1RE@Dy, S0 sO SORrY!?', your corrupted captor growls as its synthetic innards begin oozing more potent juices, grinding down into your body with increasing fervor!")
/mob/living/simple_mob/vore/hostile/corrupthound/prettyboi/init_vore()
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi/init_vore()
..()
var/obj/belly/B = vore_selected
B.name = "fuel processor"

View File

@@ -59,7 +59,6 @@
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
var/tmp/list/hearing_mobs
// Don't forget to watch your commas at the end of each line if you change these.
var/list/struggle_messages_outside = list(
@@ -177,7 +176,7 @@
. = ..()
// Called whenever an atom enters this belly
/obj/belly/Entered(var/atom/movable/thing,var/atom/OldLoc)
/obj/belly/Entered(atom/movable/thing, atom/OldLoc)
if(OldLoc in contents)
return //Someone dropping something (or being stripdigested)
@@ -207,8 +206,7 @@
// 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/silent = FALSE)
/obj/belly/proc/release_all_contents(include_absorbed = FALSE, silent = FALSE)
//Don't bother if we don't have contents
if(!contents.len)
return FALSE
@@ -246,7 +244,7 @@
// 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, var/silent = FALSE)
/obj/belly/proc/release_specific_contents(atom/movable/M, silent = FALSE)
if (!(M in contents))
return 0 // They weren't in this belly anyway
@@ -294,10 +292,10 @@
// 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)
/obj/belly/proc/nom_mob(mob/prey, mob/user)
if(owner.stat == DEAD)
return
if (prey.buckled)
if(prey.buckled)
prey.buckled.unbuckle_mob()
prey.forceMove(src)
@@ -316,9 +314,9 @@
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))
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.size_multiplier
@@ -330,10 +328,10 @@
// 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")
/obj/belly/proc/get_messages(type, 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
@@ -346,13 +344,13 @@
if("em")
raw_messages = examine_messages
var/messages = list2text(raw_messages,delim)
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")
/obj/belly/proc/set_messages(raw_text, type, delim = "\n\n")
ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
var/list/raw_list = text2list(html_encode(raw_text),delim)
@@ -389,8 +387,8 @@
// 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)
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"])")
/obj/belly/proc/digestion_death(mob/living/M)
message_admins("[key_name(owner)] has digested [key_name(M)] in their [lowertext(name)] ([owner ? ADMIN_JMP(owner) : "null"])")
// If digested prey is also a pred... anyone inside their bellies gets moved up.
if(is_vore_predator(M))
@@ -399,7 +397,7 @@
//Drop all items into the belly.
if(config.items_survive_digestion)
for(var/obj/item/W in M)
if(istype(W,/obj/item/organ/internal/mmi_holder/posibrain))
if(istype(W, /obj/item/organ/internal/mmi_holder/posibrain))
var/obj/item/organ/internal/mmi_holder/MMI = W
var/atom/movable/brain = MMI.removed()
if(brain)
@@ -410,7 +408,7 @@
var/obj/item/I = M.get_equipped_item(slot = slot)
if(I)
M.unEquip(I,force = TRUE)
if(contaminates || istype(I,/obj/item/weapon/card/id))
if(contaminates || istype(I, /obj/item/weapon/card/id))
I.gurgle_contaminate(contents, contamination_flavor, contamination_color) //We do an initial contamination pass to get stuff like IDs wet.
if(item_digest_mode == IM_HOLD)
items_preserved |= I
@@ -435,10 +433,10 @@
qdel(M)
// Handle a mob being absorbed
/obj/belly/proc/absorb_living(var/mob/living/M)
/obj/belly/proc/absorb_living(mob/living/M)
M.absorbed = 1
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>")
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>")
if(M.noisy) //Mute drained absorbee hunger if enabled.
M.noisy = FALSE
@@ -473,7 +471,7 @@
//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)
/obj/belly/proc/digest_item(obj/item/item)
var/digested = item.digest_act(src, owner)
if(!digested)
items_preserved |= item
@@ -482,6 +480,7 @@
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += (50 * digested)
return digested
//Determine where items should fall out of us into.
//Typically just to the owner's location.
@@ -499,20 +498,20 @@
/obj/belly/AllowDrop()
return TRUE
/obj/belly/onDropInto(var/atom/movable/AM)
/obj/belly/onDropInto(atom/movable/AM)
return null
//Handle a mob struggling
// Called from /mob/living/carbon/relaymove()
/obj/belly/proc/relay_resist(var/mob/living/R)
/obj/belly/proc/relay_resist(mob/living/R)
if (!(R in contents))
return // User is not in this belly
R.setClickCooldown(50)
if(owner.stat) //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 [escapetime/10] seconds.)</span>")
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
to_chat(R, "<span class='warning'>You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)</span>")
to_chat(owner, "<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
if(do_after(R, escapetime, owner, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
if((owner.stat || escapable) && (R.loc == src)) //Can still escape?
@@ -528,20 +527,20 @@
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_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_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>"
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 hearers(4, owner))
M.show_message(struggle_outer_message, 2) // hearable
to_chat(R,struggle_user_message)
to_chat(R, struggle_user_message)
var/sound/struggle_snuggle
var/sound/struggle_rustle = sound(get_sfx("rustle"))
@@ -557,8 +556,8 @@
if(escapable) //If the stomach has escapable enabled.
if(prob(escapechance)) //Let's have it check to see if the prey escapes first.
to_chat(R,"<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>")
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))
if((escapable) && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled?
release_specific_contents(R)
@@ -588,26 +587,26 @@
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>")
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>")
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_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>")
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_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>")
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
/obj/belly/proc/get_mobs_and_objs_in_belly()
@@ -624,7 +623,7 @@
return see
//Transfers contents from one belly to another
/obj/belly/proc/transfer_contents(var/atom/movable/content, var/obj/belly/target, silent = 0)
/obj/belly/proc/transfer_contents(atom/movable/content, obj/belly/target, silent = 0)
if(!(content in src) || !istype(target))
return
content.forceMove(target)
@@ -636,16 +635,6 @@
I.decontaminate()
I.gurgle_contaminate(target.contents, target.contamination_flavor, target.contamination_color)
items_preserved -= content
/* Disabling this part due to redundancy. Entered() on target belly will make the sound anyway.
if(!silent && target.vore_sound && !recent_sound)
var/soundfile
if(!target.fancy_vore)
soundfile = classic_vore_sounds[target.vore_sound]
else
soundfile = fancy_vore_sounds[target.vore_sound]
if(soundfile)
playsound(src, soundfile, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/client_preference/digestion_noises)
*/
owner.updateVRPanel()
for(var/mob/living/M in contents)
M.updateVRPanel()

View File

@@ -1,4 +1,4 @@
/obj/belly/proc/process_tf(var/mode,var/list/touchable_mobs) //We pass mode so it's mega-ultra local.
/obj/belly/proc/process_tf(mode, list/touchable_mobs) //We pass mode so it's mega-ultra local.
/* May not be necessary... Transform only shows up in the panel for humans.
if(!ishuman(owner))
return //Need DNA and junk for this.
@@ -7,231 +7,86 @@
//Cast here for reduced duplication
var/mob/living/carbon/human/O = owner
///////////////////////////// DM_TRANSFORM_HAIR_AND_EYES /////////////////////////////
if(mode == DM_TRANSFORM_HAIR_AND_EYES)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
var/stabilize_nutrition = FALSE
var/changes_eyes = FALSE
var/changes_hair_solo = FALSE
var/changes_hairandskin = FALSE
var/changes_gender = FALSE
var/changes_gender_to = null
var/changes_species = FALSE
var/changes_ears_tail_wing_nocolor = FALSE
var/changes_ears_tail_wing_color = FALSE
var/eggs = FALSE
if(O.nutrition > 400 && P.nutrition < 400)
switch(mode)
if(DM_TRANSFORM_HAIR_AND_EYES)
stabilize_nutrition = TRUE
changes_eyes = TRUE
changes_hair_solo = TRUE
if(DM_TRANSFORM_MALE, DM_TRANSFORM_FEMALE, DM_TRANSFORM_MALE_EGG, DM_TRANSFORM_FEMALE_EGG)
changes_eyes = TRUE
changes_hairandskin = TRUE
changes_gender = TRUE
changes_gender_to = (mode == DM_TRANSFORM_MALE || mode == DM_TRANSFORM_MALE_EGG) ? MALE : FEMALE
stabilize_nutrition = TRUE
eggs = (mode == DM_TRANSFORM_MALE_EGG || mode == DM_TRANSFORM_FEMALE_EGG)
if(DM_TRANSFORM_KEEP_GENDER, DM_TRANSFORM_KEEP_GENDER_EGG)
changes_eyes = TRUE
changes_hairandskin = TRUE
stabilize_nutrition = TRUE
eggs = (mode == DM_TRANSFORM_KEEP_GENDER_EGG)
if(DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR, DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
changes_species = TRUE
changes_ears_tail_wing_nocolor = TRUE
stabilize_nutrition = TRUE
eggs = (mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
if(DM_TRANSFORM_REPLICA, DM_TRANSFORM_REPLICA_EGG)
changes_eyes = TRUE
changes_hairandskin = TRUE
changes_species = TRUE
changes_ears_tail_wing_color = TRUE
eggs = (mode == DM_TRANSFORM_REPLICA_EGG)
if(DM_EGG)
eggs = TRUE
/* This is designed to do *gradual* transformations.
* For each human in the TF belly per cycle, they can only have one "stage" of transformation applied to them.
* Some transformation modes have different amounts of stages than others and that's okay.
* All stages in order: Eyes, Hair & Skin, Ears & Tail & Wings & Species, Gender, Egg
*/
for(var/mob/living/carbon/human/H in touchable_mobs)
if(H.stat == DEAD)
continue
if(stabilize_nutrition)
if(O.nutrition > 400 && H.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_eyes(P) || check_hair(P))
change_eyes(P)
change_hair(P,1)
///////////////////////////// DM_TRANSFORM_MALE /////////////////////////////
else if(mode == DM_TRANSFORM_MALE)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
H.nutrition += 1.5
if(changes_eyes && check_eyes(H))
change_eyes(H, 1)
continue
if(changes_hair_solo && check_hair(H))
change_hair(H)
continue
if(changes_hairandskin && (check_hair(H) || check_skin(H)))
change_hair(H)
change_skin(H, 1)
continue
if(changes_species)
if(changes_ears_tail_wing_nocolor && (check_ears(H) || check_tail_nocolor(H) || check_wing_nocolor(H) || check_species(H)))
change_ears(H)
change_tail_nocolor(H)
change_wing_nocolor(H)
change_species(H, 1, 1) // ,1) preserves coloring
continue
if(O.nutrition > 400 && P.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_eyes(P))
change_eyes(P,1)
if(changes_ears_tail_wing_color && (check_ears(H) || check_tail(H) || check_wing(H) || check_species(H)))
change_ears(H)
change_tail(H)
change_wing(H)
change_species(H, 1, 2) // ,2) does not preserve coloring.
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_gender(P,MALE))
change_gender(P,MALE,1)
///////////////////////////// DM_TRANSFORM_FEMALE /////////////////////////////
else if(mode == DM_TRANSFORM_FEMALE)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(O.nutrition > 400 && P.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_gender(P,FEMALE))
change_gender(P,FEMALE,1)
///////////////////////////// DM_TRANSFORM_KEEP_GENDER /////////////////////////////
else if(mode == DM_TRANSFORM_KEEP_GENDER)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(O.nutrition > 400 && P.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR /////////////////////////////
else if(mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(O.nutrition > 400 && P.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_ears(P) || check_tail_nocolor(P) || check_wing_nocolor(P) || check_species(P))
change_ears(P)
change_tail_nocolor(P)
change_wing_nocolor(P)
change_species(P,1,1)
///////////////////////////// DM_TRANSFORM_REPLICA /////////////////////////////
else if(mode == DM_TRANSFORM_REPLICA)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(O.nutrition > 400 && P.nutrition < 400)
O.nutrition -= 2
P.nutrition += 1.5
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_ears(P) || check_tail(P) || check_wing(P) || check_species(P))
change_ears(P)
change_tail(P)
change_wing(P)
change_species(P,1,2)
///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG /////////////////////////////
else if(mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(check_ears(P) || check_tail_nocolor(P) || check_wing_nocolor(P)|| check_species(P))
change_ears(P)
change_tail_nocolor(P)
change_wing_nocolor(P)
change_species(P,1,1)
continue
if(!P.absorbed)
put_in_egg(P,1)
///////////////////////////// DM_TRANSFORM_KEEP_GENDER_EGG /////////////////////////////
else if(mode == DM_TRANSFORM_KEEP_GENDER_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(!P.absorbed)
put_in_egg(P,1)
///////////////////////////// DM_TRANSFORM_REPLICA_EGG /////////////////////////////
else if(mode == DM_TRANSFORM_REPLICA_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_ears(P) || check_tail(P) || check_wing(P) || check_species(P))
change_ears(P)
change_tail(P)
change_wing(P)
change_species(P,1,2)
continue
if(!P.absorbed)
put_in_egg(P,1)
///////////////////////////// DM_TRANSFORM_MALE_EGG /////////////////////////////
else if(mode == DM_TRANSFORM_MALE_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_gender(P,MALE))
change_gender(P,MALE,1)
continue
if(!P.absorbed)
put_in_egg(P,1)
///////////////////////////// DM_TRANSFORM_FEMALE_EGG /////////////////////////////
else if(mode == DM_TRANSFORM_FEMALE_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.stat == DEAD)
continue
if(check_eyes(P))
change_eyes(P,1)
continue
if(check_hair(P) || check_skin(P))
change_hair(P)
change_skin(P,1)
continue
if(check_gender(P,MALE))
change_gender(P,MALE,1)
continue
if(!P.absorbed)
put_in_egg(P,1)
///////////////////////////// DM_EGG /////////////////////////////
else if(mode == DM_EGG)
for (var/mob/living/carbon/human/P in touchable_mobs)
if(P.absorbed || P.stat == DEAD)
continue
put_in_egg(P,1)
if(changes_gender && check_gender(H, changes_gender_to))
change_gender(H, changes_gender_to, 1)
continue
if(eggs && (!H.absorbed))
put_in_egg(H, 1)
continue

View File

@@ -1,5 +1,5 @@
// 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
/obj/belly/proc/process_belly(times_fired, wait) //Passed by controller
if((times_fired < next_process) || !contents.len)
recent_sound = FALSE
return SSBELLIES_IGNORED
@@ -11,31 +11,13 @@
qdel(src)
return SSBELLIES_PROCESSED
next_process = times_fired + (6 SECONDS/wait) //Set up our next process time.
next_process = times_fired + (6 SECONDS / wait) //Set up our next process time.
var/play_sound //Potential sound to play at the end to avoid code duplication.
var/to_update = FALSE //Did anything update worthy happen?
/////////////////////////// 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]
if(LAZYLEN(EL))
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>")
///////////////////// Prey Loop Refresh/hack //////////////////////
for(var/mob/living/M in contents)
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
if(isbelly(M.loc)) //sanity check
if(world.time > M.next_preyloop) //We don't want it to overlap, but we also want it to replay.
if(is_wet && wet_loop) // Is it a fleshy environment, and does the pred have a fleshy heartbeat loop to play?
if(!M.client)
continue
if(M.is_preference_enabled(/datum/client_preference/digestion_noises)) //then we check if the mob has sounds enabled at all
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
M.playsound_local(get_turf(src),preyloop, 80,0, channel = CHANNEL_PREYLOOP)
M.next_preyloop = (world.time + (52 SECONDS))
prey_loop()
/////////////////////////// Sound Selections ///////////////////////////
var/sound/prey_digest
@@ -61,31 +43,30 @@
var/list/touchable_mobs = list()
///////////////////// Early Non-Mode Handling /////////////////////
var/did_an_item = FALSE
if(contents.len && next_emote <= times_fired)
next_emote = times_fired + round(emote_time/wait,1)
var/list/EL = emote_lists[digest_mode]
if(LAZYLEN(EL))
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>")
var/did_an_item = FALSE // Only do one item per cycle.
var/digestion_noise_chance = 0
for(var/A in touchable_atoms)
//Handle stray items
if(isitem(A) && !did_an_item)
var/obj/item/I = A
if(contaminates || istype(I,/obj/item/weapon/card/id))
I.gurgle_contaminate(src, contamination_flavor, contamination_color)
if(item_digest_mode == IM_HOLD)
items_preserved |= I
else if(item_digest_mode == IM_DIGEST_FOOD)
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I,/obj/item/organ))
digest_item(I)
else
items_preserved |= I
if(prob(25)) //Less often than with normal digestion
play_sound = pick(pred_digest)
else if(item_digest_mode == IM_DIGEST)
if(I.digest_stage && I.digest_stage > 0)
digest_item(I)
else
digest_item(I)
did_an_item = TRUE
did_an_item = handle_digesting_item(A)
if(did_an_item)
to_update = TRUE
if(prob(25)) //Less often than with normal digestion
play_sound = pick(pred_digest)
//Less often than with normal digestion
if((item_digest_mode == IM_DIGEST_FOOD || item_digest_mode == IM_DIGEST) && prob(25))
// This is a little weird, but the point of it is that we don't want to repeat code
// but we also want the prob(25) chance to run for -every- item we look at, not just once
// More gurgles the better~
digestion_noise_chance = 25
//Handle eaten mobs
else if(isliving(A))
@@ -105,278 +86,218 @@
H.bloodstr.add_reagent("numbenzyme",4)
//Thickbelly flag
if(mode_flags & DM_FLAG_THICKBELLY)
if(!(H.muffled))
H.muffled = 1
if((mode_flags & DM_FLAG_THICKBELLY) && !H.muffled)
H.muffled = TRUE
//Stripping flag
if(mode_flags & DM_FLAG_STRIPPING)
for(var/slot in slots)
var/obj/item/I = H.get_equipped_item(slot = slot)
if(I)
H.unEquip(I,force = FALSE)
if(contaminates || istype(I,/obj/item/weapon/card/id))
I.gurgle_contaminate(contents, contamination_flavor, contamination_color)
if(item_digest_mode == IM_HOLD)
items_preserved |= I
else if(item_digest_mode == IM_DIGEST_FOOD)
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I,/obj/item/organ))
digest_item(I)
else
items_preserved |= I
if(prob(25)) //Less often than with normal digestion
if(L && L.client && L.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(L,prey_digest)
play_sound = pick(pred_digest)
else if(item_digest_mode == IM_DIGEST)
digest_item(I)
if(prob(25)) //Less often than with normal digestion
if(L && L.client && L.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(L,prey_digest)
play_sound = pick(pred_digest)
if(I && H.unEquip(I, force = FALSE))
handle_digesting_item(I)
digestion_noise_chance = 25
to_update = TRUE
break
break // Digest off one by one, not all at once
//get rid of things like blood drops and gibs that end up in there
else if(istype(A,/obj/effect/decal/cleanable/))
else if(istype(A, /obj/effect/decal/cleanable))
qdel(A)
///////////////////////////// DM_HOLD /////////////////////////////
if(digest_mode == DM_HOLD)
return SSBELLIES_PROCESSED //Pretty boring, huh
//We deliberately do not want any gurgly noises if the belly is in DM_HOLD
if(to_update)
updateVRPanels()
return SSBELLIES_PROCESSED
//////////////////////////// DM_DIGEST ////////////////////////////
else if(digest_mode == DM_DIGEST)
if(prob(50)) //Was SO OFTEN. AAAA.
for(var/mob/M in contents)
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
for (var/target in touchable_mobs)
var/mob/living/M = target
//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)
var/compensation = M.getOxyLoss() //How much of the prey's damage was caused by passive crit oxyloss to compensate the lost nutrition.
//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='notice'>" + digest_alert_owner + "</span>")
to_chat(M,"<span class='notice'>" + digest_alert_prey + "</span>")
play_sound = pick(pred_death)
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_death)
if((mode_flags & DM_FLAG_LEAVEREMAINS) && M.digest_leave_remains)
handle_remains_leaving(M)
digestion_death(M)
if(!ishuman(owner))
owner.update_icons()
if(compensation == 0) //Slightly sloppy way at making sure certain mobs don't give ZERO nutrition (fish and so on)
compensation = 21 //This reads as 20*4.5 due to the calculations afterward, making the backup nutrition value 94.5 per mob. Not op compared to regular prey.
if(compensation > 0)
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += 25*compensation
else
owner.nutrition += (nutrition_percent / 100)*4.5*compensation
to_update = TRUE
continue
// Deal digestion damage (and feed the pred)
var/old_brute = M.getBruteLoss()
var/old_burn = M.getFireLoss()
M.adjustBruteLoss(digest_brute)
M.adjustFireLoss(digest_burn)
var/actual_brute = M.getBruteLoss() - old_brute
var/actual_burn = M.getFireLoss() - old_burn
var/damage_gain = actual_brute + actual_burn
var/offset = (1 + ((M.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02
var/difference = owner.size_multiplier / M.size_multiplier
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += 25*damage_gain
if(offset) // If any different than default weight, multiply the % of offset.
owner.nutrition += offset*((nutrition_percent / 100)*4.5*(damage_gain)/difference) //4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
else
owner.nutrition += (nutrition_percent / 100)*4.5*(damage_gain)/difference
//////////////////////////// DM_ABSORB ////////////////////////////
else if(digest_mode == DM_ABSORB)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(M.absorbable == FALSE)
return
else
if(prob(10)) //Less often than gurgles. People might leave this on forever.
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
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)
to_update = TRUE
//////////////////////////// DM_UNABSORB ////////////////////////////
else if(digest_mode == DM_UNABSORB)
for (var/target in touchable_mobs)
var/mob/living/M = target
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
to_update = TRUE
//////////////////////////// DM_DRAIN ////////////////////////////
else if(digest_mode == DM_DRAIN)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(prob(10)) //Less often than gurgles. People might leave this on forever.
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
if(M.nutrition >= 100) //Drain them until there's no nutrients left.
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
owner.nutrition += oldnutrition
//////////////////////////// DM_SHRINK ////////////////////////////
else if(digest_mode == DM_SHRINK)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(prob(10)) //Infinite gurgles!
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
if(M.size_multiplier > shrink_grow_size) //Shrink until smol.
M.resize(M.size_multiplier-0.01) //Shrink by 1% per tick.
if(M.nutrition >= 100) //Absorbing bodymass results in nutrition if possible.
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
owner.nutrition += oldnutrition
//////////////////////////// DM_GROW ////////////////////////////
else if(digest_mode == DM_GROW)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(prob(10))
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
if(M.size_multiplier < shrink_grow_size) //Grow until large.
M.resize(M.size_multiplier+0.01) //Grow by 1% per tick.
if(M.nutrition >= 100)
owner.nutrition = (owner.nutrition * 0.95)
//////////////////////////// DM_SIZE_STEAL ////////////////////////////
else if(digest_mode == DM_SIZE_STEAL)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(prob(10))
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
if(M.size_multiplier > shrink_grow_size && owner.size_multiplier < 2) //Grow until either pred is large or prey is small.
owner.resize(owner.size_multiplier+0.01) //Grow by 1% per tick.
M.resize(M.size_multiplier-0.01) //Shrink by 1% per tick
if(M.nutrition >= 100)
var/oldnutrition = (M.nutrition * 0.05)
M.nutrition = (M.nutrition * 0.95)
owner.nutrition += oldnutrition
///////////////////////////// DM_HEAL /////////////////////////////
else if(digest_mode == DM_HEAL)
if(prob(50)) //Wet heals! The secret is you can leave this on for gurgle noises for fun.
for(var/mob/M in contents)
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M,prey_digest)
play_sound = pick(pred_digest)
for (var/target in touchable_mobs)
var/mob/living/M = target
if(M.stat == DEAD)
continue
if(owner.nutrition > 90 && (M.health < M.maxHealth))
M.adjustBruteLoss(-2.5)
M.adjustFireLoss(-2.5)
M.adjustToxLoss(-5)
M.adjustOxyLoss(-5)
M.adjustCloneLoss(-1.25)
owner.nutrition -= 2
if(M.nutrition <= 400)
M.nutrition += 1
else if(owner.nutrition > 90 && (M.nutrition <= 400))
owner.nutrition -= 1
M.nutrition += 1
/////////////////////////// DM_TRANSFORM ///////////////////////////
else if(digest_mode == DM_TRANSFORM)
if(digest_mode == DM_TRANSFORM)
process_tf(tf_mode, touchable_mobs)
for(var/target in touchable_mobs)
var/mob/living/L = target
if(!istype(L))
continue
switch(digest_mode)
if(DM_DIGEST)
digestion_noise_chance = 50
//Pref protection!
if(!L.digestable || L.absorbed)
continue
//Person just died in guts!
if(L.stat == DEAD)
play_sound = pred_death
if(L.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(L, prey_death)
handle_digestion_death(L)
to_update = TRUE
continue
// Deal digestion damage (and feed the pred)
var/old_brute = L.getBruteLoss()
var/old_burn = L.getFireLoss()
L.adjustBruteLoss(digest_brute)
L.adjustFireLoss(digest_burn)
var/actual_brute = L.getBruteLoss() - old_brute
var/actual_burn = L.getFireLoss() - old_burn
var/damage_gain = actual_brute + actual_burn
var/offset = (1 + ((L.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02
var/difference = owner.size_multiplier / L.size_multiplier
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += 25 * damage_gain
if(offset) // If any different than default weight, multiply the % of offset.
owner.nutrition += offset*((nutrition_percent / 100) * 4.5 * (damage_gain) / difference) //4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
else
owner.nutrition += (nutrition_percent / 100) * 4.5 * (damage_gain) / difference
if(DM_ABSORB)
if(!L.absorbable || L.absorbed)
continue
digestion_noise_chance = 10
steal_nutrition(L)
if(L.nutrition < 100)
absorb_living(L)
to_update = TRUE
if(DM_UNABSORB)
if(L.absorbed && owner.nutrition >= 100)
L.absorbed = FALSE
to_chat(L, "<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
to_update = TRUE
if(DM_DRAIN)
digestion_noise_chance = 10
steal_nutrition(L)
if(DM_SHRINK)
digestion_noise_chance = 10
if(L.size_multiplier > shrink_grow_size)
L.resize(L.size_multiplier - 0.01) // Shrink by 1% per tick
steal_nutrition(L)
if(DM_GROW)
digestion_noise_chance = 10
if(L.size_multiplier < shrink_grow_size)
L.resize(L.size_multiplier - 0.01) // Grow by 1% per tick
if(DM_SIZE_STEAL)
digestion_noise_chance = 10
if(L.size_multiplier > shrink_grow_size && owner.size_multiplier < 2) //Grow until either pred is large or prey is small.
owner.resize(owner.size_multiplier+0.01) //Grow by 1% per tick.
L.resize(L.size_multiplier-0.01) //Shrink by 1% per tick
steal_nutrition(L)
if(DM_HEAL)
digestion_noise_chance = 50 //Wet heals! The secret is you can leave this on for gurgle noises for fun.
if(L.stat == DEAD)
continue // Can't heal the dead with healbelly
if(owner.nutrition > 90 && (L.health < L.maxHealth))
L.adjustBruteLoss(-2.5)
L.adjustFireLoss(-2.5)
L.adjustToxLoss(-5)
L.adjustOxyLoss(-5)
L.adjustCloneLoss(-1.25)
owner.nutrition -= 2
if(L.nutrition <= 400)
L.nutrition += 1
else if(owner.nutrition > 90 && (L.nutrition <= 400))
owner.nutrition -= 1
L.nutrition += 1
/////////////////////////// Make any noise ///////////////////////////
if(digestion_noise_chance && prob(digestion_noise_chance))
for(var/mob/M in contents)
if(M && M.is_preference_enabled(/datum/client_preference/digestion_noises))
SEND_SOUND(M, prey_digest)
play_sound = pred_digest
if(play_sound)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/M in hearers(VORE_SOUND_RANGE, owner))
if(!M.client || !(M.is_preference_enabled(/datum/client_preference/digestion_noises)))
for(var/mob/M in hearers(VORE_SOUND_RANGE, owner)) //so we don't fill the whole room with the sound effect
if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
continue
LAZYADD(hearing_mobs, M)
for(var/mob/M in hearing_mobs) //so we don't fill the whole room with the sound effect
if(M && M.client && (isturf(M.loc) || (M.loc != src.contents))) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
if(isturf(M.loc) || (M.loc != src)) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
if(fancy_vore)
M.playsound_local(owner.loc, play_sound, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else
M.playsound_local(owner.loc, play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
//these are all external sound triggers now, so it's ok.
if(to_update)
for(var/mob/living/M in contents)
if(M.client)
M.updateVRPanel()
if(owner.client)
owner.updateVRPanel()
updateVRPanels()
return SSBELLIES_PROCESSED
/obj/belly/proc/prey_loop()
for(var/mob/living/M in contents)
//We don't bother executing any other code if the prey doesn't want to hear the noises.
if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
continue
// We don't want the sounds to overlap, but we do want them to steadily replay.
// We also don't want the sounds to play if the pred hasn't marked this belly as fleshy, or doesn't
// have the right sounds to play.
if(isbelly(M.loc) && is_wet && wet_loop && (world.time > M.next_preyloop))
M.stop_sound_channel(CHANNEL_PREYLOOP)
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
M.playsound_local(get_turf(src), preyloop, 80, 0, channel = CHANNEL_PREYLOOP)
M.next_preyloop = (world.time + (52 SECONDS))
/obj/belly/proc/handle_digesting_item(obj/item/I)
var/did_an_item = FALSE
// We always contaminate IDs.
if(contaminates || istype(I, /obj/item/weapon/card/id))
I.gurgle_contaminate(src, contamination_flavor, contamination_color)
switch(item_digest_mode)
if(IM_HOLD)
items_preserved |= I
if(IM_DIGEST_FOOD)
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I, /obj/item/organ))
did_an_item = digest_item(I)
else
items_preserved |= I
if(IM_DIGEST)
did_an_item = digest_item(I)
return did_an_item
/obj/belly/proc/handle_digestion_death(mob/living/M)
var/digest_alert_owner = pick(digest_messages_owner)
var/digest_alert_prey = pick(digest_messages_prey)
var/compensation = M.getOxyLoss() //How much of the prey's damage was caused by passive crit oxyloss to compensate the lost nutrition.
//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='notice'>[digest_alert_owner]</span>")
to_chat(M, "<span class='notice'>[digest_alert_prey]</span>")
if((mode_flags & DM_FLAG_LEAVEREMAINS) && M.digest_leave_remains)
handle_remains_leaving(M)
digestion_death(M)
if(!ishuman(owner))
owner.update_icons()
if(compensation == 0) //Slightly sloppy way at making sure certain mobs don't give ZERO nutrition (fish and so on)
compensation = 21 //This reads as 20*4.5 due to the calculations afterward, making the backup nutrition value 94.5 per mob. Not op compared to regular prey.
if(compensation > 0)
if(isrobot(owner))
var/mob/living/silicon/robot/R = owner
R.cell.charge += 25*compensation
else
owner.nutrition += (nutrition_percent / 100)*4.5*compensation
/obj/belly/proc/steal_nutrition(mob/living/L)
if(L.nutrition >= 100)
var/oldnutrition = (L.nutrition * 0.05)
L.nutrition = (L.nutrition * 0.95)
owner.nutrition += oldnutrition
/obj/belly/proc/updateVRPanels()
for(var/mob/living/M in contents)
if(M.client)
M.updateVRPanel()
if(owner.client)
owner.updateVRPanel()

View File

@@ -22,7 +22,7 @@ var/list/gurgled_overlays = list(
var/cleandesc
var/gurgled_color
/obj/item/proc/gurgle_contaminate(var/atom/movable/item_storage = null, var/contamination_flavor = "Generic", var/contamination_color = "green")
/obj/item/proc/gurgle_contaminate(atom/movable/item_storage = null, contamination_flavor = "Generic", contamination_color = "green")
if(!can_gurgle())
return FALSE
@@ -65,28 +65,16 @@ var/list/gurgled_overlays = list(
if(gurgled)
decontaminate()
/obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob) //Wash the soggy item before it can interact with the sink.
if(O.gurgled)
var/turf/location = user.loc
if(!isturf(location)) return
var/obj/item/I = O
if(!I || !istype(I,/obj/item)) return
to_chat(usr, "<span class='notice'>You start washing \the [I].</span>")
/obj/structure/sink/attackby(obj/item/I, mob/user) //Wash the soggy item before it can interact with the sink.
if(istype(I) && I.gurgled)
to_chat(user, "<span class='notice'>You start washing [I].</span>")
busy = TRUE
sleep(40)
if(do_after(user, 40, src))
I.clean_blood()
user.visible_message("<span class='notice'>[user] washes [I] using [src].</span>",
"<span class='notice'>You wash [I] using [src].</span>")
busy = FALSE
if(user.loc != location) return //User has moved
if(!I) return //Item's been destroyed while washing
if(user.get_active_hand() != I) return //Person has switched hands or the item in their hands
O.clean_blood()
user.visible_message( \
"<span class='notice'>[user] washes \a [I] using \the [src].</span>", \
"<span class='notice'>You wash \a [I] using \the [src].</span>")
else
..()

View File

@@ -3,10 +3,10 @@
//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)
if(istype(item_storage,/obj/item/device/dogborg/sleeper))
/obj/item/proc/digest_act(atom/movable/item_storage = null)
if(istype(item_storage, /obj/item/device/dogborg/sleeper))
for(var/obj/item/O in contents)
if(istype(O,/obj/item/weapon/storage/internal)) //Dump contents from dummy pockets.
if(istype(O, /obj/item/weapon/storage/internal)) //Dump contents from dummy pockets.
for(var/obj/item/SO in O)
if(item_storage)
SO.forceMove(item_storage)
@@ -15,12 +15,15 @@
O.forceMove(item_storage)
qdel(src)
return w_class
var/g_damage = 1
if(digest_stage == null)
digest_stage = w_class
if(isbelly(item_storage))
var/obj/belly/B = item_storage
g_damage = 0.25 * (B.digest_brute + B.digest_burn)
if(digest_stage > 0)
if(g_damage > digest_stage)
g_damage = digest_stage
@@ -65,16 +68,16 @@
// 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)
/obj/item/device/pda/digest_act(atom/movable/item_storage = null)
if(id)
if(istype(item_storage,/obj/item/device/dogborg/sleeper) || (!isnull(digest_stage) && digest_stage <= 0))
if(istype(item_storage, /obj/item/device/dogborg/sleeper) || (!isnull(digest_stage) && digest_stage <= 0))
id = null
. = ..()
/obj/item/weapon/card/id
var/lost_access = list()
/obj/item/weapon/card/id/digest_act(var/atom/movable/item_storage = null)
/obj/item/weapon/card/id/digest_act(atom/movable/item_storage = null)
desc = "A partially digested card that has seen better days. The damage appears to be only cosmetic, but the access codes need to be reprogrammed at the HoP office."
icon = 'icons/obj/card_vr.dmi'
icon_state = "[initial(icon_state)]_digested"
@@ -83,7 +86,7 @@
access = list() // Then lose it
return FALSE
/obj/item/weapon/reagent_containers/food/digest_act(var/atom/movable/item_storage = null)
/obj/item/weapon/reagent_containers/food/digest_act(atom/movable/item_storage = null)
if(isbelly(item_storage))
var/obj/belly/B = item_storage
if(ishuman(B.owner))
@@ -96,7 +99,7 @@
return w_class
. = ..()
/obj/item/weapon/holder/digest_act(var/atom/movable/item_storage = null)
/obj/item/weapon/holder/digest_act(atom/movable/item_storage = null)
for(var/mob/living/M in contents)
if(item_storage)
M.forceMove(item_storage)
@@ -104,7 +107,7 @@
. = ..()
/obj/item/organ/digest_act(var/atom/movable/item_storage = null)
/obj/item/organ/digest_act(atom/movable/item_storage = null)
if((. = ..()))
if(isbelly(item_storage))
var/obj/belly/B = item_storage
@@ -112,7 +115,7 @@
else
. += 30 //Organs give a little more
/obj/item/weapon/storage/digest_act(var/atom/movable/item_storage = null)
/obj/item/weapon/storage/digest_act(atom/movable/item_storage = null)
for(var/obj/item/I in contents)
I.screen_loc = null
@@ -121,7 +124,7 @@
/////////////
// Some more complicated stuff
/////////////
/obj/item/device/mmi/digital/posibrain/digest_act(var/atom/movable/item_storage = null)
/obj/item/device/mmi/digital/posibrain/digest_act(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

View File

@@ -1,72 +1,62 @@
/datum/species
var/skull_type = /obj/item/weapon/digestion_remains/skull
/datum/species/tajaran
skull_type = /obj/item/weapon/digestion_remains/skull/tajaran
/datum/species/unathi
skull_type = /obj/item/weapon/digestion_remains/skull/unathi
/datum/species/skrell
skull_type = /obj/item/weapon/digestion_remains/skull/skrell
/datum/species/spider
skull_type = /obj/item/weapon/digestion_remains/skull/vasilissan
/datum/species/akula
skull_type = /obj/item/weapon/digestion_remains/skull/akula
/datum/species/harpy
skull_type = /obj/item/weapon/digestion_remains/skull/rapala
/datum/species/vulpkanin
skull_type = /obj/item/weapon/digestion_remains/skull/vulpkanin
/datum/species/sergal
skull_type = /obj/item/weapon/digestion_remains/skull/sergal
/datum/species/hi_zorren
skull_type = /obj/item/weapon/digestion_remains/skull/zorren
/datum/species/nevrean
skull_type = /obj/item/weapon/digestion_remains/skull/nevrean
/datum/species/teshari
skull_type = /obj/item/weapon/digestion_remains/skull/teshari
/datum/species/vox
skull_type = /obj/item/weapon/digestion_remains/skull/vox
/obj/belly/proc/handle_remains_leaving(var/mob/living/M)
if(istype(M,/mob/living/carbon/human)) //Are we even humanoid?
var/mob/living/carbon/human/H = M
if((H.species.name in remainless_species) || H.isSynthetic()) //Don't leave anything if there is nothing to leave
return
else
var/bones_amount = rand(2,3) //some random variety in amount of bones left
if(prob(20)) //ribcage surviving whole is some luck
new /obj/item/weapon/digestion_remains/ribcage(src,owner)
bones_amount--
while(bones_amount) //throw in the rest
new /obj/item/weapon/digestion_remains(src,owner)
bones_amount--
var/skull_amount = 1
switch(H.species.name) //oh boy here we go, finding us a right skull
if(SPECIES_HUMAN)
new /obj/item/weapon/digestion_remains/skull(src,owner)
skull_amount--
if(SPECIES_TAJ)
new /obj/item/weapon/digestion_remains/skull/tajaran(src,owner)
skull_amount--
if(SPECIES_UNATHI)
new /obj/item/weapon/digestion_remains/skull/unathi(src,owner)
skull_amount--
if(SPECIES_SKRELL)
new /obj/item/weapon/digestion_remains/skull/skrell(src,owner)
skull_amount--
if(SPECIES_VASILISSAN)
new /obj/item/weapon/digestion_remains/skull/vasilissan(src,owner)
skull_amount--
if(SPECIES_AKULA)
new /obj/item/weapon/digestion_remains/skull/akula(src,owner)
skull_amount--
if(SPECIES_RAPALA)
new /obj/item/weapon/digestion_remains/skull/rapala(src,owner)
skull_amount--
if(SPECIES_VULPKANIN)
new /obj/item/weapon/digestion_remains/skull/vulpkanin(src,owner)
skull_amount--
if(SPECIES_SERGAL)
new /obj/item/weapon/digestion_remains/skull/sergal(src,owner)
skull_amount--
if(SPECIES_ZORREN_HIGH)
new /obj/item/weapon/digestion_remains/skull/zorren(src,owner)
skull_amount--
if(SPECIES_NEVREAN)
new /obj/item/weapon/digestion_remains/skull/nevrean(src,owner)
skull_amount--
if(SPECIES_TESHARI)
new /obj/item/weapon/digestion_remains/skull/teshari(src,owner)
skull_amount--
if(SPECIES_VOX)
new /obj/item/weapon/digestion_remains/skull/vox(src,owner)
skull_amount--
if(skull_amount && H.species.selects_bodytype) //We still haven't found correct skull...
if(H.species.base_species == SPECIES_HUMAN)
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
else
new /obj/item/weapon/digestion_remains/skull/unknown/anthro(src,owner)
else if(skull_amount) //Something entirely different...
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
else
if(!ishuman(M)) //Are we even humanoid?
return
var/mob/living/carbon/human/H = M
if((H.species.name in remainless_species) || H.isSynthetic()) //Don't leave anything if there is nothing to leave
return
var/bones_amount = rand(2,3) //some random variety in amount of bones left
if(prob(20)) //ribcage surviving whole is some luck
new /obj/item/weapon/digestion_remains/ribcage(src,owner)
bones_amount--
while(bones_amount) //throw in the rest
new /obj/item/weapon/digestion_remains(src,owner)
bones_amount--
var/skull_amount = 1
if(H.species.skull_type)
new H.species.skull_type(src, owner)
skull_amount--
if(skull_amount && H.species.selects_bodytype)
// We still haven't found correct skull...
if(H.species.base_species == SPECIES_HUMAN)
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
else
new /obj/item/weapon/digestion_remains/skull/unknown/anthro(src,owner)
else if(skull_amount)
// Something entirely different...
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
/obj/item/weapon/digestion_remains
name = "bone"
@@ -80,7 +70,7 @@
var/pred_ckey
var/pred_name
/obj/item/weapon/digestion_remains/New(var/newloc,var/mob/living/pred)
/obj/item/weapon/digestion_remains/New(newloc, mob/living/pred)
..(newloc)
pred_ckey = pred.ckey
pred_name = pred.name

View File

@@ -19,7 +19,6 @@
var/metabolism = 0.0015
var/vore_taste = null // What the character tastes like
var/no_vore = FALSE // If the character/mob can vore.
var/openpanel = FALSE // Is the vore panel open?
var/noisy = FALSE // Toggle audible hunger.
var/absorbing_prey = 0 // Determines if the person is using the succubus drain or not. See station_special_abilities_vr.
var/drain_finalized = 0 // Determines if the succubus drain will be KO'd/absorbed. Can be toggled on at any time.
@@ -41,6 +40,7 @@
M.verbs += /mob/living/proc/switch_scaling
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 TRUE
M.vorePanel = new
M.verbs += /mob/living/proc/insidePanel
//Tries to load prefs if a client is present otherwise gives freebie stomach
@@ -88,26 +88,25 @@
//
// Handle being clicked, perhaps with something to devour
//
/mob/living/proc/vore_attackby(obj/item/I,mob/user)
/mob/living/proc/vore_attackby(obj/item/I, mob/user)
//Handle case: /obj/item/weapon/grab
if(istype(I,/obj/item/weapon/grab))
if(istype(I, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = I
//Has to be aggressive grab, has to be living click-er and non-silicon grabbed
if((G.state >= GRAB_AGGRESSIVE) && (isliving(user) && !issilicon(G.affecting)))
if(G.state >= GRAB_AGGRESSIVE && (isliving(user) && !issilicon(G.affecting)))
var/mob/living/attacker = user // Typecast to living
// src is the mob clicked on and attempted predator
///// If user clicked on themselves
if((src == G.assailant) && (is_vore_predator(src)))
if(!(G.affecting.devourable))
if(src == G.assailant && is_vore_predator(src))
if(!G.affecting.devourable)
to_chat(user, "<span class='notice'>They aren't able to be devoured.</span>")
log_and_message_admins("[key_name(src)] ([src.real_name]) attempted to devour [key_name(G.affecting)] ([G.affecting.real_name]) against their prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
log_and_message_admins("[key_name_admin(src)] attempted to devour [key_name_admin(G.affecting)] against their prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
return FALSE
if(src.feed_grabbed_to_self(src, G.affecting))
if(feed_grabbed_to_self(src, G.affecting))
qdel(G)
return TRUE
else
@@ -115,57 +114,62 @@
///// If user clicked on their grabbed target
else if((src == G.affecting) && (attacker.a_intent == I_GRAB) && (attacker.zone_sel.selecting == BP_TORSO) && (is_vore_predator(G.affecting)))
if(!(G.affecting.feeding))
if(!G.affecting.feeding)
to_chat(user, "<span class='notice'>[G.affecting] isn't willing to be fed.</span>")
log_and_message_admins("[key_name(src)] ([src.real_name]) attempted to feed themselves to [key_name(G.affecting)] ([G.affecting.real_name]) against their prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
log_and_message_admins("[key_name_admin(src)] attempted to feed themselves to [key_name_admin(G.affecting)] against their prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
return FALSE
if (attacker.feed_self_to_grabbed(attacker, G.affecting))
if(attacker.feed_self_to_grabbed(attacker, G.affecting))
qdel(G)
return TRUE
else
log_debug("[attacker] attempted to feed [user] to [G.affecting] ([G.affecting.type]) but it failed.")
log_debug("[attacker] attempted to feed [user] to [G.affecting] ([G.affecting ? G.affecting.type : "null"]) but it failed.")
///// If user clicked on anyone else but their grabbed target
else if((src != G.affecting) && (src != G.assailant) && (is_vore_predator(src)))
if(!(src.feeding))
if(!feeding)
to_chat(user, "<span class='notice'>[src] isn't willing to be fed.</span>")
log_and_message_admins("[key_name(attacker)] ([attacker.real_name]) attempted to feed [key_name(G.affecting)] ([G.affecting.real_name]) to [key_name(src)] ([src.real_name]) against predator's prefs ([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against predator's prefs ([src ? ADMIN_JMP(src) : "null"])")
return FALSE
if(!(G.affecting.devourable))
to_chat(user, "<span class='notice'>[G.affecting] isn't able to be devoured.</span>")
log_and_message_admins("[key_name(attacker)] ([attacker.real_name]) attempted to feed [key_name(G.affecting)] ([G.affecting.real_name]) to [key_name(src)] ([src.real_name]) against prey's prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against prey's prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
return FALSE
if (attacker.feed_grabbed_to_other(attacker, G.affecting, src))
if(attacker.feed_grabbed_to_other(attacker, G.affecting, src))
qdel(G)
return TRUE
else
log_debug("[attacker] attempted to feed [G.affecting] to [src] ([src.type]) but it failed.")
log_debug("[attacker] attempted to feed [G.affecting] to [src] ([type]) but it failed.")
//Handle case: /obj/item/weapon/holder
else if(istype(I,/obj/item/weapon/holder))
else if(istype(I, /obj/item/weapon/holder))
var/obj/item/weapon/holder/H = I
if(!isliving(user)) return FALSE // return FALSE to continue upper procs
if(!isliving(user))
return FALSE // return FALSE 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)
if (attacker.eat_held_mob(attacker, M, src))
if (H.held_mob == M)
if(is_vore_predator(src))
for(var/mob/living/M in H.contents)
if(attacker.eat_held_mob(attacker, M, src))
if(H.held_mob == M)
H.held_mob = null
return TRUE //return TRUE to exit upper procs
else
log_debug("[attacker] attempted to feed [H.contents] to [src] ([src.type]) but it failed.")
log_debug("[attacker] attempted to feed [H.contents] to [src] ([type]) but it failed.")
//Handle case: /obj/item/device/radio/beacon
else if(istype(I,/obj/item/device/radio/beacon))
var/confirm = alert(user, "[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]", "Confirmation", "Yes!", "Cancel")
var/confirm = alert(user,
"[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]",
"Confirmation",
"Yes!", "Cancel")
if(confirm == "Yes!")
var/obj/belly/B = input("Which belly?","Select A Belly") as null|anything in vore_organs
var/obj/belly/B = input("Which belly?", "Select A Belly") as null|anything in vore_organs
if(!istype(B))
return TRUE
visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [lowertext(B.name)]!</span>","<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [lowertext(B.name)]!</span>",
"<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
if(do_after(user,30,src))
user.drop_item()
I.forceMove(B)
@@ -179,7 +183,6 @@
// Our 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
@@ -187,7 +190,6 @@
return TRUE //resist() on living does this TRUE thing.
//Other overridden resists go here
return FALSE
//
@@ -310,13 +312,12 @@
if(suit.hides_bulges)
return FALSE
return ..()
//
// Clearly super important. Obviously.
//
/mob/living/proc/lick(var/mob/living/tasted in living_mobs(1))
/mob/living/proc/lick(mob/living/tasted in living_mobs(1))
set name = "Lick"
set category = "IC"
set desc = "Lick someone nearby!"
@@ -402,11 +403,11 @@
//
// Eating procs depending on who clicked what
//
/mob/living/proc/feed_grabbed_to_self(var/mob/living/user, var/mob/living/prey)
/mob/living/proc/feed_grabbed_to_self(mob/living/user, mob/living/prey)
var/belly = user.vore_selected
return perform_the_nom(user, prey, user, belly)
/mob/living/proc/eat_held_mob(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
/mob/living/proc/eat_held_mob(mob/living/user, mob/living/prey, mob/living/pred)
var/belly
if(user != pred)
belly = input("Choose Belly") in pred.vore_organs
@@ -414,18 +415,18 @@
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)
/mob/living/proc/feed_self_to_grabbed(mob/living/user, 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)
/mob/living/proc/feed_grabbed_to_other(mob/living/user, mob/living/prey, mob/living/pred)
var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, prey, pred, belly)
//
// Master vore proc that actually does vore procedures
//
/mob/living/proc/perform_the_nom(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/obj/belly/belly, var/delay)
/mob/living/proc/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay)
//Sanity
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs))
log_debug("[user] attempted to feed [prey] to [pred], via [belly ? lowertext(belly.name) : "*null*"] but it went wrong.")
@@ -444,11 +445,11 @@
// Prepare messages
if(user == pred) //Feeding someone to yourself
attempt_msg = text("<span class='warning'>[] is attempting 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))
attempt_msg = "<span class='warning'>[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
success_msg = "<span class='warning'>[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
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))
attempt_msg = "<span class='warning'>[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
success_msg = "<span class='warning'>[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
// Announce that we start the attempt!
user.visible_message(attempt_msg)
@@ -477,10 +478,10 @@
to_chat(belly.owner, "<span class='notice'>[prey] tastes of [prey.get_taste_message(FALSE)].</span>")
// Inform Admins
if (pred == user)
add_attack_logs(pred,prey,"Eaten via [belly.name]")
if(pred == user)
add_attack_logs(pred, prey, "Eaten via [belly.name]")
else
add_attack_logs(user,pred,"Forced to eat [key_name(prey)]")
add_attack_logs(user, pred, "Forced to eat [key_name(prey)]")
return TRUE
//
@@ -522,7 +523,7 @@
to_chat(src,"<font color='red'>You're pinned back underfoot!</font>")
to_chat(H,"<font color='blue'>You pin the escapee back underfoot!</font>")
return
if(src.loc != C)
if(loc != C)
return
sleep(1)
@@ -538,7 +539,7 @@
to_chat(src,"<font color='red'>You're pinned underfoot!</font>")
to_chat(H,"<font color='blue'>You pin the escapee underfoot!</font>")
return
if(src.loc != C)
if(loc != C)
return
sleep(1)
to_chat(src,"<font color='blue'>You manage to escape \the [C]!</font>")
@@ -599,7 +600,7 @@
if(is_type_in_list(I,edible_trash) | adminbus_trash)
if(I.hidden_uplink)
to_chat(src, "<span class='warning'>You really should not be eating this.</span>")
message_admins("[key_name(src)] has attempted to ingest an uplink item. ([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
message_admins("[key_name(src)] has attempted to ingest an uplink item. ([src ? ADMIN_JMP(src) : "null"])")
return
if(istype(I,/obj/item/device/pda))
var/obj/item/device/pda/P = I

View File

@@ -37,7 +37,7 @@
playsound('sound/effects/stealthoff.ogg',50,0)
bellied.forceMove(get_turf(src))
bellied.Weaken(2)
bellied.visible_message("[bellied] flops out of \the [src].","You flop out of \the [src].","You hear a thud.")
bellied.visible_message("[bellied] flops out of [src].","You flop out of [src].","You hear a thud.")
bellied = null
desc = "[initial(desc)]"
@@ -64,7 +64,7 @@
//Already full
if (hologram.bellied)
var/choice = alert("You can only contain one person. [hologram.bellied] is in you.","Already Full","Drop Mob","Cancel")
var/choice = alert("You can only contain one person. [hologram.bellied] is in you.", "Already Full", "Drop Mob", "Cancel")
if(choice == "Drop Mob")
hologram.drop_prey()
return
@@ -93,7 +93,7 @@
/mob/living/AIShiftClick(var/mob/user) //Shift-click as AI overridden on mobs to examine.
if(user.client)
src.examine(user)
examine(user)
return
//This can go here with all the references.

View File

@@ -6,21 +6,22 @@
//
// Simple nom proc for if you get ckey'd into a simple_mob mob! Avoids grabs.
//
/mob/living/simple_mob/proc/animal_nom(var/mob/living/T in living_mobs(1))
/mob/living/simple_mob/proc/animal_nom(mob/living/T in living_mobs(1))
set name = "Animal Nom"
set category = "IC"
set desc = "Since you can't grab, you get a verb!"
if (stat != CONSCIOUS)
if(stat != CONSCIOUS)
return
if (istype(src,/mob/living/simple_mob/animal/passive/mouse) && T.ckey == null)
// Verbs are horrifying. They don't call overrides. So we're stuck with this.
if(istype(src, /mob/living/simple_mob/animal/passive/mouse) && !T.ckey)
// Mice can't eat logged out players!
return
if (client && IsAdvancedToolUser())
if(client && IsAdvancedToolUser())
to_chat(src, "<span class='warning'>Put your hands to good use instead!</span>")
return
feed_grabbed_to_self(src,T)
update_icon()
return
//
// Simple proc for animals to have their digestion toggled on/off externally
@@ -45,8 +46,7 @@
var/confirm = alert(user, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will reset after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel")
if(confirm == "Enable")
vore_selected.digest_mode = DM_DIGEST
spawn(20 MINUTES)
if(src) vore_selected.digest_mode = vore_default_mode
addtimer(VARSET_CALLBACK(vore_selected, digest_mode, vore_default_mode), 20 MINUTES)
else
var/confirm = alert(user, "This mob is currently set to process all stomach contents. Do you want to disable this?", "Disabling [name]'s Digestion", "Disable", "Cancel")
if(confirm == "Disable")
@@ -69,28 +69,31 @@
to_chat(user, "[src] is now using [vore_selected.fancy_vore ? "Fancy" : "Classic"] vore sounds.")
/mob/living/simple_mob/attackby(var/obj/item/O, var/mob/user)
if (istype(O, /obj/item/weapon/newspaper) && !(ckey || (ai_holder.hostile && faction != user.faction)) && isturf(user.loc))
if (ai_holder.retaliate && prob(vore_pounce_chance/2)) // This is a gamble!
if(istype(O, /obj/item/weapon/newspaper) && !(ckey || (ai_holder.hostile && faction != user.faction)) && isturf(user.loc))
if(ai_holder.retaliate && prob(vore_pounce_chance/2)) // This is a gamble!
user.Weaken(5) //They get tackled anyway whether they're edible or not.
user.visible_message("<span class='danger'>\the [user] swats \the [src] with \the [O] and promptly gets tackled!</span>!")
if (will_eat(user))
user.visible_message("<span class='danger'>[user] swats [src] with [O] and promptly gets tackled!</span>!")
if(will_eat(user))
set_AI_busy(TRUE)
animal_nom(user)
update_icon()
set_AI_busy(FALSE)
else if (!ai_holder.target) // no using this to clear a retaliate mob's target
else if(!ai_holder.target) // no using this to clear a retaliate mob's target
ai_holder.target = user //just because you're not tasty doesn't mean you get off the hook. A swat for a swat.
//AttackTarget() //VOREStation AI Temporary Removal
//LoseTarget() // only make one attempt at an attack rather than going into full rage mode
else
user.visible_message("<span class='info'>\the [user] swats \the [src] with \the [O]!</span>!")
user.visible_message("<span class='info'>[user] swats [src] with [O]!</span>")
release_vore_contents()
for(var/mob/living/L in living_mobs(0)) //add everyone on the tile to the do-not-eat list for a while
if(!(L in prey_excludes)) // Unless they're already on it, just to avoid fuckery.
prey_excludes += L
spawn(5 MINUTES)
if(src && L)
prey_excludes -= L
addtimer(CALLBACK(src, .proc/removeMobFromPreyExcludes, weakref(L)), 5 MINUTES)
else
..()
/mob/living/simple_mob/proc/removeMobFromPreyExcludes(weakref/target)
if(isweakref(target))
var/mob/living/L = target.resolve()
if(L)
LAZYREMOVE(prey_excludes, L)

View File

@@ -241,7 +241,6 @@
BI.forceMove(torso)
torso.implants += BI
if(message)
to_chat(M, "<span class='notice'>You lose sensation of your body, feeling only the warmth of everything around you... </span>")
to_chat(O, "<span class='notice'>Your body shifts as you make dramatic changes to your captive's body.</span>")

View File

@@ -70,7 +70,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
//
// Check if an object is capable of eating things, based on vore_organs
//
/proc/is_vore_predator(var/mob/living/O)
/proc/is_vore_predator(mob/living/O)
if(istype(O,/mob/living))
if(O.vore_organs.len > 0)
return TRUE
@@ -87,8 +87,9 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
//
// Save/Load Vore Preferences
//
/datum/vore_preferences/proc/load_path(ckey,slot,filename="character",ext="json")
if(!ckey || !slot) return
/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]"
@@ -102,7 +103,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
load_path(client_ckey,slot)
if(!path) return FALSE //Path couldn't be set?
if(!path)
return FALSE //Path couldn't be set?
if(!fexists(path)) //Never saved before
save_vore() //Make the file first
return TRUE
@@ -151,7 +153,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
return TRUE
/datum/vore_preferences/proc/save_vore()
if(!path) return FALSE
if(!path)
return FALSE
var/version = VORE_VERSION //For "good times" use in the future
var/list/settings_list = list(

View File

@@ -8,68 +8,72 @@
#define BELLIES_DESC_MAX 2048
#define FLAVOR_MAX 40
/mob/living
var/datum/vore_look/vorePanel
/mob/living/proc/insidePanel()
set name = "Vore Panel"
set category = "IC"
var/datum/vore_look/picker_holder = new()
picker_holder.loop = picker_holder
picker_holder.selected = vore_selected
if(!vorePanel)
log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and tried to use the verb.")
vorePanel = new
var/dat = picker_holder.gen_ui(src)
picker_holder.popup = new(src, "insidePanel","Inside!", 450, 700, picker_holder)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
src.openpanel = 1
vorePanel.selected = vore_selected
vorePanel.show(src)
/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
if(!vorePanel)
log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and something tried to update it.")
vorePanel = new
var/dat = picker_holder.gen_ui(src)
picker_holder.popup = new(src, "insidePanel","Inside!", 450, 700, picker_holder)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
if(vorePanel.open)
vorePanel.selected = vore_selected
vorePanel.show(src)
//
// Callback Handler for the Inside form
//
/datum/vore_look
var/datum/browser/popup
var/obj/belly/selected
var/show_interacts = 0
var/datum/browser/popup
var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.
var/open = FALSE
/datum/vore_look/Destroy()
loop = null
selected = null
return QDEL_HINT_HARDDEL // TODO - Until I can better analyze how this weird thing works, lets be safe
QDEL_NULL(popup)
. = ..()
/datum/vore_look/Topic(href,href_list[])
if (vp_interact(href, href_list))
if(vp_interact(href, href_list))
popup.set_content(gen_ui(usr))
usr << output(popup.get_content(), "insidePanel.browser")
/datum/vore_look/proc/show(mob/living/user)
if(popup)
QDEL_NULL(popup)
popup = new(user, "insidePanel", "Inside!", 450, 700, src)
popup.set_content(gen_ui(user))
popup.open()
open = TRUE
/datum/vore_look/proc/gen_ui(var/mob/living/user)
var/dat
var/atom/userloc = user.loc
if (isbelly(userloc))
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>"
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)
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))
@@ -374,11 +378,9 @@
/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
user.openpanel = 0
open = FALSE
QDEL_NULL(popup)
return
if(href_list["show_int"])

View File

@@ -18,8 +18,8 @@
/datum/effect/effect/system/grav_pull/start()
spawn(0)
if(holder)
src.location = get_turf(holder)
for(var/i=0, i < number, i++)
location = get_turf(holder)
for(var/i = 0, i < number, i++)
do_pull()
sleep(25)
@@ -29,35 +29,35 @@
defer_powernet_rebuild = 1
// Let's just make this one loop.
for(var/atom/X in orange(pull_radius, location))
for(var/X in orange(pull_radius, location))
// Movable atoms only
if(istype(X, /atom/movable))
if(istype(X, /obj/effect/overlay)) continue
if(X && !istype(X, /mob/living/carbon/human))
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
var/obj/structure/window/W = X
W.ex_act(2.0)
if(!ismovableatom(X) || istype(X, /obj/effect/overlay))
continue
if(istype(X, /obj))
var/obj/O = X
if(O.anchored)
if (!pull_anchored) continue // Don't pull anchored stuff unless configured
step_towards(X, location) // step just once if anchored
continue
if(ishuman(X))
var/mob/living/carbon/human/H = X
if(istype(H.shoes, /obj/item/clothing/shoes/magboots))
var/obj/item/clothing/shoes/magboots/M = H.shoes
if(M.magpulse)
step_towards(H, location) //step just once with magboots
continue
step_towards(H, location) //step twice
step_towards(H, location)
else
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
var/obj/structure/window/W = X
W.ex_act(2.0)
step_towards(X, location) // Step twice
step_towards(X, location)
if(isobj(X))
var/obj/O = X
if(O.anchored)
if(!pull_anchored)
continue // Don't pull anchored stuff unless configured
step_towards(X, location) // step just once if anchored
continue
else if(istype(X,/mob/living/carbon/human))
var/mob/living/carbon/human/H = X
if(istype(H.shoes,/obj/item/clothing/shoes/magboots))
var/obj/item/clothing/shoes/magboots/M = H.shoes
if(M.magpulse)
step_towards(H, location) //step just once with magboots
continue
step_towards(H, location) //step twice
step_towards(H, location)
step_towards(X, location) // Step twice
step_towards(X, location)
if(defer_powernet_rebuild != 2)
defer_powernet_rebuild = 0
return

View File

@@ -10,36 +10,34 @@
item_icons = list() // No in-hand sprites (for now, anyway, we could totally add some)
pixel_y = 0 // Override value from parent.
/obj/item/weapon/holder/micro/examine(var/mob/user)
/obj/item/weapon/holder/micro/examine(mob/user)
for(var/mob/living/M in contents)
M.examine(user)
/obj/item/weapon/holder/MouseDrop(mob/M as mob)
/obj/item/weapon/holder/MouseDrop(mob/M)
..()
if(M != usr) return
if(usr == src) return
if(!Adjacent(usr)) return
if(istype(M,/mob/living/silicon/ai)) return
if(isAI(M)) return
for(var/mob/living/carbon/human/O in contents)
O.show_inv(usr)
/obj/item/weapon/holder/micro/attack_self(mob/living/carbon/user) //reworked so it works w/ nonhumans
for(var/L in contents)
if(!isliving(L))
continue
if(ishuman(L) && user.canClick())
if(ishuman(L) && user.canClick()) // These canClicks() are repeated here to make sure users can't avoid the click delay
var/mob/living/carbon/human/H = L
H.help_shake_act(user)
user.setClickCooldown(user.get_attack_speed()) //uses the same cooldown as regular attack_hand
return
if(istype(L, /mob/living/simple_mob) && user.canClick())
if(isanimal(L) && user.canClick())
var/mob/living/simple_mob/S = L
user.visible_message("<span class='notice'>[user] [S.response_help] \the [S].</span>")
user.setClickCooldown(user.get_attack_speed())
/obj/item/weapon/holder/micro/update_state()
if(istype(loc,/turf) || !(held_mob) || !(held_mob.loc == src))
if(isturf(loc) || !held_mob || held_mob.loc != src)
qdel(src)
/obj/item/weapon/holder/micro/Destroy()

View File

@@ -43,7 +43,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
var/matrix/M = matrix()
M.Scale(size_multiplier)
M.Translate(0, 16*(size_multiplier-1))
src.transform = M
transform = M
/**
* Get the effective size of a mob.
@@ -55,7 +55,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
return 100000 //Whatever it is, it's too big to pick up, or it's a ghost, or something.
/mob/living/get_effective_size()
return src.size_multiplier
return size_multiplier
/**
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
@@ -111,10 +111,11 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
var/nagmessage = "Adjust your mass to be a size between 25 to 200% (DO NOT ABUSE)"
var/new_size = input(nagmessage, "Pick a Size") as num|null
if(new_size && ISINRANGE(new_size,25,200))
src.resize(new_size/100)
message_admins("[key_name(src)] used the resize command in-game to be [new_size]% size. \
([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
if(new_size && ISINRANGE(new_size, 25, 200))
resize(new_size/100)
// I'm not entirely convinced that `src ? ADMIN_JMP(src) : "null"` here does anything
// but just in case it does, I'm leaving the null-src checking
message_admins("[key_name(src)] used the resize command in-game to be [new_size]% size. [src ? ADMIN_JMP(src) : "null"]")
/*
//Add the set_size() proc to usable verbs. By commenting this out, we can leave the proc and hand it to species that need it.
@@ -127,7 +128,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
* Attempt to scoop up this mob up into H's hands, if the size difference is large enough.
* @return false if normal code should continue, 1 to prevent normal code.
*/
/mob/living/proc/attempt_to_scoop(var/mob/living/M, var/mob/living/G) //second one is for the Grabber, only exists for animals to self-grab
/mob/living/proc/attempt_to_scoop(mob/living/M, mob/living/G) //second one is for the Grabber, only exists for animals to self-grab
var/size_diff = M.get_effective_size() - get_effective_size()
if(!holder_default && holder_type)
holder_default = holder_type
@@ -156,37 +157,42 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
* Called from /mob/living/Bump() in the 'brohugs all around' section.
* @return false if normal code should continue, true to prevent normal code.
*/
/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
/mob/living/proc/handle_micro_bump_helping(mob/living/tmob)
//Both small! Go ahead and go.
if(src.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
if(get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
return TRUE
//Worthy of doing messages at all
if(abs(get_effective_size() - tmob.get_effective_size()) >= 0.50)
var/src_message = null
var/tmob_message = null
//Smaller person being stepped onto
if(get_effective_size() > tmob.get_effective_size() && ishuman(src))
src_message = "You carefully step over [tmob]."
tmob_message = "[src] steps over you carefully!"
var/mob/living/carbon/human/H = src
if(H.flying)
return TRUE //Silently pass without a message.
if(isTaurTail(H.tail_style))
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER(tail.msg_owner_help_run))
to_chat(tmob,STEP_TEXT_PREY(tail.msg_prey_help_run))
else
to_chat(src,"You carefully step over [tmob].")
to_chat(tmob,"[src] steps over you carefully!")
src_message = tail.msg_owner_help_run
tmob_message = tail.msg_prey_help_run
//Smaller person stepping under larger person
else if(tmob.get_effective_size() > get_effective_size() && ishuman(tmob))
else if(get_effective_size() < tmob.get_effective_size() && ishuman(tmob))
src_message = "You run between [tmob]'s legs."
tmob_message = "[src] runs between your legs."
var/mob/living/carbon/human/H = tmob
if(isTaurTail(H.tail_style))
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER(tail.msg_prey_stepunder))
to_chat(tmob,STEP_TEXT_PREY(tail.msg_owner_stepunder))
else
to_chat(src,"You run between [tmob]'s legs.")
to_chat(tmob,"[src] runs between your legs.")
src_message = tail.msg_prey_stepunder
tmob_message = tail.msg_owner_stepunder
if(src_message)
to_chat(src, STEP_TEXT_OWNER(src_message))
if(tmob_message)
to_chat(tmob, STEP_TEXT_PREY(tmob_message))
return TRUE
return FALSE
@@ -196,202 +202,124 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
*
* @return false if normal code should continue, 1 to prevent normal code.
*/
/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
/mob/living/proc/handle_micro_bump_other(mob/living/tmob)
ASSERT(istype(tmob))
//If they're flying, don't do any special interactions.
if(ishuman(src))
var/mob/living/carbon/human/P = src
if(P.flying)
return
//If we're flying, don't do any special interactions.
if(flying)
return
//If the prey is flying, don't smush them.
if(ishuman(tmob))
var/mob/living/carbon/human/D = tmob
if(D.flying)
return
//They can't be stepping on anyone
if(tmob.flying)
return
//We can't be stepping on anyone
if(!canmove || buckled)
return
//Test/set if human
var/mob/living/carbon/human/H
if(ishuman(src))
H = src
else
var/mob/living/carbon/human/pred = src
if(!istype(pred))
//If we're not human, can't do the steppy
return FALSE
var/mob/living/carbon/human/Ht
if(ishuman(tmob))
Ht = tmob
else
var/mob/living/carbon/human/prey = tmob
if(!istype(prey))
//If they're not human, steppy shouldn't happen
return FALSE
//Depending on intent...
switch(a_intent)
// We need to be above a certain size ratio in order to do anything to the prey.
// For DISARM and HURT intent, this is >=0.75, for GRAB it is >=0.5
var/size_ratio = get_effective_size() - tmob.get_effective_size()
if(a_intent == I_GRAB && size_ratio < 0.5)
return FALSE
if((a_intent == I_DISARM || a_intent == I_HURT) && size_ratio < 0.75)
return FALSE
if(a_intent == I_HELP) // Theoretically not possible, but just in case.
return FALSE
//src stepped on someone with disarm intent
if(I_DISARM)
// If bigger than them by at least 0.75, move onto them and print message.
if((get_effective_size() - tmob.get_effective_size()) >= 0.75)
now_pushing = 0
forceMove(tmob.loc)
now_pushing = 0
forceMove(tmob.loc)
if(a_intent == I_GRAB || a_intent == I_DISARM)
tmob.resting = 1
//Running on I_DISARM
if(m_intent == "run")
tmob.resting = 1 //Force them down to the ground.
var/size_damage_multiplier = size_multiplier - tmob.size_multiplier
// This technically means that I_GRAB will set this value to the same as I_HARM, but
// I_GRAB won't ever trigger the damage-giving code, so it doesn't matter.
// I_HARM: Rand 1-3 multiplied by 1 min or 1.75 max. 1 min 5.25 max damage to each limb.
// I_DISARM: Perform some HALLOSS damage to the smaller.
// Since stunned is broken, let's do this. Rand 15-30 multiplied by 1 min or 1.75 max. 15 holo to 52.5 holo, depending on RNG and size differnece.
var/damage = (a_intent == I_DISARM) ? (rand(15, 30) * size_damage_multiplier) : (rand(1, 3) * size_damage_multiplier)
// I_HARM only
var/calculated_damage = damage / 2 //This will sting, but not kill. Does .5 to 2.625 damage, randomly, to each limb.
//Log it for admins (as opposed to walk which logs damage)
add_attack_logs(src,tmob,"Pinned underfoot (run, no halloss)")
var/message_pred = null
var/message_prey = null
var/datum/sprite_accessory/tail/taur/tail = null
if(isTaurTail(pred.tail_style))
tail = pred.tail_style
//Not a human, or not a taur, generic message only
if(!H || !isTaurTail(H.tail_style))
to_chat(src,"<span class='danger'>You quickly push [tmob] to the ground with your foot!</span>")
to_chat(tmob,"<span class='danger'>[src] pushes you down to the ground with their foot!</span>")
if(a_intent == I_GRAB)
// You can only grab prey if you have no shoes on.
if(pred.shoes)
message_pred = "You step down onto [prey], squishing them and forcing them down to the ground!"
message_prey = "[pred] steps down and squishes you with their foot, forcing you down to the ground!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_grab_fail)
message_prey = STEP_TEXT_PREY(tail.msg_prey_grab_fail)
add_attack_logs(pred, prey,"Grabbed underfoot ([tail ? "taur" : "nontaur"], shoes)")
else
message_pred = "You pin [prey] down onto the floor with your foot and curl your toes up around their body, trapping them inbetween them!"
message_prey = "[pred] pins you down to the floor with their foot and curls their toes up around your body, trapping you inbetween them!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_grab_success)
message_prey = STEP_TEXT_PREY(tail.msg_prey_grab_success)
equip_to_slot_if_possible(prey.get_scooped(pred), slot_shoes, 0, 1)
add_attack_logs(pred, prey, "Grabbed underfoot ([tail ? "taur" : "nontaur"], no shoes)")
//Human with taur tail, special messages are sent
else
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_disarm_run]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_disarm_run]</span>"))
if(m_intent == "run")
switch(a_intent)
if(I_DISARM)
message_pred = "You quickly push [prey] to the ground with your foot!"
message_prey = "[pred] pushes you down to the ground with their foot!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_disarm_run)
message_prey = STEP_TEXT_PREY(tail.msg_prey_disarm_run)
add_attack_logs(pred, prey, "Pinned underfoot (run, no halloss)")
if(I_HURT)
message_pred = "You carelessly step down onto [prey], crushing them!"
message_prey = "[pred] steps carelessly on your body, crushing you!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_harm_run)
message_prey = STEP_TEXT_PREY(tail.msg_prey_harm_run)
//Walking on I_DISARM
else
//Perform some HALLOSS damage to the smaller.
var/size_damage_multiplier = (src.size_multiplier - tmob.size_multiplier)
var/damage = (rand(15,30)* size_damage_multiplier) //Since stunned is broken, let's do this. Rand 15-30 multiplied by 1 min or 1.75 max. 15 holo to 52.5 holo, depending on RNG and size differnece.
tmob.apply_damage(damage, HALLOSS)
tmob.resting = 1
for(var/obj/item/organ/external/I in prey.organs)
I.take_damage(calculated_damage, 0) // 5 damage min, 26.25 damage max, depending on size & RNG. If they're only stepped on once, the damage will (probably not...) heal over time.
prey.drip(0.1)
add_attack_logs(pred, prey, "Crushed underfoot (run, about [calculated_damage] damage)")
else
switch(a_intent)
if(I_DISARM)
message_pred = "You firmly push your foot down on [prey], painfully but harmlessly pinning them to the ground!"
message_prey = "[pred] firmly pushes their foot down on you, quite painfully but harmlessly pinning you to the ground!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_disarm_walk)
message_prey = STEP_TEXT_PREY(tail.msg_prey_disarm_walk)
add_attack_logs(pred, prey, "Pinned underfoot (walk, about [damage] halloss)")
tmob.apply_damage(damage, HALLOSS)
if(I_HURT)
message_pred = "You methodically place your foot down upon [prey]'s body, slowly applying pressure, crushing them against the floor below!"
message_prey = "[pred] methodically places their foot upon your body, slowly applying pressure, crushing you against the floor below!"
if(tail)
message_pred = STEP_TEXT_OWNER(tail.msg_owner_harm_walk)
message_prey = STEP_TEXT_PREY(tail.msg_prey_harm_walk)
// Multiplies the above damage by 3.5. This means a min of 1.75 damage, or a max of 9.1875. damage to each limb, depending on size and RNG.
calculated_damage *= 3.5
for(var/obj/item/organ/I in prey.organs)
I.take_damage(calculated_damage, 0)
prey.drip(3)
add_attack_logs(pred, prey, "Crushed underfoot (walk, about [calculated_damage] damage)")
//Log it for admins (as opposed to run which logs no damage)
add_attack_logs(src,tmob,"Pinned underfoot (walk, about [damage] halloss)")
//Not a human, or not a taur, generic message only
if(!H || !isTaurTail(H.tail_style))
to_chat(src,"<span class='danger'>You firmly push your foot down on [tmob], painfully but harmlessly pinning them to the ground!</span>")
to_chat(tmob,"<span class='danger'>[src] firmly pushes their foot down on you, quite painfully but harmlessly pinning you to the ground!</span>")
//Human with taur tail, special messages are sent
else
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_disarm_walk]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_disarm_walk]</span>"))
//Return true, the sizediff was enough that we handled it.
return TRUE
//Not enough sizediff for I_DISARM to do anything.
else
return FALSE
//src stepped on someone with harm intent
if(I_HURT)
// If bigger than them by at least 0.75, move onto them and print message.
if((get_effective_size() - tmob.get_effective_size()) >= 0.75)
now_pushing = 0
forceMove(tmob.loc)
//Precalculate base damage
var/size_damage_multiplier = (src.size_multiplier - tmob.size_multiplier)
var/damage = (rand(1,3)* size_damage_multiplier) //Rand 1-3 multiplied by 1 min or 1.75 max. 1 min 5.25 max damage to each limb.
var/calculated_damage = damage/2 //This will sting, but not kill. Does .5 to 2.625 damage, randomly, to each limb.
//Running on I_HURT
if(m_intent == "run")
//Not a human, or not a taur, generic message only
if(!H || !isTaurTail(H.tail_style))
to_chat(src,"<span class='danger'>You carelessly step down onto [tmob], crushing them!</span>")
to_chat(tmob,"<span class='danger'>[src] steps carelessly on your body, crushing you!</span>")
//Human with taur tail, special messages are sent
else
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_harm_run]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_harm_run]</span>"))
//If they are a human, do damage (doesn't hurt other mobs...?)
if(Ht)
for(var/obj/item/organ/external/I in Ht.organs)
I.take_damage(calculated_damage, 0) // 5 damage min, 26.25 damage max, depending on size & RNG. If they're only stepped on once, the damage will (probably not...) heal over time.
Ht.drip(0.1)
add_attack_logs(src,tmob,"Crushed underfoot (run, about [calculated_damage] damage)")
//Walking on I_HURT
else
//Multiplies the above damage by 3.5. This means a min of 1.75 damage, or a max of 9.1875. damage to each limb, depending on size and RNG.
calculated_damage *= 3.5
//If they are a human, do damage (doesn't hurt other mobs...?)
if(Ht)
for(var/obj/item/organ/I in Ht.organs)
I.take_damage(calculated_damage, 0)
Ht.drip(3)
add_attack_logs(src,tmob,"Crushed underfoot (walk, about [calculated_damage] damage)")
//Not a human, or not a taur, generic message only
if(!H || !isTaurTail(H.tail_style))
to_chat(src,"<span class='danger'>You methodically place your foot down upon [tmob]'s body, slowly applying pressure, crushing them against the floor below!</span>")
to_chat(tmob,"<span class='danger'>[src] methodically places their foot upon your body, slowly applying pressure, crushing you against the floor below!</span>")
//Human with taur tail, special messages are sent
else
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_harm_walk]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_harm_walk]</span>"))
//Return true, the sizediff was enough that we handled it.
return TRUE
//Not enough sizediff for I_HURT to do anything.
else
return FALSE
//src stepped on someone with grab intent
if(I_GRAB)
// If bigger than them by at least 0.50, move onto them and print message.
if((get_effective_size() - tmob.get_effective_size()) >= 0.50)
now_pushing = 0
tmob.resting = 1
forceMove(tmob.loc)
//Not a human, or not a taur while wearing shoes = no grab
if(!H || (!isTaurTail(H.tail_style) && H.shoes))
to_chat(src,"<span class='danger'>You step down onto [tmob], squishing them and forcing them down to the ground!</span>")
to_chat(tmob,"<span class='danger'>[src] steps down and squishes you with their foot, forcing you down to the ground!</span>")
add_attack_logs(src,tmob,"Grabbed underfoot (nontaur, shoes)")
//Human, not a taur, but not wearing shoes = yes grab
else if(H && (!isTaurTail(H.tail_style) && !H.shoes))
to_chat(src,"<span class='danger'>You pin [tmob] down onto the floor with your foot and curl your toes up around their body, trapping them inbetween them!</span>")
to_chat(tmob,"<span class='danger'>[src] pins you down to the floor with their foot and curls their toes up around your body, trapping you inbetween them!</span>")
equip_to_slot_if_possible(tmob.get_scooped(H), slot_shoes, 0, 1)
add_attack_logs(src,tmob,"Grabbed underfoot (nontaur, no shoes)")
//Human, taur, shoes = no grab, special message
else if(H.shoes)
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_grab_fail]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_grab_fail]</span>"))
add_attack_logs(src,tmob,"Grabbed underfoot (taur, shoes)")
//Human, taur, no shoes = yes grab, special message
else
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_grab_success]</span>"))
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_grab_success]</span>"))
equip_to_slot_if_possible(tmob.get_scooped(H), slot_shoes, 0, 1)
add_attack_logs(src,tmob,"Grabbed underfoot (taur, no shoes)")
//Return true, the sizediff was enough that we handled it.
return TRUE
//Not enough sizediff for I_GRAB to do anything.
else
return FALSE
to_chat(pred, "<span class='danger'>[message_pred]</span>")
to_chat(prey, "<span class='danger'>[message_prey]</span>")
return TRUE
#undef STEP_TEXT_OWNER
#undef STEP_TEXT_PREY

View File

@@ -41,8 +41,8 @@
set category = "Object"
set src in view(1)
var/size_select = input("Put the desired size (25-200%)", "Set Size", size_set_to*100) as num
if(size_select>200 || size_select<25)
var/size_select = input("Put the desired size (25-200%)", "Set Size", size_set_to * 100) as num
if(size_select > 200 || size_select < 25)
to_chat(usr, "<span class='notice'>Invalid size.</span>")
return
size_set_to = (size_select/100)
@@ -69,24 +69,17 @@
tracer_type = /obj/effect/projectile/tracer/xray
impact_type = /obj/effect/projectile/impact/xray
on_hit(var/atom/target)
var/mob/living/M = target
if(ishuman(target))
var/mob/living/carbon/human/H = M
H.resize(set_size)
H.show_message("<font color='blue'> The beam fires into your body, changing your size!</font>")
H.updateicon()
else if (istype(target, /mob/living/))
var/mob/living/H = M
H.resize(set_size)
H.updateicon()
else
return 1
/obj/item/projectile/beam/sizelaser/on_hit(var/atom/target)
var/mob/living/M = target
if(istype(M))
M.resize(set_size)
to_chat(M, "<font color='blue'> The beam fires into your body, changing your size!</font>")
M.updateicon()
return
return 1
/obj/item/projectile/beam/sizelaser/shrink
set_size = 0.5 //50% of current size
/obj/item/projectile/beam/sizelaser/grow
set_size = 2.0 //200% of current size
set_size = 2.0 //200% of current size

View File

@@ -11,7 +11,7 @@
var/cooldown = 10
var/weightloss_power = 1
/obj/machinery/fitness/attack_hand(var/mob/living/user)
/obj/machinery/fitness/attack_hand(mob/living/user)
if(user.nutrition < 70)
to_chat(user, "<span class='notice'>You need more energy to workout with the [src]!</span>")
@@ -21,12 +21,12 @@
else //If they have enough nutrition and body weight, they can exercise.
user.setClickCooldown(cooldown)
user.nutrition -= 10 * weightloss_power
user.weight -= 0.025 * weightloss_power * (0.01*user.weight_loss)
flick("[icon_state]2",src)
user.weight -= 0.025 * weightloss_power * (0.01 * user.weight_loss)
flick("[icon_state]2", src)
var/message = pick(messages)
to_chat(user, "<span class='notice'>[message].</span>")
for(var/s in workout_sounds)
playsound(src.loc, s, 50, 1)
playsound(loc, s, 50, 1)
/obj/machinery/fitness/punching_bag
name = "punching bag"
@@ -54,20 +54,20 @@
"You hammer the clown right in it's face with your fist",
"A honk emits from the punching bag as you hit it")
/obj/machinery/fitness/heavy/attackby(obj/item/W, var/mob/living/user)
/obj/machinery/fitness/heavy/attackby(obj/item/W, mob/living/user)
if(W.is_wrench())
src.add_fingerprint(user)
add_fingerprint(user)
user.visible_message("<span class='warning'>[user] has [anchored ? "un" : ""]secured \the [src].</span>", "<span class='notice'>You [anchored ? "un" : ""]secure \the [src].</span>")
anchored = !anchored
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
return
/obj/machinery/fitness/heavy/attack_hand(var/mob/living/user)
/obj/machinery/fitness/heavy/attack_hand(mob/living/user)
if(!anchored)
to_chat(user, "<span class='notice'>For safety reasons, you are required to have this equipment wrenched down before using it!</span>")
return
else if(user.loc != src.loc)
else if(user.loc != loc)
to_chat(user, "<span class='notice'>For safety reasons, you need to be sitting in the [src] for it to work!</span>")
return