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/content = ""
var/title_buttons = "" var/title_buttons = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) /datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
user = nuser user = nuser
window_id = nwindow_id window_id = nwindow_id
if (ntitle) if (ntitle)
@@ -33,6 +31,14 @@
return return
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs 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) /datum/browser/proc/set_title(ntitle)
title = format_text(ntitle) title = format_text(ntitle)

View File

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

View File

@@ -32,6 +32,8 @@
if(buckled) if(buckled)
buckled.unbuckle_mob(src, TRUE) buckled.unbuckle_mob(src, TRUE)
qdel(selected_image) qdel(selected_image)
QDEL_NULL(vorePanel) //VOREStation Add
QDEL_LIST_NULL(vore_organs) //VOREStation Add
return ..() return ..()
//mob verbs are faster than object verbs. See mob/verb/examine. //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) /mob/living/simple_mob/vore/aggressive/corrupthound/space/Process_Spacemove(var/check_drift = 0)
return TRUE 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 var/obj/belly/B = vore_selected
B.name = "fuel processor" 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!", "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!") "'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 var/obj/belly/B = vore_selected
B.name = "fuel processor" 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/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/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/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. // Don't forget to watch your commas at the end of each line if you change these.
var/list/struggle_messages_outside = list( var/list/struggle_messages_outside = list(
@@ -177,7 +176,7 @@
. = ..() . = ..()
// Called whenever an atom enters this belly // 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) if(OldLoc in contents)
return //Someone dropping something (or being stripdigested) return //Someone dropping something (or being stripdigested)
@@ -207,8 +206,7 @@
// Release all contents of this belly into the owning mob's location. // 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. // 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. // 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 //Don't bother if we don't have contents
if(!contents.len) if(!contents.len)
return FALSE return FALSE
@@ -246,7 +244,7 @@
// Release a specific atom from the contents of this belly into the owning mob's location. // 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. // 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. // 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)) if (!(M in contents))
return 0 // They weren't in this belly anyway return 0 // They weren't in this belly anyway
@@ -294,10 +292,10 @@
// Actually perform the mechanics of devouring the tasty prey. // Actually perform the mechanics of devouring the tasty prey.
// The purpose of this method is to avoid duplicate code, and ensure that all necessary // The purpose of this method is to avoid duplicate code, and ensure that all necessary
// steps are taken. // 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) if(owner.stat == DEAD)
return return
if (prey.buckled) if(prey.buckled)
prey.buckled.unbuckle_mob() prey.buckled.unbuckle_mob()
prey.forceMove(src) prey.forceMove(src)
@@ -316,9 +314,9 @@
var/raw_message = pick(examine_messages) var/raw_message = pick(examine_messages)
var/total_bulge = 0 var/total_bulge = 0
formatted_message = replacetext(raw_message,"%belly",lowertext(name)) formatted_message = replacetext(raw_message, "%belly" ,lowertext(name))
formatted_message = replacetext(formatted_message,"%pred",owner) formatted_message = replacetext(formatted_message, "%pred" ,owner)
formatted_message = replacetext(formatted_message,"%prey",english_list(contents)) formatted_message = replacetext(formatted_message, "%prey" ,english_list(contents))
for(var/mob/living/P in 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. 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 total_bulge += P.size_multiplier
@@ -330,10 +328,10 @@
// The next function gets the messages set on the belly, in human-readable format. // 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 // 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. // 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") ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
var/list/raw_messages var/list/raw_messages
switch(type) switch(type)
if("smo") if("smo")
raw_messages = struggle_messages_outside raw_messages = struggle_messages_outside
@@ -346,13 +344,13 @@
if("em") if("em")
raw_messages = examine_messages raw_messages = examine_messages
var/messages = list2text(raw_messages,delim) var/messages = list2text(raw_messages, delim)
return messages return messages
// The next function sets the messages on the belly, from human-readable var // The next function sets the messages on the belly, from human-readable var
// replacement strings and linebreaks as delimiters (two \n\n by default). // replacement strings and linebreaks as delimiters (two \n\n by default).
// They also sanitize the messages. // 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") ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
var/list/raw_list = text2list(html_encode(raw_text),delim) 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. // Called from the process_Life() methods of bellies that digest prey.
// Default implementation calls M.death() and removes from internal contents. // Default implementation calls M.death() and removes from internal contents.
// Indigestable items are removed, and M is deleted. // Indigestable items are removed, and M is deleted.
/obj/belly/proc/digestion_death(var/mob/living/M) /obj/belly/proc/digestion_death(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"])") 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 digested prey is also a pred... anyone inside their bellies gets moved up.
if(is_vore_predator(M)) if(is_vore_predator(M))
@@ -399,7 +397,7 @@
//Drop all items into the belly. //Drop all items into the belly.
if(config.items_survive_digestion) if(config.items_survive_digestion)
for(var/obj/item/W in M) 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/obj/item/organ/internal/mmi_holder/MMI = W
var/atom/movable/brain = MMI.removed() var/atom/movable/brain = MMI.removed()
if(brain) if(brain)
@@ -410,7 +408,7 @@
var/obj/item/I = M.get_equipped_item(slot = slot) var/obj/item/I = M.get_equipped_item(slot = slot)
if(I) if(I)
M.unEquip(I,force = TRUE) 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. 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) if(item_digest_mode == IM_HOLD)
items_preserved |= I items_preserved |= I
@@ -435,10 +433,10 @@
qdel(M) qdel(M)
// Handle a mob being absorbed // 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 M.absorbed = 1
to_chat(M,"<span class='notice'>[owner]'s [lowertext(name)] absorbs your body, making you part of them.</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>") 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. if(M.noisy) //Mute drained absorbee hunger if enabled.
M.noisy = FALSE M.noisy = FALSE
@@ -473,7 +471,7 @@
//Digest a single item //Digest a single item
//Receives a return value from digest_act that's how much nutrition //Receives a return value from digest_act that's how much nutrition
//the item should be worth //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) var/digested = item.digest_act(src, owner)
if(!digested) if(!digested)
items_preserved |= item items_preserved |= item
@@ -482,6 +480,7 @@
if(isrobot(owner)) if(isrobot(owner))
var/mob/living/silicon/robot/R = owner var/mob/living/silicon/robot/R = owner
R.cell.charge += (50 * digested) R.cell.charge += (50 * digested)
return digested
//Determine where items should fall out of us into. //Determine where items should fall out of us into.
//Typically just to the owner's location. //Typically just to the owner's location.
@@ -499,20 +498,20 @@
/obj/belly/AllowDrop() /obj/belly/AllowDrop()
return TRUE return TRUE
/obj/belly/onDropInto(var/atom/movable/AM) /obj/belly/onDropInto(atom/movable/AM)
return null return null
//Handle a mob struggling //Handle a mob struggling
// Called from /mob/living/carbon/relaymove() // 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)) if (!(R in contents))
return // User is not in this belly return // User is not in this belly
R.setClickCooldown(50) R.setClickCooldown(50)
if(owner.stat) //If owner is stat (dead, KO) we can actually escape 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(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(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(do_after(R, escapetime, owner, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
if((owner.stat || escapable) && (R.loc == src)) //Can still escape? if((owner.stat || escapable) && (R.loc == src)) //Can still escape?
@@ -528,20 +527,20 @@
var/struggle_outer_message = pick(struggle_messages_outside) var/struggle_outer_message = pick(struggle_messages_outside)
var/struggle_user_message = pick(struggle_messages_inside) var/struggle_user_message = pick(struggle_messages_inside)
struggle_outer_message = replacetext(struggle_outer_message,"%pred",owner) 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, "%prey", R)
struggle_outer_message = replacetext(struggle_outer_message,"%belly",lowertext(name)) 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, "%pred", owner)
struggle_user_message = replacetext(struggle_user_message,"%prey",R) 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, "%belly", lowertext(name))
struggle_outer_message = "<span class='alert'>" + struggle_outer_message + "</span>" struggle_outer_message = "<span class='alert'>[struggle_outer_message]</span>"
struggle_user_message = "<span class='alert'>" + struggle_user_message + "</span>" struggle_user_message = "<span class='alert'>[struggle_user_message]</span>"
for(var/mob/M in hearers(4, owner)) for(var/mob/M in hearers(4, owner))
M.show_message(struggle_outer_message, 2) // hearable 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_snuggle
var/sound/struggle_rustle = sound(get_sfx("rustle")) var/sound/struggle_rustle = sound(get_sfx("rustle"))
@@ -557,8 +556,8 @@
if(escapable) //If the stomach has escapable enabled. if(escapable) //If the stomach has escapable enabled.
if(prob(escapechance)) //Let's have it check to see if the prey escapes first. 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(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(owner, "<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
if(do_after(R, escapetime)) if(do_after(R, escapetime))
if((escapable) && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled? if((escapable) && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled?
release_specific_contents(R) release_specific_contents(R)
@@ -588,26 +587,26 @@
transferlocation = null transferlocation = null
return 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(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(owner, "<span class='warning'>Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!</span>")
transfer_contents(R, dest_belly) transfer_contents(R, dest_belly)
return return
else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance. 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(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(owner, "<span class='warning'>You feel your [lowertext(name)] start to cling onto its contents...</span>")
digest_mode = DM_ABSORB digest_mode = DM_ABSORB
return return
else if(prob(digestchance) && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance. 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(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(owner, "<span class='warning'>You feel your [lowertext(name)] beginning to become active!</span>")
digest_mode = DM_DIGEST digest_mode = DM_DIGEST
return return
else //Nothing interesting happened. else //Nothing interesting happened.
to_chat(R,"<span class='warning'>You make no progress in escaping [owner]'s [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>") to_chat(owner, "<span class='warning'>Your prey appears to be unable to make any progress in escaping your [lowertext(name)].</span>")
return return
/obj/belly/proc/get_mobs_and_objs_in_belly() /obj/belly/proc/get_mobs_and_objs_in_belly()
@@ -624,7 +623,7 @@
return see return see
//Transfers contents from one belly to another //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)) if(!(content in src) || !istype(target))
return return
content.forceMove(target) content.forceMove(target)
@@ -636,16 +635,6 @@
I.decontaminate() I.decontaminate()
I.gurgle_contaminate(target.contents, target.contamination_flavor, target.contamination_color) I.gurgle_contaminate(target.contents, target.contamination_flavor, target.contamination_color)
items_preserved -= content 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() owner.updateVRPanel()
for(var/mob/living/M in contents) for(var/mob/living/M in contents)
M.updateVRPanel() 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. /* May not be necessary... Transform only shows up in the panel for humans.
if(!ishuman(owner)) if(!ishuman(owner))
return //Need DNA and junk for this. return //Need DNA and junk for this.
@@ -7,231 +7,86 @@
//Cast here for reduced duplication //Cast here for reduced duplication
var/mob/living/carbon/human/O = owner var/mob/living/carbon/human/O = owner
///////////////////////////// DM_TRANSFORM_HAIR_AND_EYES ///////////////////////////// var/stabilize_nutrition = FALSE
if(mode == DM_TRANSFORM_HAIR_AND_EYES) var/changes_eyes = FALSE
for (var/mob/living/carbon/human/P in touchable_mobs) var/changes_hair_solo = FALSE
if(P.stat == DEAD) var/changes_hairandskin = FALSE
continue 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 O.nutrition -= 2
P.nutrition += 1.5 H.nutrition += 1.5
if(changes_eyes && check_eyes(H))
if(check_eyes(P) || check_hair(P)) change_eyes(H, 1)
change_eyes(P) continue
change_hair(P,1) if(changes_hair_solo && check_hair(H))
change_hair(H)
///////////////////////////// DM_TRANSFORM_MALE ///////////////////////////// continue
else if(mode == DM_TRANSFORM_MALE) if(changes_hairandskin && (check_hair(H) || check_skin(H)))
for (var/mob/living/carbon/human/P in touchable_mobs) change_hair(H)
if(P.stat == DEAD) 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 continue
if(changes_ears_tail_wing_color && (check_ears(H) || check_tail(H) || check_wing(H) || check_species(H)))
if(O.nutrition > 400 && P.nutrition < 400) change_ears(H)
O.nutrition -= 2 change_tail(H)
P.nutrition += 1.5 change_wing(H)
change_species(H, 1, 2) // ,2) does not preserve coloring.
if(check_eyes(P))
change_eyes(P,1)
continue continue
if(changes_gender && check_gender(H, changes_gender_to))
if(check_hair(P) || check_skin(P)) change_gender(H, changes_gender_to, 1)
change_hair(P) continue
change_skin(P,1) if(eggs && (!H.absorbed))
continue put_in_egg(H, 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)

View File

@@ -1,5 +1,5 @@
// Process the predator's effects upon the contents of its belly (i.e digestion/transformation etc) // 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) if((times_fired < next_process) || !contents.len)
recent_sound = FALSE recent_sound = FALSE
return SSBELLIES_IGNORED return SSBELLIES_IGNORED
@@ -11,31 +11,13 @@
qdel(src) qdel(src)
return SSBELLIES_PROCESSED 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/play_sound //Potential sound to play at the end to avoid code duplication.
var/to_update = FALSE //Did anything update worthy happen? 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 ////////////////////// ///////////////////// Prey Loop Refresh/hack //////////////////////
for(var/mob/living/M in contents) prey_loop()
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))
/////////////////////////// Sound Selections /////////////////////////// /////////////////////////// Sound Selections ///////////////////////////
var/sound/prey_digest var/sound/prey_digest
@@ -61,31 +43,30 @@
var/list/touchable_mobs = list() var/list/touchable_mobs = list()
///////////////////// Early Non-Mode Handling ///////////////////// ///////////////////// 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) for(var/A in touchable_atoms)
//Handle stray items //Handle stray items
if(isitem(A) && !did_an_item) if(isitem(A) && !did_an_item)
var/obj/item/I = A did_an_item = handle_digesting_item(A)
if(contaminates || istype(I,/obj/item/weapon/card/id)) if(did_an_item)
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
to_update = TRUE 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 //Handle eaten mobs
else if(isliving(A)) else if(isliving(A))
@@ -105,278 +86,218 @@
H.bloodstr.add_reagent("numbenzyme",4) H.bloodstr.add_reagent("numbenzyme",4)
//Thickbelly flag //Thickbelly flag
if(mode_flags & DM_FLAG_THICKBELLY) if((mode_flags & DM_FLAG_THICKBELLY) && !H.muffled)
if(!(H.muffled)) H.muffled = TRUE
H.muffled = 1
//Stripping flag //Stripping flag
if(mode_flags & DM_FLAG_STRIPPING) if(mode_flags & DM_FLAG_STRIPPING)
for(var/slot in slots) for(var/slot in slots)
var/obj/item/I = H.get_equipped_item(slot = slot) var/obj/item/I = H.get_equipped_item(slot = slot)
if(I) if(I && H.unEquip(I, force = FALSE))
H.unEquip(I,force = FALSE) handle_digesting_item(I)
if(contaminates || istype(I,/obj/item/weapon/card/id)) digestion_noise_chance = 25
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)
to_update = TRUE 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 //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) qdel(A)
///////////////////////////// DM_HOLD /////////////////////////////
if(digest_mode == 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 //////////////////////////// if(digest_mode == DM_TRANSFORM)
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)
process_tf(tf_mode, touchable_mobs) 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 /////////////////////////// /////////////////////////// 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) if(play_sound)
LAZYCLEARLIST(hearing_mobs) for(var/mob/M in hearers(VORE_SOUND_RANGE, owner)) //so we don't fill the whole room with the sound effect
for(var/mob/M in hearers(VORE_SOUND_RANGE, owner)) if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
if(!M.client || !(M.is_preference_enabled(/datum/client_preference/digestion_noises)))
continue continue
LAZYADD(hearing_mobs, M) 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
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(fancy_vore) if(fancy_vore)
M.playsound_local(owner.loc, play_sound, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF) M.playsound_local(owner.loc, play_sound, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else else
M.playsound_local(owner.loc, play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF) 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. //these are all external sound triggers now, so it's ok.
if(to_update) if(to_update)
for(var/mob/living/M in contents) updateVRPanels()
if(M.client)
M.updateVRPanel()
if(owner.client)
owner.updateVRPanel()
return SSBELLIES_PROCESSED 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/cleandesc
var/gurgled_color 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()) if(!can_gurgle())
return FALSE return FALSE
@@ -65,28 +65,16 @@ var/list/gurgled_overlays = list(
if(gurgled) if(gurgled)
decontaminate() 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. /obj/structure/sink/attackby(obj/item/I, mob/user) //Wash the soggy item before it can interact with the sink.
if(O.gurgled) if(istype(I) && I.gurgled)
var/turf/location = user.loc to_chat(user, "<span class='notice'>You start washing [I].</span>")
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>")
busy = TRUE 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 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 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). //return non-negative integer: Amount of nutrition/charge gained (scaled to nutrition, other end can multiply for charge scale).
// Ye default implementation. // Ye default implementation.
/obj/item/proc/digest_act(var/atom/movable/item_storage = null) /obj/item/proc/digest_act(atom/movable/item_storage = null)
if(istype(item_storage,/obj/item/device/dogborg/sleeper)) if(istype(item_storage, /obj/item/device/dogborg/sleeper))
for(var/obj/item/O in contents) 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) for(var/obj/item/SO in O)
if(item_storage) if(item_storage)
SO.forceMove(item_storage) SO.forceMove(item_storage)
@@ -15,12 +15,15 @@
O.forceMove(item_storage) O.forceMove(item_storage)
qdel(src) qdel(src)
return w_class return w_class
var/g_damage = 1 var/g_damage = 1
if(digest_stage == null) if(digest_stage == null)
digest_stage = w_class digest_stage = w_class
if(isbelly(item_storage)) if(isbelly(item_storage))
var/obj/belly/B = item_storage var/obj/belly/B = item_storage
g_damage = 0.25 * (B.digest_brute + B.digest_burn) g_damage = 0.25 * (B.digest_brute + B.digest_burn)
if(digest_stage > 0) if(digest_stage > 0)
if(g_damage > digest_stage) if(g_damage > digest_stage)
g_damage = digest_stage g_damage = digest_stage
@@ -65,16 +68,16 @@
// Some special treatment // Some special treatment
///////////// /////////////
//PDAs need to lose their ID to not take it with them, so we can get a digested ID //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(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 id = null
. = ..() . = ..()
/obj/item/weapon/card/id /obj/item/weapon/card/id
var/lost_access = list() 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." 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 = 'icons/obj/card_vr.dmi'
icon_state = "[initial(icon_state)]_digested" icon_state = "[initial(icon_state)]_digested"
@@ -83,7 +86,7 @@
access = list() // Then lose it access = list() // Then lose it
return FALSE 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)) if(isbelly(item_storage))
var/obj/belly/B = item_storage var/obj/belly/B = item_storage
if(ishuman(B.owner)) if(ishuman(B.owner))
@@ -96,7 +99,7 @@
return w_class 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) for(var/mob/living/M in contents)
if(item_storage) if(item_storage)
M.forceMove(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((. = ..()))
if(isbelly(item_storage)) if(isbelly(item_storage))
var/obj/belly/B = item_storage var/obj/belly/B = item_storage
@@ -112,7 +115,7 @@
else else
. += 30 //Organs give a little more . += 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) for(var/obj/item/I in contents)
I.screen_loc = null I.screen_loc = null
@@ -121,7 +124,7 @@
///////////// /////////////
// Some more complicated stuff // 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 //Replace this with a VORE setting so all types of posibrains can/can't be digested on a whim
return FALSE 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) /obj/belly/proc/handle_remains_leaving(var/mob/living/M)
if(!ishuman(M)) //Are we even humanoid?
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
return 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 /obj/item/weapon/digestion_remains
name = "bone" name = "bone"
@@ -80,7 +70,7 @@
var/pred_ckey var/pred_ckey
var/pred_name 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) ..(newloc)
pred_ckey = pred.ckey pred_ckey = pred.ckey
pred_name = pred.name pred_name = pred.name

View File

@@ -19,7 +19,6 @@
var/metabolism = 0.0015 var/metabolism = 0.0015
var/vore_taste = null // What the character tastes like var/vore_taste = null // What the character tastes like
var/no_vore = FALSE // If the character/mob can vore. 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/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/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. 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 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. 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 return TRUE
M.vorePanel = new
M.verbs += /mob/living/proc/insidePanel M.verbs += /mob/living/proc/insidePanel
//Tries to load prefs if a client is present otherwise gives freebie stomach //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 // 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 //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 var/obj/item/weapon/grab/G = I
//Has to be aggressive grab, has to be living click-er and non-silicon grabbed //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 var/mob/living/attacker = user // Typecast to living
// src is the mob clicked on and attempted predator // src is the mob clicked on and attempted predator
///// If user clicked on themselves ///// If user clicked on themselves
if((src == G.assailant) && (is_vore_predator(src))) if(src == G.assailant && is_vore_predator(src))
if(!(G.affecting.devourable)) if(!G.affecting.devourable)
to_chat(user, "<span class='notice'>They aren't able to be devoured.</span>") 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 return FALSE
if(src.feed_grabbed_to_self(src, G.affecting))
if(feed_grabbed_to_self(src, G.affecting))
qdel(G) qdel(G)
return TRUE return TRUE
else else
@@ -115,57 +114,62 @@
///// If user clicked on their grabbed target ///// 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))) 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>") 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 return FALSE
if (attacker.feed_self_to_grabbed(attacker, G.affecting))
if(attacker.feed_self_to_grabbed(attacker, G.affecting))
qdel(G) qdel(G)
return TRUE return TRUE
else 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 ///// If user clicked on anyone else but their grabbed target
else if((src != G.affecting) && (src != G.assailant) && (is_vore_predator(src))) 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>") 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 return FALSE
if(!(G.affecting.devourable)) if(!(G.affecting.devourable))
to_chat(user, "<span class='notice'>[G.affecting] isn't able to be devoured.</span>") 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 return FALSE
if(attacker.feed_grabbed_to_other(attacker, G.affecting, src))
if (attacker.feed_grabbed_to_other(attacker, G.affecting, src))
qdel(G) qdel(G)
return TRUE return TRUE
else 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 //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 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 var/mob/living/attacker = user // Typecast to living
if(is_vore_predator(src))
if (is_vore_predator(src)) for(var/mob/living/M in H.contents)
for (var/mob/living/M in H.contents) if(attacker.eat_held_mob(attacker, M, src))
if (attacker.eat_held_mob(attacker, M, src)) if(H.held_mob == M)
if (H.held_mob == M)
H.held_mob = null H.held_mob = null
return TRUE //return TRUE to exit upper procs return TRUE //return TRUE to exit upper procs
else 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 //Handle case: /obj/item/device/radio/beacon
else if(istype(I,/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!") 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)) if(!istype(B))
return TRUE 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)) if(do_after(user,30,src))
user.drop_item() user.drop_item()
I.forceMove(B) I.forceMove(B)
@@ -179,7 +183,6 @@
// Our custom resist catches for /mob/living // Our custom resist catches for /mob/living
// //
/mob/living/proc/vore_process_resist() /mob/living/proc/vore_process_resist()
//Are we resisting from inside a belly? //Are we resisting from inside a belly?
if(isbelly(loc)) if(isbelly(loc))
var/obj/belly/B = loc var/obj/belly/B = loc
@@ -187,7 +190,6 @@
return TRUE //resist() on living does this TRUE thing. return TRUE //resist() on living does this TRUE thing.
//Other overridden resists go here //Other overridden resists go here
return FALSE return FALSE
// //
@@ -310,13 +312,12 @@
if(suit.hides_bulges) if(suit.hides_bulges)
return FALSE return FALSE
return ..() return ..()
// //
// Clearly super important. Obviously. // 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 name = "Lick"
set category = "IC" set category = "IC"
set desc = "Lick someone nearby!" set desc = "Lick someone nearby!"
@@ -402,11 +403,11 @@
// //
// Eating procs depending on who clicked what // 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 var/belly = user.vore_selected
return perform_the_nom(user, prey, user, belly) 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 var/belly
if(user != pred) if(user != pred)
belly = input("Choose Belly") in pred.vore_organs belly = input("Choose Belly") in pred.vore_organs
@@ -414,18 +415,18 @@
belly = pred.vore_selected belly = pred.vore_selected
return perform_the_nom(user, prey, pred, belly) 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 var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, user, pred, belly) 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 var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, prey, pred, belly) return perform_the_nom(user, prey, pred, belly)
// //
// Master vore proc that actually does vore procedures // 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 //Sanity
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs)) 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.") 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 // Prepare messages
if(user == pred) //Feeding someone to yourself 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)) attempt_msg = "<span class='warning'>[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
success_msg = text("<span class='warning'>[] manages to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name)) 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 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)) attempt_msg = "<span class='warning'>[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
success_msg = text("<span class='warning'>[] manages to make [] [] [] into their []!</span>",user,pred,lowertext(belly.vore_verb),prey,lowertext(belly.name)) 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! // Announce that we start the attempt!
user.visible_message(attempt_msg) 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>") to_chat(belly.owner, "<span class='notice'>[prey] tastes of [prey.get_taste_message(FALSE)].</span>")
// Inform Admins // Inform Admins
if (pred == user) if(pred == user)
add_attack_logs(pred,prey,"Eaten via [belly.name]") add_attack_logs(pred, prey, "Eaten via [belly.name]")
else 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 return TRUE
// //
@@ -522,7 +523,7 @@
to_chat(src,"<font color='red'>You're pinned back underfoot!</font>") 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>") to_chat(H,"<font color='blue'>You pin the escapee back underfoot!</font>")
return return
if(src.loc != C) if(loc != C)
return return
sleep(1) sleep(1)
@@ -538,7 +539,7 @@
to_chat(src,"<font color='red'>You're pinned underfoot!</font>") to_chat(src,"<font color='red'>You're pinned underfoot!</font>")
to_chat(H,"<font color='blue'>You pin the escapee underfoot!</font>") to_chat(H,"<font color='blue'>You pin the escapee underfoot!</font>")
return return
if(src.loc != C) if(loc != C)
return return
sleep(1) sleep(1)
to_chat(src,"<font color='blue'>You manage to escape \the [C]!</font>") 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(is_type_in_list(I,edible_trash) | adminbus_trash)
if(I.hidden_uplink) if(I.hidden_uplink)
to_chat(src, "<span class='warning'>You really should not be eating this.</span>") 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 return
if(istype(I,/obj/item/device/pda)) if(istype(I,/obj/item/device/pda))
var/obj/item/device/pda/P = I var/obj/item/device/pda/P = I

View File

@@ -37,7 +37,7 @@
playsound('sound/effects/stealthoff.ogg',50,0) playsound('sound/effects/stealthoff.ogg',50,0)
bellied.forceMove(get_turf(src)) bellied.forceMove(get_turf(src))
bellied.Weaken(2) 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 bellied = null
desc = "[initial(desc)]" desc = "[initial(desc)]"
@@ -64,7 +64,7 @@
//Already full //Already full
if (hologram.bellied) 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") if(choice == "Drop Mob")
hologram.drop_prey() hologram.drop_prey()
return return
@@ -93,7 +93,7 @@
/mob/living/AIShiftClick(var/mob/user) //Shift-click as AI overridden on mobs to examine. /mob/living/AIShiftClick(var/mob/user) //Shift-click as AI overridden on mobs to examine.
if(user.client) if(user.client)
src.examine(user) examine(user)
return return
//This can go here with all the references. //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. // 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 name = "Animal Nom"
set category = "IC" set category = "IC"
set desc = "Since you can't grab, you get a verb!" set desc = "Since you can't grab, you get a verb!"
if (stat != CONSCIOUS) if(stat != CONSCIOUS)
return 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 return
if (client && IsAdvancedToolUser()) if(client && IsAdvancedToolUser())
to_chat(src, "<span class='warning'>Put your hands to good use instead!</span>") to_chat(src, "<span class='warning'>Put your hands to good use instead!</span>")
return return
feed_grabbed_to_self(src,T) feed_grabbed_to_self(src,T)
update_icon() update_icon()
return
// //
// Simple proc for animals to have their digestion toggled on/off externally // 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") 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") if(confirm == "Enable")
vore_selected.digest_mode = DM_DIGEST vore_selected.digest_mode = DM_DIGEST
spawn(20 MINUTES) addtimer(VARSET_CALLBACK(vore_selected, digest_mode, vore_default_mode), 20 MINUTES)
if(src) vore_selected.digest_mode = vore_default_mode
else 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") 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") if(confirm == "Disable")
@@ -69,28 +69,31 @@
to_chat(user, "[src] is now using [vore_selected.fancy_vore ? "Fancy" : "Classic"] vore sounds.") 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) /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(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(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.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>!") user.visible_message("<span class='danger'>[user] swats [src] with [O] and promptly gets tackled!</span>!")
if (will_eat(user)) if(will_eat(user))
set_AI_busy(TRUE) set_AI_busy(TRUE)
animal_nom(user) animal_nom(user)
update_icon() update_icon()
set_AI_busy(FALSE) 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. 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 //AttackTarget() //VOREStation AI Temporary Removal
//LoseTarget() // only make one attempt at an attack rather than going into full rage mode //LoseTarget() // only make one attempt at an attack rather than going into full rage mode
else 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() 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 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. if(!(L in prey_excludes)) // Unless they're already on it, just to avoid fuckery.
prey_excludes += L prey_excludes += L
spawn(5 MINUTES) addtimer(CALLBACK(src, .proc/removeMobFromPreyExcludes, weakref(L)), 5 MINUTES)
if(src && L)
prey_excludes -= L
else 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) BI.forceMove(torso)
torso.implants += BI torso.implants += BI
if(message) 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(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>") 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 // 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(istype(O,/mob/living))
if(O.vore_organs.len > 0) if(O.vore_organs.len > 0)
return TRUE return TRUE
@@ -87,8 +87,9 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
// //
// Save/Load Vore Preferences // Save/Load Vore Preferences
// //
/datum/vore_preferences/proc/load_path(ckey,slot,filename="character",ext="json") /datum/vore_preferences/proc/load_path(ckey, slot, filename="character", ext="json")
if(!ckey || !slot) return if(!ckey || !slot)
return
path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/vore/[filename][slot].[ext]" 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) 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 if(!fexists(path)) //Never saved before
save_vore() //Make the file first save_vore() //Make the file first
return TRUE return TRUE
@@ -151,7 +153,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
return TRUE return TRUE
/datum/vore_preferences/proc/save_vore() /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/version = VORE_VERSION //For "good times" use in the future
var/list/settings_list = list( var/list/settings_list = list(

View File

@@ -8,68 +8,72 @@
#define BELLIES_DESC_MAX 2048 #define BELLIES_DESC_MAX 2048
#define FLAVOR_MAX 40 #define FLAVOR_MAX 40
/mob/living
var/datum/vore_look/vorePanel
/mob/living/proc/insidePanel() /mob/living/proc/insidePanel()
set name = "Vore Panel" set name = "Vore Panel"
set category = "IC" set category = "IC"
var/datum/vore_look/picker_holder = new() if(!vorePanel)
picker_holder.loop = picker_holder log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and tried to use the verb.")
picker_holder.selected = vore_selected vorePanel = new
var/dat = picker_holder.gen_ui(src) vorePanel.selected = vore_selected
vorePanel.show(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
/mob/living/proc/updateVRPanel() //Panel popup update call from belly events. /mob/living/proc/updateVRPanel() //Panel popup update call from belly events.
if(src.openpanel == 1) if(!vorePanel)
var/datum/vore_look/picker_holder = new() log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and something tried to update it.")
picker_holder.loop = picker_holder vorePanel = new
picker_holder.selected = vore_selected
var/dat = picker_holder.gen_ui(src) if(vorePanel.open)
vorePanel.selected = vore_selected
picker_holder.popup = new(src, "insidePanel","Inside!", 450, 700, picker_holder) vorePanel.show(src)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
// //
// Callback Handler for the Inside form // Callback Handler for the Inside form
// //
/datum/vore_look /datum/vore_look
var/datum/browser/popup
var/obj/belly/selected var/obj/belly/selected
var/show_interacts = 0 var/show_interacts = 0
var/datum/browser/popup var/open = FALSE
var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.
/datum/vore_look/Destroy() /datum/vore_look/Destroy()
loop = null
selected = 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[]) /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)) popup.set_content(gen_ui(usr))
usr << output(popup.get_content(), "insidePanel.browser") 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) /datum/vore_look/proc/gen_ui(var/mob/living/user)
var/dat var/dat
var/atom/userloc = user.loc var/atom/userloc = user.loc
if (isbelly(userloc)) if(isbelly(userloc))
var/obj/belly/inside_belly = userloc var/obj/belly/inside_belly = userloc
var/mob/living/eater = inside_belly.owner 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. //Don't display this part if we couldn't find the belly since could be held in hand.
if(inside_belly) 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) if(inside_belly.desc)
dat += "[inside_belly.desc]<br><br>" 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>" dat += "You can see the following around you:<br>"
for (var/atom/movable/O in inside_belly) for (var/atom/movable/O in inside_belly)
if(istype(O,/mob/living)) if(istype(O,/mob/living))
@@ -374,11 +378,9 @@
/datum/vore_look/proc/vp_interact(href, href_list) /datum/vore_look/proc/vp_interact(href, href_list)
var/mob/living/user = usr var/mob/living/user = usr
for(var/H in href_list)
if(href_list["close"]) if(href_list["close"])
qdel(src) // Cleanup open = FALSE
user.openpanel = 0 QDEL_NULL(popup)
return return
if(href_list["show_int"]) if(href_list["show_int"])

View File

@@ -18,8 +18,8 @@
/datum/effect/effect/system/grav_pull/start() /datum/effect/effect/system/grav_pull/start()
spawn(0) spawn(0)
if(holder) if(holder)
src.location = get_turf(holder) location = get_turf(holder)
for(var/i=0, i < number, i++) for(var/i = 0, i < number, i++)
do_pull() do_pull()
sleep(25) sleep(25)
@@ -29,35 +29,35 @@
defer_powernet_rebuild = 1 defer_powernet_rebuild = 1
// Let's just make this one loop. // 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 // Movable atoms only
if(istype(X, /atom/movable)) if(!ismovableatom(X) || istype(X, /obj/effect/overlay))
if(istype(X, /obj/effect/overlay)) continue 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(istype(X, /obj)) if(ishuman(X))
var/obj/O = X var/mob/living/carbon/human/H = X
if(O.anchored) if(istype(H.shoes, /obj/item/clothing/shoes/magboots))
if (!pull_anchored) continue // Don't pull anchored stuff unless configured var/obj/item/clothing/shoes/magboots/M = H.shoes
step_towards(X, location) // step just once if anchored if(M.magpulse)
continue 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 if(isobj(X))
step_towards(X, location) 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)) step_towards(X, location) // Step twice
var/mob/living/carbon/human/H = X step_towards(X, location)
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)
if(defer_powernet_rebuild != 2) if(defer_powernet_rebuild != 2)
defer_powernet_rebuild = 0 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) item_icons = list() // No in-hand sprites (for now, anyway, we could totally add some)
pixel_y = 0 // Override value from parent. 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) for(var/mob/living/M in contents)
M.examine(user) M.examine(user)
/obj/item/weapon/holder/MouseDrop(mob/M as mob) /obj/item/weapon/holder/MouseDrop(mob/M)
..() ..()
if(M != usr) return if(M != usr) return
if(usr == src) return if(usr == src) return
if(!Adjacent(usr)) 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) for(var/mob/living/carbon/human/O in contents)
O.show_inv(usr) O.show_inv(usr)
/obj/item/weapon/holder/micro/attack_self(mob/living/carbon/user) //reworked so it works w/ nonhumans /obj/item/weapon/holder/micro/attack_self(mob/living/carbon/user) //reworked so it works w/ nonhumans
for(var/L in contents) for(var/L in contents)
if(!isliving(L)) if(ishuman(L) && user.canClick()) // These canClicks() are repeated here to make sure users can't avoid the click delay
continue
if(ishuman(L) && user.canClick())
var/mob/living/carbon/human/H = L var/mob/living/carbon/human/H = L
H.help_shake_act(user) H.help_shake_act(user)
user.setClickCooldown(user.get_attack_speed()) //uses the same cooldown as regular attack_hand user.setClickCooldown(user.get_attack_speed()) //uses the same cooldown as regular attack_hand
return return
if(istype(L, /mob/living/simple_mob) && user.canClick()) if(isanimal(L) && user.canClick())
var/mob/living/simple_mob/S = L var/mob/living/simple_mob/S = L
user.visible_message("<span class='notice'>[user] [S.response_help] \the [S].</span>") user.visible_message("<span class='notice'>[user] [S.response_help] \the [S].</span>")
user.setClickCooldown(user.get_attack_speed()) user.setClickCooldown(user.get_attack_speed())
/obj/item/weapon/holder/micro/update_state() /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) qdel(src)
/obj/item/weapon/holder/micro/Destroy() /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() var/matrix/M = matrix()
M.Scale(size_multiplier) M.Scale(size_multiplier)
M.Translate(0, 16*(size_multiplier-1)) M.Translate(0, 16*(size_multiplier-1))
src.transform = M transform = M
/** /**
* Get the effective size of a mob. * 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. return 100000 //Whatever it is, it's too big to pick up, or it's a ghost, or something.
/mob/living/get_effective_size() /mob/living/get_effective_size()
return src.size_multiplier return size_multiplier
/** /**
* Resizes the mob immediately to the desired mod, animating it growing/shrinking. * 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/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 var/new_size = input(nagmessage, "Pick a Size") as num|null
if(new_size && ISINRANGE(new_size,25,200)) if(new_size && ISINRANGE(new_size, 25, 200))
src.resize(new_size/100) resize(new_size/100)
message_admins("[key_name(src)] used the resize command in-game to be [new_size]% size. \ // I'm not entirely convinced that `src ? ADMIN_JMP(src) : "null"` here does anything
([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])") // 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. //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. * 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. * @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() var/size_diff = M.get_effective_size() - get_effective_size()
if(!holder_default && holder_type) if(!holder_default && holder_type)
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. * Called from /mob/living/Bump() in the 'brohugs all around' section.
* @return false if normal code should continue, true to prevent normal code. * @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. //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 return TRUE
//Worthy of doing messages at all //Worthy of doing messages at all
if(abs(get_effective_size() - tmob.get_effective_size()) >= 0.50) if(abs(get_effective_size() - tmob.get_effective_size()) >= 0.50)
var/src_message = null
var/tmob_message = null
//Smaller person being stepped onto //Smaller person being stepped onto
if(get_effective_size() > tmob.get_effective_size() && ishuman(src)) 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 var/mob/living/carbon/human/H = src
if(H.flying) if(H.flying)
return TRUE //Silently pass without a message. return TRUE //Silently pass without a message.
if(isTaurTail(H.tail_style)) if(isTaurTail(H.tail_style))
var/datum/sprite_accessory/tail/taur/tail = H.tail_style var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER(tail.msg_owner_help_run)) src_message = tail.msg_owner_help_run
to_chat(tmob,STEP_TEXT_PREY(tail.msg_prey_help_run)) tmob_message = tail.msg_prey_help_run
else
to_chat(src,"You carefully step over [tmob].")
to_chat(tmob,"[src] steps over you carefully!")
//Smaller person stepping under larger person //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 var/mob/living/carbon/human/H = tmob
if(isTaurTail(H.tail_style)) if(isTaurTail(H.tail_style))
var/datum/sprite_accessory/tail/taur/tail = H.tail_style var/datum/sprite_accessory/tail/taur/tail = H.tail_style
to_chat(src,STEP_TEXT_OWNER(tail.msg_prey_stepunder)) src_message = tail.msg_prey_stepunder
to_chat(tmob,STEP_TEXT_PREY(tail.msg_owner_stepunder)) tmob_message = tail.msg_owner_stepunder
else
to_chat(src,"You run between [tmob]'s legs.") if(src_message)
to_chat(tmob,"[src] runs between your legs.") to_chat(src, STEP_TEXT_OWNER(src_message))
if(tmob_message)
to_chat(tmob, STEP_TEXT_PREY(tmob_message))
return TRUE return TRUE
return FALSE 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. * @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)) ASSERT(istype(tmob))
//If we're flying, don't do any special interactions.
//If they're flying, don't do any special interactions. if(flying)
if(ishuman(src)) return
var/mob/living/carbon/human/P = src
if(P.flying)
return
//If the prey is flying, don't smush them. //If the prey is flying, don't smush them.
if(ishuman(tmob)) if(tmob.flying)
var/mob/living/carbon/human/D = tmob return
if(D.flying) //We can't be stepping on anyone
return
//They can't be stepping on anyone
if(!canmove || buckled) if(!canmove || buckled)
return return
//Test/set if human //Test/set if human
var/mob/living/carbon/human/H var/mob/living/carbon/human/pred = src
if(ishuman(src)) if(!istype(pred))
H = src
else
//If we're not human, can't do the steppy //If we're not human, can't do the steppy
return FALSE return FALSE
var/mob/living/carbon/human/Ht var/mob/living/carbon/human/prey = tmob
if(ishuman(tmob)) if(!istype(prey))
Ht = tmob
else
//If they're not human, steppy shouldn't happen //If they're not human, steppy shouldn't happen
return FALSE return FALSE
//Depending on intent... // We need to be above a certain size ratio in order to do anything to the prey.
switch(a_intent) // 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 now_pushing = 0
if(I_DISARM) forceMove(tmob.loc)
// If bigger than them by at least 0.75, move onto them and print message. if(a_intent == I_GRAB || a_intent == I_DISARM)
if((get_effective_size() - tmob.get_effective_size()) >= 0.75) tmob.resting = 1
now_pushing = 0
forceMove(tmob.loc)
//Running on I_DISARM var/size_damage_multiplier = size_multiplier - tmob.size_multiplier
if(m_intent == "run") // This technically means that I_GRAB will set this value to the same as I_HARM, but
tmob.resting = 1 //Force them down to the ground. // 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) var/message_pred = null
add_attack_logs(src,tmob,"Pinned underfoot (run, no halloss)") 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(a_intent == I_GRAB)
if(!H || !isTaurTail(H.tail_style)) // You can only grab prey if you have no shoes on.
to_chat(src,"<span class='danger'>You quickly push [tmob] to the ground with your foot!</span>") if(pred.shoes)
to_chat(tmob,"<span class='danger'>[src] pushes you down to the ground with their foot!</span>") 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 if(m_intent == "run")
else switch(a_intent)
var/datum/sprite_accessory/tail/taur/tail = H.tail_style if(I_DISARM)
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_disarm_run]</span>")) message_pred = "You quickly push [prey] to the ground with your foot!"
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_disarm_run]</span>")) 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 for(var/obj/item/organ/external/I in prey.organs)
else 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.
//Perform some HALLOSS damage to the smaller. prey.drip(0.1)
var/size_damage_multiplier = (src.size_multiplier - tmob.size_multiplier) add_attack_logs(pred, prey, "Crushed underfoot (run, about [calculated_damage] damage)")
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. else
tmob.apply_damage(damage, HALLOSS) switch(a_intent)
tmob.resting = 1 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) to_chat(pred, "<span class='danger'>[message_pred]</span>")
add_attack_logs(src,tmob,"Pinned underfoot (walk, about [damage] halloss)") to_chat(prey, "<span class='danger'>[message_prey]</span>")
return TRUE
//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
#undef STEP_TEXT_OWNER #undef STEP_TEXT_OWNER
#undef STEP_TEXT_PREY #undef STEP_TEXT_PREY

View File

@@ -41,8 +41,8 @@
set category = "Object" set category = "Object"
set src in view(1) set src in view(1)
var/size_select = input("Put the desired size (25-200%)", "Set Size", size_set_to*100) as num 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) if(size_select > 200 || size_select < 25)
to_chat(usr, "<span class='notice'>Invalid size.</span>") to_chat(usr, "<span class='notice'>Invalid size.</span>")
return return
size_set_to = (size_select/100) size_set_to = (size_select/100)
@@ -69,24 +69,17 @@
tracer_type = /obj/effect/projectile/tracer/xray tracer_type = /obj/effect/projectile/tracer/xray
impact_type = /obj/effect/projectile/impact/xray impact_type = /obj/effect/projectile/impact/xray
on_hit(var/atom/target) /obj/item/projectile/beam/sizelaser/on_hit(var/atom/target)
var/mob/living/M = target var/mob/living/M = target
if(ishuman(target)) if(istype(M))
var/mob/living/carbon/human/H = M M.resize(set_size)
H.resize(set_size) to_chat(M, "<font color='blue'> The beam fires into your body, changing your size!</font>")
H.show_message("<font color='blue'> The beam fires into your body, changing your size!</font>") M.updateicon()
H.updateicon() return
else if (istype(target, /mob/living/)) return 1
var/mob/living/H = M
H.resize(set_size)
H.updateicon()
else
return 1
/obj/item/projectile/beam/sizelaser/shrink /obj/item/projectile/beam/sizelaser/shrink
set_size = 0.5 //50% of current size set_size = 0.5 //50% of current size
/obj/item/projectile/beam/sizelaser/grow /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/cooldown = 10
var/weightloss_power = 1 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) if(user.nutrition < 70)
to_chat(user, "<span class='notice'>You need more energy to workout with the [src]!</span>") 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. else //If they have enough nutrition and body weight, they can exercise.
user.setClickCooldown(cooldown) user.setClickCooldown(cooldown)
user.nutrition -= 10 * weightloss_power user.nutrition -= 10 * weightloss_power
user.weight -= 0.025 * weightloss_power * (0.01*user.weight_loss) user.weight -= 0.025 * weightloss_power * (0.01 * user.weight_loss)
flick("[icon_state]2",src) flick("[icon_state]2", src)
var/message = pick(messages) var/message = pick(messages)
to_chat(user, "<span class='notice'>[message].</span>") to_chat(user, "<span class='notice'>[message].</span>")
for(var/s in workout_sounds) for(var/s in workout_sounds)
playsound(src.loc, s, 50, 1) playsound(loc, s, 50, 1)
/obj/machinery/fitness/punching_bag /obj/machinery/fitness/punching_bag
name = "punching bag" name = "punching bag"
@@ -54,20 +54,20 @@
"You hammer the clown right in it's face with your fist", "You hammer the clown right in it's face with your fist",
"A honk emits from the punching bag as you hit it") "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()) 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>") 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 anchored = !anchored
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
return return
/obj/machinery/fitness/heavy/attack_hand(var/mob/living/user) /obj/machinery/fitness/heavy/attack_hand(mob/living/user)
if(!anchored) if(!anchored)
to_chat(user, "<span class='notice'>For safety reasons, you are required to have this equipment wrenched down before using it!</span>") to_chat(user, "<span class='notice'>For safety reasons, you are required to have this equipment wrenched down before using it!</span>")
return 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>") to_chat(user, "<span class='notice'>For safety reasons, you need to be sitting in the [src] for it to work!</span>")
return return