mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
Cleanup vore code
This commit is contained in:
@@ -15,9 +15,7 @@
|
||||
var/content = ""
|
||||
var/title_buttons = ""
|
||||
|
||||
|
||||
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
|
||||
|
||||
user = nuser
|
||||
window_id = nwindow_id
|
||||
if (ntitle)
|
||||
@@ -33,6 +31,14 @@
|
||||
return
|
||||
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
|
||||
|
||||
//VOREStation Edit - Allow browser datums to be garbage collected
|
||||
/datum/browser/Destroy()
|
||||
close()
|
||||
ref = null
|
||||
user = null
|
||||
. = ..()
|
||||
//VOREStation Edit End - Allow browser datums to be garbage collected
|
||||
|
||||
/datum/browser/proc/set_title(ntitle)
|
||||
title = format_text(ntitle)
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
for(var/organ in organs)
|
||||
qdel(organ)
|
||||
QDEL_NULL(nif) //VOREStation Add
|
||||
QDEL_LIST_NULL(vore_organs) //VOREStation Add
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Stat()
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob(src, TRUE)
|
||||
qdel(selected_image)
|
||||
QDEL_NULL(vorePanel) //VOREStation Add
|
||||
QDEL_LIST_NULL(vore_organs) //VOREStation Add
|
||||
return ..()
|
||||
|
||||
//mob verbs are faster than object verbs. See mob/verb/examine.
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/space/Process_Spacemove(var/check_drift = 0)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/vore/hostile/corrupthound/init_vore()
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/init_vore()
|
||||
..()
|
||||
var/obj/belly/B = vore_selected
|
||||
B.name = "fuel processor"
|
||||
@@ -143,7 +143,7 @@
|
||||
"The longer you spend stewing away in the pool of hot, clingy juices surrounding you, the weaker and weaker you seem to feel!",
|
||||
"'FU3L mE A1RE@Dy, S0 sO SORrY!?', your corrupted captor growls as its synthetic innards begin oozing more potent juices, grinding down into your body with increasing fervor!")
|
||||
|
||||
/mob/living/simple_mob/vore/hostile/corrupthound/prettyboi/init_vore()
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi/init_vore()
|
||||
..()
|
||||
var/obj/belly/B = vore_selected
|
||||
B.name = "fuel processor"
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
var/tmp/list/items_preserved = list() // Stuff that wont digest so we shouldn't process it again.
|
||||
var/tmp/next_emote = 0 // When we're supposed to print our next emote, as a belly controller tick #
|
||||
var/tmp/recent_sound = FALSE // Prevent audio spam
|
||||
var/tmp/list/hearing_mobs
|
||||
|
||||
// Don't forget to watch your commas at the end of each line if you change these.
|
||||
var/list/struggle_messages_outside = list(
|
||||
@@ -177,7 +176,7 @@
|
||||
. = ..()
|
||||
|
||||
// Called whenever an atom enters this belly
|
||||
/obj/belly/Entered(var/atom/movable/thing,var/atom/OldLoc)
|
||||
/obj/belly/Entered(atom/movable/thing, atom/OldLoc)
|
||||
if(OldLoc in contents)
|
||||
return //Someone dropping something (or being stripdigested)
|
||||
|
||||
@@ -207,8 +206,7 @@
|
||||
// Release all contents of this belly into the owning mob's location.
|
||||
// If that location is another mob, contents are transferred into whichever of its bellies the owning mob is in.
|
||||
// Returns the number of mobs so released.
|
||||
/obj/belly/proc/release_all_contents(var/include_absorbed = FALSE, var/silent = FALSE)
|
||||
|
||||
/obj/belly/proc/release_all_contents(include_absorbed = FALSE, silent = FALSE)
|
||||
//Don't bother if we don't have contents
|
||||
if(!contents.len)
|
||||
return FALSE
|
||||
@@ -246,7 +244,7 @@
|
||||
// Release a specific atom from the contents of this belly into the owning mob's location.
|
||||
// If that location is another mob, the atom is transferred into whichever of its bellies the owning mob is in.
|
||||
// Returns the number of atoms so released.
|
||||
/obj/belly/proc/release_specific_contents(var/atom/movable/M, var/silent = FALSE)
|
||||
/obj/belly/proc/release_specific_contents(atom/movable/M, silent = FALSE)
|
||||
if (!(M in contents))
|
||||
return 0 // They weren't in this belly anyway
|
||||
|
||||
@@ -294,10 +292,10 @@
|
||||
// Actually perform the mechanics of devouring the tasty prey.
|
||||
// The purpose of this method is to avoid duplicate code, and ensure that all necessary
|
||||
// steps are taken.
|
||||
/obj/belly/proc/nom_mob(var/mob/prey, var/mob/user)
|
||||
/obj/belly/proc/nom_mob(mob/prey, mob/user)
|
||||
if(owner.stat == DEAD)
|
||||
return
|
||||
if (prey.buckled)
|
||||
if(prey.buckled)
|
||||
prey.buckled.unbuckle_mob()
|
||||
|
||||
prey.forceMove(src)
|
||||
@@ -316,9 +314,9 @@
|
||||
var/raw_message = pick(examine_messages)
|
||||
var/total_bulge = 0
|
||||
|
||||
formatted_message = replacetext(raw_message,"%belly",lowertext(name))
|
||||
formatted_message = replacetext(formatted_message,"%pred",owner)
|
||||
formatted_message = replacetext(formatted_message,"%prey",english_list(contents))
|
||||
formatted_message = replacetext(raw_message, "%belly" ,lowertext(name))
|
||||
formatted_message = replacetext(formatted_message, "%pred" ,owner)
|
||||
formatted_message = replacetext(formatted_message, "%prey" ,english_list(contents))
|
||||
for(var/mob/living/P in contents)
|
||||
if(!P.absorbed) //This is required first, in case there's a person absorbed and not absorbed in a stomach.
|
||||
total_bulge += P.size_multiplier
|
||||
@@ -330,10 +328,10 @@
|
||||
// The next function gets the messages set on the belly, in human-readable format.
|
||||
// This is useful in customization boxes and such. The delimiter right now is \n\n so
|
||||
// in message boxes, this looks nice and is easily delimited.
|
||||
/obj/belly/proc/get_messages(var/type, var/delim = "\n\n")
|
||||
/obj/belly/proc/get_messages(type, delim = "\n\n")
|
||||
ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
|
||||
|
||||
var/list/raw_messages
|
||||
|
||||
switch(type)
|
||||
if("smo")
|
||||
raw_messages = struggle_messages_outside
|
||||
@@ -346,13 +344,13 @@
|
||||
if("em")
|
||||
raw_messages = examine_messages
|
||||
|
||||
var/messages = list2text(raw_messages,delim)
|
||||
var/messages = list2text(raw_messages, delim)
|
||||
return messages
|
||||
|
||||
// The next function sets the messages on the belly, from human-readable var
|
||||
// replacement strings and linebreaks as delimiters (two \n\n by default).
|
||||
// They also sanitize the messages.
|
||||
/obj/belly/proc/set_messages(var/raw_text, var/type, var/delim = "\n\n")
|
||||
/obj/belly/proc/set_messages(raw_text, type, delim = "\n\n")
|
||||
ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
|
||||
|
||||
var/list/raw_list = text2list(html_encode(raw_text),delim)
|
||||
@@ -389,8 +387,8 @@
|
||||
// Called from the process_Life() methods of bellies that digest prey.
|
||||
// Default implementation calls M.death() and removes from internal contents.
|
||||
// Indigestable items are removed, and M is deleted.
|
||||
/obj/belly/proc/digestion_death(var/mob/living/M)
|
||||
message_admins("[key_name(owner)] has digested [key_name(M)] in their [lowertext(name)] ([owner ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[owner.x];Y=[owner.y];Z=[owner.z]'>JMP</a>" : "null"])")
|
||||
/obj/belly/proc/digestion_death(mob/living/M)
|
||||
message_admins("[key_name(owner)] has digested [key_name(M)] in their [lowertext(name)] ([owner ? ADMIN_JMP(owner) : "null"])")
|
||||
|
||||
// If digested prey is also a pred... anyone inside their bellies gets moved up.
|
||||
if(is_vore_predator(M))
|
||||
@@ -399,7 +397,7 @@
|
||||
//Drop all items into the belly.
|
||||
if(config.items_survive_digestion)
|
||||
for(var/obj/item/W in M)
|
||||
if(istype(W,/obj/item/organ/internal/mmi_holder/posibrain))
|
||||
if(istype(W, /obj/item/organ/internal/mmi_holder/posibrain))
|
||||
var/obj/item/organ/internal/mmi_holder/MMI = W
|
||||
var/atom/movable/brain = MMI.removed()
|
||||
if(brain)
|
||||
@@ -410,7 +408,7 @@
|
||||
var/obj/item/I = M.get_equipped_item(slot = slot)
|
||||
if(I)
|
||||
M.unEquip(I,force = TRUE)
|
||||
if(contaminates || istype(I,/obj/item/weapon/card/id))
|
||||
if(contaminates || istype(I, /obj/item/weapon/card/id))
|
||||
I.gurgle_contaminate(contents, contamination_flavor, contamination_color) //We do an initial contamination pass to get stuff like IDs wet.
|
||||
if(item_digest_mode == IM_HOLD)
|
||||
items_preserved |= I
|
||||
@@ -435,10 +433,10 @@
|
||||
qdel(M)
|
||||
|
||||
// Handle a mob being absorbed
|
||||
/obj/belly/proc/absorb_living(var/mob/living/M)
|
||||
/obj/belly/proc/absorb_living(mob/living/M)
|
||||
M.absorbed = 1
|
||||
to_chat(M,"<span class='notice'>[owner]'s [lowertext(name)] absorbs your body, making you part of them.</span>")
|
||||
to_chat(owner,"<span class='notice'>Your [lowertext(name)] absorbs [M]'s body, making them part of you.</span>")
|
||||
to_chat(M, "<span class='notice'>[owner]'s [lowertext(name)] absorbs your body, making you part of them.</span>")
|
||||
to_chat(owner, "<span class='notice'>Your [lowertext(name)] absorbs [M]'s body, making them part of you.</span>")
|
||||
if(M.noisy) //Mute drained absorbee hunger if enabled.
|
||||
M.noisy = FALSE
|
||||
|
||||
@@ -473,7 +471,7 @@
|
||||
//Digest a single item
|
||||
//Receives a return value from digest_act that's how much nutrition
|
||||
//the item should be worth
|
||||
/obj/belly/proc/digest_item(var/obj/item/item)
|
||||
/obj/belly/proc/digest_item(obj/item/item)
|
||||
var/digested = item.digest_act(src, owner)
|
||||
if(!digested)
|
||||
items_preserved |= item
|
||||
@@ -482,6 +480,7 @@
|
||||
if(isrobot(owner))
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
R.cell.charge += (50 * digested)
|
||||
return digested
|
||||
|
||||
//Determine where items should fall out of us into.
|
||||
//Typically just to the owner's location.
|
||||
@@ -499,20 +498,20 @@
|
||||
/obj/belly/AllowDrop()
|
||||
return TRUE
|
||||
|
||||
/obj/belly/onDropInto(var/atom/movable/AM)
|
||||
/obj/belly/onDropInto(atom/movable/AM)
|
||||
return null
|
||||
|
||||
//Handle a mob struggling
|
||||
// Called from /mob/living/carbon/relaymove()
|
||||
/obj/belly/proc/relay_resist(var/mob/living/R)
|
||||
/obj/belly/proc/relay_resist(mob/living/R)
|
||||
if (!(R in contents))
|
||||
return // User is not in this belly
|
||||
|
||||
R.setClickCooldown(50)
|
||||
|
||||
if(owner.stat) //If owner is stat (dead, KO) we can actually escape
|
||||
to_chat(R,"<span class='warning'>You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)</span>")
|
||||
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
|
||||
to_chat(R, "<span class='warning'>You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)</span>")
|
||||
to_chat(owner, "<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
|
||||
|
||||
if(do_after(R, escapetime, owner, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
|
||||
if((owner.stat || escapable) && (R.loc == src)) //Can still escape?
|
||||
@@ -528,20 +527,20 @@
|
||||
var/struggle_outer_message = pick(struggle_messages_outside)
|
||||
var/struggle_user_message = pick(struggle_messages_inside)
|
||||
|
||||
struggle_outer_message = replacetext(struggle_outer_message,"%pred",owner)
|
||||
struggle_outer_message = replacetext(struggle_outer_message,"%prey",R)
|
||||
struggle_outer_message = replacetext(struggle_outer_message,"%belly",lowertext(name))
|
||||
struggle_outer_message = replacetext(struggle_outer_message, "%pred", owner)
|
||||
struggle_outer_message = replacetext(struggle_outer_message, "%prey", R)
|
||||
struggle_outer_message = replacetext(struggle_outer_message, "%belly", lowertext(name))
|
||||
|
||||
struggle_user_message = replacetext(struggle_user_message,"%pred",owner)
|
||||
struggle_user_message = replacetext(struggle_user_message,"%prey",R)
|
||||
struggle_user_message = replacetext(struggle_user_message,"%belly",lowertext(name))
|
||||
struggle_user_message = replacetext(struggle_user_message, "%pred", owner)
|
||||
struggle_user_message = replacetext(struggle_user_message, "%prey", R)
|
||||
struggle_user_message = replacetext(struggle_user_message, "%belly", lowertext(name))
|
||||
|
||||
struggle_outer_message = "<span class='alert'>" + struggle_outer_message + "</span>"
|
||||
struggle_user_message = "<span class='alert'>" + struggle_user_message + "</span>"
|
||||
struggle_outer_message = "<span class='alert'>[struggle_outer_message]</span>"
|
||||
struggle_user_message = "<span class='alert'>[struggle_user_message]</span>"
|
||||
|
||||
for(var/mob/M in hearers(4, owner))
|
||||
M.show_message(struggle_outer_message, 2) // hearable
|
||||
to_chat(R,struggle_user_message)
|
||||
to_chat(R, struggle_user_message)
|
||||
|
||||
var/sound/struggle_snuggle
|
||||
var/sound/struggle_rustle = sound(get_sfx("rustle"))
|
||||
@@ -557,8 +556,8 @@
|
||||
|
||||
if(escapable) //If the stomach has escapable enabled.
|
||||
if(prob(escapechance)) //Let's have it check to see if the prey escapes first.
|
||||
to_chat(R,"<span class='warning'>You start to climb out of \the [lowertext(name)].</span>")
|
||||
to_chat(owner,"<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
|
||||
to_chat(R, "<span class='warning'>You start to climb out of \the [lowertext(name)].</span>")
|
||||
to_chat(owner, "<span class='warning'>Someone is attempting to climb out of your [lowertext(name)]!</span>")
|
||||
if(do_after(R, escapetime))
|
||||
if((escapable) && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled?
|
||||
release_specific_contents(R)
|
||||
@@ -588,26 +587,26 @@
|
||||
transferlocation = null
|
||||
return
|
||||
|
||||
to_chat(R,"<span class='warning'>Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!</span>")
|
||||
to_chat(owner,"<span class='warning'>Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!</span>")
|
||||
to_chat(R, "<span class='warning'>Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!</span>")
|
||||
to_chat(owner, "<span class='warning'>Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!</span>")
|
||||
transfer_contents(R, dest_belly)
|
||||
return
|
||||
|
||||
else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance.
|
||||
to_chat(R,"<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to cling more tightly...</span>")
|
||||
to_chat(owner,"<span class='warning'>You feel your [lowertext(name)] start to cling onto its contents...</span>")
|
||||
to_chat(R, "<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to cling more tightly...</span>")
|
||||
to_chat(owner, "<span class='warning'>You feel your [lowertext(name)] start to cling onto its contents...</span>")
|
||||
digest_mode = DM_ABSORB
|
||||
return
|
||||
|
||||
else if(prob(digestchance) && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance.
|
||||
to_chat(R,"<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to get more active...</span>")
|
||||
to_chat(owner,"<span class='warning'>You feel your [lowertext(name)] beginning to become active!</span>")
|
||||
to_chat(R, "<span class='warning'>In response to your struggling, \the [lowertext(name)] begins to get more active...</span>")
|
||||
to_chat(owner, "<span class='warning'>You feel your [lowertext(name)] beginning to become active!</span>")
|
||||
digest_mode = DM_DIGEST
|
||||
return
|
||||
|
||||
else //Nothing interesting happened.
|
||||
to_chat(R,"<span class='warning'>You make no progress in escaping [owner]'s [lowertext(name)].</span>")
|
||||
to_chat(owner,"<span class='warning'>Your prey appears to be unable to make any progress in escaping your [lowertext(name)].</span>")
|
||||
to_chat(R, "<span class='warning'>You make no progress in escaping [owner]'s [lowertext(name)].</span>")
|
||||
to_chat(owner, "<span class='warning'>Your prey appears to be unable to make any progress in escaping your [lowertext(name)].</span>")
|
||||
return
|
||||
|
||||
/obj/belly/proc/get_mobs_and_objs_in_belly()
|
||||
@@ -624,7 +623,7 @@
|
||||
return see
|
||||
|
||||
//Transfers contents from one belly to another
|
||||
/obj/belly/proc/transfer_contents(var/atom/movable/content, var/obj/belly/target, silent = 0)
|
||||
/obj/belly/proc/transfer_contents(atom/movable/content, obj/belly/target, silent = 0)
|
||||
if(!(content in src) || !istype(target))
|
||||
return
|
||||
content.forceMove(target)
|
||||
@@ -636,16 +635,6 @@
|
||||
I.decontaminate()
|
||||
I.gurgle_contaminate(target.contents, target.contamination_flavor, target.contamination_color)
|
||||
items_preserved -= content
|
||||
/* Disabling this part due to redundancy. Entered() on target belly will make the sound anyway.
|
||||
if(!silent && target.vore_sound && !recent_sound)
|
||||
var/soundfile
|
||||
if(!target.fancy_vore)
|
||||
soundfile = classic_vore_sounds[target.vore_sound]
|
||||
else
|
||||
soundfile = fancy_vore_sounds[target.vore_sound]
|
||||
if(soundfile)
|
||||
playsound(src, soundfile, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF, preference = /datum/client_preference/digestion_noises)
|
||||
*/
|
||||
owner.updateVRPanel()
|
||||
for(var/mob/living/M in contents)
|
||||
M.updateVRPanel()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/belly/proc/process_tf(var/mode,var/list/touchable_mobs) //We pass mode so it's mega-ultra local.
|
||||
/obj/belly/proc/process_tf(mode, list/touchable_mobs) //We pass mode so it's mega-ultra local.
|
||||
/* May not be necessary... Transform only shows up in the panel for humans.
|
||||
if(!ishuman(owner))
|
||||
return //Need DNA and junk for this.
|
||||
@@ -7,231 +7,86 @@
|
||||
//Cast here for reduced duplication
|
||||
var/mob/living/carbon/human/O = owner
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_HAIR_AND_EYES /////////////////////////////
|
||||
if(mode == DM_TRANSFORM_HAIR_AND_EYES)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
var/stabilize_nutrition = FALSE
|
||||
var/changes_eyes = FALSE
|
||||
var/changes_hair_solo = FALSE
|
||||
var/changes_hairandskin = FALSE
|
||||
var/changes_gender = FALSE
|
||||
var/changes_gender_to = null
|
||||
var/changes_species = FALSE
|
||||
var/changes_ears_tail_wing_nocolor = FALSE
|
||||
var/changes_ears_tail_wing_color = FALSE
|
||||
var/eggs = FALSE
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
switch(mode)
|
||||
if(DM_TRANSFORM_HAIR_AND_EYES)
|
||||
stabilize_nutrition = TRUE
|
||||
changes_eyes = TRUE
|
||||
changes_hair_solo = TRUE
|
||||
if(DM_TRANSFORM_MALE, DM_TRANSFORM_FEMALE, DM_TRANSFORM_MALE_EGG, DM_TRANSFORM_FEMALE_EGG)
|
||||
changes_eyes = TRUE
|
||||
changes_hairandskin = TRUE
|
||||
changes_gender = TRUE
|
||||
changes_gender_to = (mode == DM_TRANSFORM_MALE || mode == DM_TRANSFORM_MALE_EGG) ? MALE : FEMALE
|
||||
stabilize_nutrition = TRUE
|
||||
eggs = (mode == DM_TRANSFORM_MALE_EGG || mode == DM_TRANSFORM_FEMALE_EGG)
|
||||
if(DM_TRANSFORM_KEEP_GENDER, DM_TRANSFORM_KEEP_GENDER_EGG)
|
||||
changes_eyes = TRUE
|
||||
changes_hairandskin = TRUE
|
||||
stabilize_nutrition = TRUE
|
||||
eggs = (mode == DM_TRANSFORM_KEEP_GENDER_EGG)
|
||||
if(DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR, DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
|
||||
changes_species = TRUE
|
||||
changes_ears_tail_wing_nocolor = TRUE
|
||||
stabilize_nutrition = TRUE
|
||||
eggs = (mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
|
||||
if(DM_TRANSFORM_REPLICA, DM_TRANSFORM_REPLICA_EGG)
|
||||
changes_eyes = TRUE
|
||||
changes_hairandskin = TRUE
|
||||
changes_species = TRUE
|
||||
changes_ears_tail_wing_color = TRUE
|
||||
eggs = (mode == DM_TRANSFORM_REPLICA_EGG)
|
||||
if(DM_EGG)
|
||||
eggs = TRUE
|
||||
|
||||
/* This is designed to do *gradual* transformations.
|
||||
* For each human in the TF belly per cycle, they can only have one "stage" of transformation applied to them.
|
||||
* Some transformation modes have different amounts of stages than others and that's okay.
|
||||
* All stages in order: Eyes, Hair & Skin, Ears & Tail & Wings & Species, Gender, Egg
|
||||
*/
|
||||
for(var/mob/living/carbon/human/H in touchable_mobs)
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if(stabilize_nutrition)
|
||||
if(O.nutrition > 400 && H.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_eyes(P) || check_hair(P))
|
||||
change_eyes(P)
|
||||
change_hair(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_MALE /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_MALE)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
H.nutrition += 1.5
|
||||
if(changes_eyes && check_eyes(H))
|
||||
change_eyes(H, 1)
|
||||
continue
|
||||
if(changes_hair_solo && check_hair(H))
|
||||
change_hair(H)
|
||||
continue
|
||||
if(changes_hairandskin && (check_hair(H) || check_skin(H)))
|
||||
change_hair(H)
|
||||
change_skin(H, 1)
|
||||
continue
|
||||
if(changes_species)
|
||||
if(changes_ears_tail_wing_nocolor && (check_ears(H) || check_tail_nocolor(H) || check_wing_nocolor(H) || check_species(H)))
|
||||
change_ears(H)
|
||||
change_tail_nocolor(H)
|
||||
change_wing_nocolor(H)
|
||||
change_species(H, 1, 1) // ,1) preserves coloring
|
||||
continue
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
if(changes_ears_tail_wing_color && (check_ears(H) || check_tail(H) || check_wing(H) || check_species(H)))
|
||||
change_ears(H)
|
||||
change_tail(H)
|
||||
change_wing(H)
|
||||
change_species(H, 1, 2) // ,2) does not preserve coloring.
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_gender(P,MALE))
|
||||
change_gender(P,MALE,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_FEMALE /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_FEMALE)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_gender(P,FEMALE))
|
||||
change_gender(P,FEMALE,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_KEEP_GENDER /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_KEEP_GENDER)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_ears(P) || check_tail_nocolor(P) || check_wing_nocolor(P) || check_species(P))
|
||||
change_ears(P)
|
||||
change_tail_nocolor(P)
|
||||
change_wing_nocolor(P)
|
||||
change_species(P,1,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_REPLICA /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_REPLICA)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(O.nutrition > 400 && P.nutrition < 400)
|
||||
O.nutrition -= 2
|
||||
P.nutrition += 1.5
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_ears(P) || check_tail(P) || check_wing(P) || check_species(P))
|
||||
change_ears(P)
|
||||
change_tail(P)
|
||||
change_wing(P)
|
||||
change_species(P,1,2)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(check_ears(P) || check_tail_nocolor(P) || check_wing_nocolor(P)|| check_species(P))
|
||||
change_ears(P)
|
||||
change_tail_nocolor(P)
|
||||
change_wing_nocolor(P)
|
||||
change_species(P,1,1)
|
||||
continue
|
||||
|
||||
if(!P.absorbed)
|
||||
put_in_egg(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_KEEP_GENDER_EGG /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_KEEP_GENDER_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(!P.absorbed)
|
||||
put_in_egg(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_REPLICA_EGG /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_REPLICA_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_ears(P) || check_tail(P) || check_wing(P) || check_species(P))
|
||||
change_ears(P)
|
||||
change_tail(P)
|
||||
change_wing(P)
|
||||
change_species(P,1,2)
|
||||
continue
|
||||
|
||||
if(!P.absorbed)
|
||||
put_in_egg(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_MALE_EGG /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_MALE_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_gender(P,MALE))
|
||||
change_gender(P,MALE,1)
|
||||
continue
|
||||
|
||||
if(!P.absorbed)
|
||||
put_in_egg(P,1)
|
||||
|
||||
///////////////////////////// DM_TRANSFORM_FEMALE_EGG /////////////////////////////
|
||||
else if(mode == DM_TRANSFORM_FEMALE_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(check_eyes(P))
|
||||
change_eyes(P,1)
|
||||
continue
|
||||
|
||||
if(check_hair(P) || check_skin(P))
|
||||
change_hair(P)
|
||||
change_skin(P,1)
|
||||
continue
|
||||
|
||||
if(check_gender(P,MALE))
|
||||
change_gender(P,MALE,1)
|
||||
continue
|
||||
|
||||
if(!P.absorbed)
|
||||
put_in_egg(P,1)
|
||||
|
||||
///////////////////////////// DM_EGG /////////////////////////////
|
||||
else if(mode == DM_EGG)
|
||||
for (var/mob/living/carbon/human/P in touchable_mobs)
|
||||
if(P.absorbed || P.stat == DEAD)
|
||||
continue
|
||||
|
||||
put_in_egg(P,1)
|
||||
|
||||
if(changes_gender && check_gender(H, changes_gender_to))
|
||||
change_gender(H, changes_gender_to, 1)
|
||||
continue
|
||||
if(eggs && (!H.absorbed))
|
||||
put_in_egg(H, 1)
|
||||
continue
|
||||
@@ -1,5 +1,5 @@
|
||||
// Process the predator's effects upon the contents of its belly (i.e digestion/transformation etc)
|
||||
/obj/belly/proc/process_belly(var/times_fired,var/wait) //Passed by controller
|
||||
/obj/belly/proc/process_belly(times_fired, wait) //Passed by controller
|
||||
if((times_fired < next_process) || !contents.len)
|
||||
recent_sound = FALSE
|
||||
return SSBELLIES_IGNORED
|
||||
@@ -11,31 +11,13 @@
|
||||
qdel(src)
|
||||
return SSBELLIES_PROCESSED
|
||||
|
||||
next_process = times_fired + (6 SECONDS/wait) //Set up our next process time.
|
||||
next_process = times_fired + (6 SECONDS / wait) //Set up our next process time.
|
||||
|
||||
var/play_sound //Potential sound to play at the end to avoid code duplication.
|
||||
var/to_update = FALSE //Did anything update worthy happen?
|
||||
|
||||
/////////////////////////// Auto-Emotes ///////////////////////////
|
||||
if(contents.len && next_emote <= times_fired)
|
||||
next_emote = times_fired + round(emote_time/wait,1)
|
||||
var/list/EL = emote_lists[digest_mode]
|
||||
if(LAZYLEN(EL))
|
||||
for(var/mob/living/M in contents)
|
||||
if(M.digestable || digest_mode != DM_DIGEST) // don't give digesty messages to indigestible people
|
||||
to_chat(M,"<span class='notice'>[pick(EL)]</span>")
|
||||
|
||||
///////////////////// Prey Loop Refresh/hack //////////////////////
|
||||
for(var/mob/living/M in contents)
|
||||
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
|
||||
if(isbelly(M.loc)) //sanity check
|
||||
if(world.time > M.next_preyloop) //We don't want it to overlap, but we also want it to replay.
|
||||
if(is_wet && wet_loop) // Is it a fleshy environment, and does the pred have a fleshy heartbeat loop to play?
|
||||
if(!M.client)
|
||||
continue
|
||||
if(M.is_preference_enabled(/datum/client_preference/digestion_noises)) //then we check if the mob has sounds enabled at all
|
||||
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
|
||||
M.playsound_local(get_turf(src),preyloop, 80,0, channel = CHANNEL_PREYLOOP)
|
||||
M.next_preyloop = (world.time + (52 SECONDS))
|
||||
prey_loop()
|
||||
|
||||
/////////////////////////// Sound Selections ///////////////////////////
|
||||
var/sound/prey_digest
|
||||
@@ -61,31 +43,30 @@
|
||||
var/list/touchable_mobs = list()
|
||||
|
||||
///////////////////// Early Non-Mode Handling /////////////////////
|
||||
var/did_an_item = FALSE
|
||||
if(contents.len && next_emote <= times_fired)
|
||||
next_emote = times_fired + round(emote_time/wait,1)
|
||||
var/list/EL = emote_lists[digest_mode]
|
||||
if(LAZYLEN(EL))
|
||||
for(var/mob/living/M in contents)
|
||||
if(M.digestable || digest_mode != DM_DIGEST) // don't give digesty messages to indigestible people
|
||||
to_chat(M, "<span class='notice'>[pick(EL)]</span>")
|
||||
|
||||
var/did_an_item = FALSE // Only do one item per cycle.
|
||||
var/digestion_noise_chance = 0
|
||||
|
||||
for(var/A in touchable_atoms)
|
||||
//Handle stray items
|
||||
if(isitem(A) && !did_an_item)
|
||||
var/obj/item/I = A
|
||||
if(contaminates || istype(I,/obj/item/weapon/card/id))
|
||||
I.gurgle_contaminate(src, contamination_flavor, contamination_color)
|
||||
if(item_digest_mode == IM_HOLD)
|
||||
items_preserved |= I
|
||||
else if(item_digest_mode == IM_DIGEST_FOOD)
|
||||
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I,/obj/item/organ))
|
||||
digest_item(I)
|
||||
else
|
||||
items_preserved |= I
|
||||
if(prob(25)) //Less often than with normal digestion
|
||||
play_sound = pick(pred_digest)
|
||||
else if(item_digest_mode == IM_DIGEST)
|
||||
if(I.digest_stage && I.digest_stage > 0)
|
||||
digest_item(I)
|
||||
else
|
||||
digest_item(I)
|
||||
did_an_item = TRUE
|
||||
did_an_item = handle_digesting_item(A)
|
||||
if(did_an_item)
|
||||
to_update = TRUE
|
||||
if(prob(25)) //Less often than with normal digestion
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
//Less often than with normal digestion
|
||||
if((item_digest_mode == IM_DIGEST_FOOD || item_digest_mode == IM_DIGEST) && prob(25))
|
||||
// This is a little weird, but the point of it is that we don't want to repeat code
|
||||
// but we also want the prob(25) chance to run for -every- item we look at, not just once
|
||||
// More gurgles the better~
|
||||
digestion_noise_chance = 25
|
||||
|
||||
//Handle eaten mobs
|
||||
else if(isliving(A))
|
||||
@@ -105,278 +86,218 @@
|
||||
H.bloodstr.add_reagent("numbenzyme",4)
|
||||
|
||||
//Thickbelly flag
|
||||
if(mode_flags & DM_FLAG_THICKBELLY)
|
||||
if(!(H.muffled))
|
||||
H.muffled = 1
|
||||
if((mode_flags & DM_FLAG_THICKBELLY) && !H.muffled)
|
||||
H.muffled = TRUE
|
||||
|
||||
//Stripping flag
|
||||
if(mode_flags & DM_FLAG_STRIPPING)
|
||||
for(var/slot in slots)
|
||||
var/obj/item/I = H.get_equipped_item(slot = slot)
|
||||
if(I)
|
||||
H.unEquip(I,force = FALSE)
|
||||
if(contaminates || istype(I,/obj/item/weapon/card/id))
|
||||
I.gurgle_contaminate(contents, contamination_flavor, contamination_color)
|
||||
if(item_digest_mode == IM_HOLD)
|
||||
items_preserved |= I
|
||||
else if(item_digest_mode == IM_DIGEST_FOOD)
|
||||
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I,/obj/item/organ))
|
||||
digest_item(I)
|
||||
else
|
||||
items_preserved |= I
|
||||
if(prob(25)) //Less often than with normal digestion
|
||||
if(L && L.client && L.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(L,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
else if(item_digest_mode == IM_DIGEST)
|
||||
digest_item(I)
|
||||
if(prob(25)) //Less often than with normal digestion
|
||||
if(L && L.client && L.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(L,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
if(I && H.unEquip(I, force = FALSE))
|
||||
handle_digesting_item(I)
|
||||
digestion_noise_chance = 25
|
||||
to_update = TRUE
|
||||
break
|
||||
break // Digest off one by one, not all at once
|
||||
|
||||
//get rid of things like blood drops and gibs that end up in there
|
||||
else if(istype(A,/obj/effect/decal/cleanable/))
|
||||
else if(istype(A, /obj/effect/decal/cleanable))
|
||||
qdel(A)
|
||||
|
||||
///////////////////////////// DM_HOLD /////////////////////////////
|
||||
if(digest_mode == DM_HOLD)
|
||||
return SSBELLIES_PROCESSED //Pretty boring, huh
|
||||
//We deliberately do not want any gurgly noises if the belly is in DM_HOLD
|
||||
if(to_update)
|
||||
updateVRPanels()
|
||||
return SSBELLIES_PROCESSED
|
||||
|
||||
//////////////////////////// DM_DIGEST ////////////////////////////
|
||||
else if(digest_mode == DM_DIGEST)
|
||||
|
||||
if(prob(50)) //Was SO OFTEN. AAAA.
|
||||
for(var/mob/M in contents)
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
//Pref protection!
|
||||
if (!M.digestable || M.absorbed)
|
||||
continue
|
||||
|
||||
//Person just died in guts!
|
||||
if(M.stat == DEAD)
|
||||
var/digest_alert_owner = pick(digest_messages_owner)
|
||||
var/digest_alert_prey = pick(digest_messages_prey)
|
||||
var/compensation = M.getOxyLoss() //How much of the prey's damage was caused by passive crit oxyloss to compensate the lost nutrition.
|
||||
|
||||
//Replace placeholder vars
|
||||
digest_alert_owner = replacetext(digest_alert_owner,"%pred",owner)
|
||||
digest_alert_owner = replacetext(digest_alert_owner,"%prey",M)
|
||||
digest_alert_owner = replacetext(digest_alert_owner,"%belly",lowertext(name))
|
||||
|
||||
digest_alert_prey = replacetext(digest_alert_prey,"%pred",owner)
|
||||
digest_alert_prey = replacetext(digest_alert_prey,"%prey",M)
|
||||
digest_alert_prey = replacetext(digest_alert_prey,"%belly",lowertext(name))
|
||||
|
||||
//Send messages
|
||||
to_chat(owner,"<span class='notice'>" + digest_alert_owner + "</span>")
|
||||
to_chat(M,"<span class='notice'>" + digest_alert_prey + "</span>")
|
||||
|
||||
play_sound = pick(pred_death)
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_death)
|
||||
if((mode_flags & DM_FLAG_LEAVEREMAINS) && M.digest_leave_remains)
|
||||
handle_remains_leaving(M)
|
||||
digestion_death(M)
|
||||
if(!ishuman(owner))
|
||||
owner.update_icons()
|
||||
if(compensation == 0) //Slightly sloppy way at making sure certain mobs don't give ZERO nutrition (fish and so on)
|
||||
compensation = 21 //This reads as 20*4.5 due to the calculations afterward, making the backup nutrition value 94.5 per mob. Not op compared to regular prey.
|
||||
if(compensation > 0)
|
||||
if(isrobot(owner))
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
R.cell.charge += 25*compensation
|
||||
else
|
||||
owner.nutrition += (nutrition_percent / 100)*4.5*compensation
|
||||
to_update = TRUE
|
||||
|
||||
continue
|
||||
|
||||
// Deal digestion damage (and feed the pred)
|
||||
var/old_brute = M.getBruteLoss()
|
||||
var/old_burn = M.getFireLoss()
|
||||
M.adjustBruteLoss(digest_brute)
|
||||
M.adjustFireLoss(digest_burn)
|
||||
var/actual_brute = M.getBruteLoss() - old_brute
|
||||
var/actual_burn = M.getFireLoss() - old_burn
|
||||
var/damage_gain = actual_brute + actual_burn
|
||||
|
||||
var/offset = (1 + ((M.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02
|
||||
var/difference = owner.size_multiplier / M.size_multiplier
|
||||
if(isrobot(owner))
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
R.cell.charge += 25*damage_gain
|
||||
if(offset) // If any different than default weight, multiply the % of offset.
|
||||
owner.nutrition += offset*((nutrition_percent / 100)*4.5*(damage_gain)/difference) //4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
|
||||
else
|
||||
owner.nutrition += (nutrition_percent / 100)*4.5*(damage_gain)/difference
|
||||
|
||||
|
||||
//////////////////////////// DM_ABSORB ////////////////////////////
|
||||
else if(digest_mode == DM_ABSORB)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
if(M.absorbable == FALSE)
|
||||
return
|
||||
else
|
||||
if(prob(10)) //Less often than gurgles. People might leave this on forever.
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.absorbed)
|
||||
continue
|
||||
|
||||
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
|
||||
var/oldnutrition = (M.nutrition * 0.05)
|
||||
M.nutrition = (M.nutrition * 0.95)
|
||||
owner.nutrition += oldnutrition
|
||||
else if(M.nutrition < 100) //When they're finally drained.
|
||||
absorb_living(M)
|
||||
to_update = TRUE
|
||||
|
||||
//////////////////////////// DM_UNABSORB ////////////////////////////
|
||||
else if(digest_mode == DM_UNABSORB)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(M.absorbed && owner.nutrition >= 100)
|
||||
M.absorbed = 0
|
||||
to_chat(M,"<span class='notice'>You suddenly feel solid again </span>")
|
||||
to_chat(owner,"<span class='notice'>You feel like a part of you is missing.</span>")
|
||||
owner.nutrition -= 100
|
||||
to_update = TRUE
|
||||
|
||||
//////////////////////////// DM_DRAIN ////////////////////////////
|
||||
else if(digest_mode == DM_DRAIN)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(prob(10)) //Less often than gurgles. People might leave this on forever.
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.nutrition >= 100) //Drain them until there's no nutrients left.
|
||||
var/oldnutrition = (M.nutrition * 0.05)
|
||||
M.nutrition = (M.nutrition * 0.95)
|
||||
owner.nutrition += oldnutrition
|
||||
|
||||
//////////////////////////// DM_SHRINK ////////////////////////////
|
||||
else if(digest_mode == DM_SHRINK)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(prob(10)) //Infinite gurgles!
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.size_multiplier > shrink_grow_size) //Shrink until smol.
|
||||
M.resize(M.size_multiplier-0.01) //Shrink by 1% per tick.
|
||||
|
||||
if(M.nutrition >= 100) //Absorbing bodymass results in nutrition if possible.
|
||||
var/oldnutrition = (M.nutrition * 0.05)
|
||||
M.nutrition = (M.nutrition * 0.95)
|
||||
owner.nutrition += oldnutrition
|
||||
|
||||
//////////////////////////// DM_GROW ////////////////////////////
|
||||
else if(digest_mode == DM_GROW)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(prob(10))
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.size_multiplier < shrink_grow_size) //Grow until large.
|
||||
M.resize(M.size_multiplier+0.01) //Grow by 1% per tick.
|
||||
if(M.nutrition >= 100)
|
||||
owner.nutrition = (owner.nutrition * 0.95)
|
||||
|
||||
//////////////////////////// DM_SIZE_STEAL ////////////////////////////
|
||||
else if(digest_mode == DM_SIZE_STEAL)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(prob(10))
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.size_multiplier > shrink_grow_size && owner.size_multiplier < 2) //Grow until either pred is large or prey is small.
|
||||
owner.resize(owner.size_multiplier+0.01) //Grow by 1% per tick.
|
||||
M.resize(M.size_multiplier-0.01) //Shrink by 1% per tick
|
||||
|
||||
if(M.nutrition >= 100)
|
||||
var/oldnutrition = (M.nutrition * 0.05)
|
||||
M.nutrition = (M.nutrition * 0.95)
|
||||
owner.nutrition += oldnutrition
|
||||
|
||||
///////////////////////////// DM_HEAL /////////////////////////////
|
||||
else if(digest_mode == DM_HEAL)
|
||||
|
||||
if(prob(50)) //Wet heals! The secret is you can leave this on for gurgle noises for fun.
|
||||
for(var/mob/M in contents)
|
||||
if(M && M.client && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
for (var/target in touchable_mobs)
|
||||
var/mob/living/M = target
|
||||
|
||||
if(M.stat == DEAD)
|
||||
continue
|
||||
|
||||
if(owner.nutrition > 90 && (M.health < M.maxHealth))
|
||||
M.adjustBruteLoss(-2.5)
|
||||
M.adjustFireLoss(-2.5)
|
||||
M.adjustToxLoss(-5)
|
||||
M.adjustOxyLoss(-5)
|
||||
M.adjustCloneLoss(-1.25)
|
||||
owner.nutrition -= 2
|
||||
if(M.nutrition <= 400)
|
||||
M.nutrition += 1
|
||||
else if(owner.nutrition > 90 && (M.nutrition <= 400))
|
||||
owner.nutrition -= 1
|
||||
M.nutrition += 1
|
||||
|
||||
/////////////////////////// DM_TRANSFORM ///////////////////////////
|
||||
else if(digest_mode == DM_TRANSFORM)
|
||||
if(digest_mode == DM_TRANSFORM)
|
||||
process_tf(tf_mode, touchable_mobs)
|
||||
|
||||
for(var/target in touchable_mobs)
|
||||
var/mob/living/L = target
|
||||
if(!istype(L))
|
||||
continue
|
||||
switch(digest_mode)
|
||||
if(DM_DIGEST)
|
||||
digestion_noise_chance = 50
|
||||
//Pref protection!
|
||||
if(!L.digestable || L.absorbed)
|
||||
continue
|
||||
|
||||
//Person just died in guts!
|
||||
if(L.stat == DEAD)
|
||||
play_sound = pred_death
|
||||
if(L.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(L, prey_death)
|
||||
handle_digestion_death(L)
|
||||
to_update = TRUE
|
||||
continue
|
||||
|
||||
// Deal digestion damage (and feed the pred)
|
||||
var/old_brute = L.getBruteLoss()
|
||||
var/old_burn = L.getFireLoss()
|
||||
L.adjustBruteLoss(digest_brute)
|
||||
L.adjustFireLoss(digest_burn)
|
||||
var/actual_brute = L.getBruteLoss() - old_brute
|
||||
var/actual_burn = L.getFireLoss() - old_burn
|
||||
var/damage_gain = actual_brute + actual_burn
|
||||
|
||||
var/offset = (1 + ((L.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02
|
||||
var/difference = owner.size_multiplier / L.size_multiplier
|
||||
if(isrobot(owner))
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
R.cell.charge += 25 * damage_gain
|
||||
if(offset) // If any different than default weight, multiply the % of offset.
|
||||
owner.nutrition += offset*((nutrition_percent / 100) * 4.5 * (damage_gain) / difference) //4.5 nutrition points per health point. Normal same size 100+100 health prey with average weight would give 900 points if the digestion was instant. With all the size/weight offset taxes plus over time oxyloss+hunger taxes deducted with non-instant digestion, this should be enough to not leave the pred starved.
|
||||
else
|
||||
owner.nutrition += (nutrition_percent / 100) * 4.5 * (damage_gain) / difference
|
||||
if(DM_ABSORB)
|
||||
if(!L.absorbable || L.absorbed)
|
||||
continue
|
||||
digestion_noise_chance = 10
|
||||
steal_nutrition(L)
|
||||
if(L.nutrition < 100)
|
||||
absorb_living(L)
|
||||
to_update = TRUE
|
||||
if(DM_UNABSORB)
|
||||
if(L.absorbed && owner.nutrition >= 100)
|
||||
L.absorbed = FALSE
|
||||
to_chat(L, "<span class='notice'>You suddenly feel solid again.</span>")
|
||||
to_chat(owner,"<span class='notice'>You feel like a part of you is missing.</span>")
|
||||
owner.nutrition -= 100
|
||||
to_update = TRUE
|
||||
if(DM_DRAIN)
|
||||
digestion_noise_chance = 10
|
||||
steal_nutrition(L)
|
||||
if(DM_SHRINK)
|
||||
digestion_noise_chance = 10
|
||||
if(L.size_multiplier > shrink_grow_size)
|
||||
L.resize(L.size_multiplier - 0.01) // Shrink by 1% per tick
|
||||
steal_nutrition(L)
|
||||
if(DM_GROW)
|
||||
digestion_noise_chance = 10
|
||||
if(L.size_multiplier < shrink_grow_size)
|
||||
L.resize(L.size_multiplier - 0.01) // Grow by 1% per tick
|
||||
if(DM_SIZE_STEAL)
|
||||
digestion_noise_chance = 10
|
||||
if(L.size_multiplier > shrink_grow_size && owner.size_multiplier < 2) //Grow until either pred is large or prey is small.
|
||||
owner.resize(owner.size_multiplier+0.01) //Grow by 1% per tick.
|
||||
L.resize(L.size_multiplier-0.01) //Shrink by 1% per tick
|
||||
steal_nutrition(L)
|
||||
if(DM_HEAL)
|
||||
digestion_noise_chance = 50 //Wet heals! The secret is you can leave this on for gurgle noises for fun.
|
||||
if(L.stat == DEAD)
|
||||
continue // Can't heal the dead with healbelly
|
||||
if(owner.nutrition > 90 && (L.health < L.maxHealth))
|
||||
L.adjustBruteLoss(-2.5)
|
||||
L.adjustFireLoss(-2.5)
|
||||
L.adjustToxLoss(-5)
|
||||
L.adjustOxyLoss(-5)
|
||||
L.adjustCloneLoss(-1.25)
|
||||
owner.nutrition -= 2
|
||||
if(L.nutrition <= 400)
|
||||
L.nutrition += 1
|
||||
else if(owner.nutrition > 90 && (L.nutrition <= 400))
|
||||
owner.nutrition -= 1
|
||||
L.nutrition += 1
|
||||
|
||||
/////////////////////////// Make any noise ///////////////////////////
|
||||
if(digestion_noise_chance && prob(digestion_noise_chance))
|
||||
for(var/mob/M in contents)
|
||||
if(M && M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
SEND_SOUND(M, prey_digest)
|
||||
play_sound = pred_digest
|
||||
|
||||
if(play_sound)
|
||||
LAZYCLEARLIST(hearing_mobs)
|
||||
for(var/mob/M in hearers(VORE_SOUND_RANGE, owner))
|
||||
if(!M.client || !(M.is_preference_enabled(/datum/client_preference/digestion_noises)))
|
||||
for(var/mob/M in hearers(VORE_SOUND_RANGE, owner)) //so we don't fill the whole room with the sound effect
|
||||
if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
continue
|
||||
LAZYADD(hearing_mobs, M)
|
||||
for(var/mob/M in hearing_mobs) //so we don't fill the whole room with the sound effect
|
||||
if(M && M.client && (isturf(M.loc) || (M.loc != src.contents))) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
|
||||
if(isturf(M.loc) || (M.loc != src)) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
|
||||
if(fancy_vore)
|
||||
M.playsound_local(owner.loc, play_sound, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
|
||||
else
|
||||
M.playsound_local(owner.loc, play_sound, vol = 100, vary = 1, falloff = VORE_SOUND_FALLOFF)
|
||||
//these are all external sound triggers now, so it's ok.
|
||||
|
||||
if(to_update)
|
||||
for(var/mob/living/M in contents)
|
||||
if(M.client)
|
||||
M.updateVRPanel()
|
||||
if(owner.client)
|
||||
owner.updateVRPanel()
|
||||
updateVRPanels()
|
||||
|
||||
return SSBELLIES_PROCESSED
|
||||
|
||||
/obj/belly/proc/prey_loop()
|
||||
for(var/mob/living/M in contents)
|
||||
//We don't bother executing any other code if the prey doesn't want to hear the noises.
|
||||
if(!M.is_preference_enabled(/datum/client_preference/digestion_noises))
|
||||
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case, because byond is whack and you can't trust it
|
||||
continue
|
||||
|
||||
// We don't want the sounds to overlap, but we do want them to steadily replay.
|
||||
// We also don't want the sounds to play if the pred hasn't marked this belly as fleshy, or doesn't
|
||||
// have the right sounds to play.
|
||||
if(isbelly(M.loc) && is_wet && wet_loop && (world.time > M.next_preyloop))
|
||||
M.stop_sound_channel(CHANNEL_PREYLOOP)
|
||||
var/sound/preyloop = sound('sound/vore/sunesound/prey/loop.ogg')
|
||||
M.playsound_local(get_turf(src), preyloop, 80, 0, channel = CHANNEL_PREYLOOP)
|
||||
M.next_preyloop = (world.time + (52 SECONDS))
|
||||
|
||||
/obj/belly/proc/handle_digesting_item(obj/item/I)
|
||||
var/did_an_item = FALSE
|
||||
// We always contaminate IDs.
|
||||
if(contaminates || istype(I, /obj/item/weapon/card/id))
|
||||
I.gurgle_contaminate(src, contamination_flavor, contamination_color)
|
||||
|
||||
switch(item_digest_mode)
|
||||
if(IM_HOLD)
|
||||
items_preserved |= I
|
||||
if(IM_DIGEST_FOOD)
|
||||
if(istype(I,/obj/item/weapon/reagent_containers/food) || istype(I, /obj/item/organ))
|
||||
did_an_item = digest_item(I)
|
||||
else
|
||||
items_preserved |= I
|
||||
if(IM_DIGEST)
|
||||
did_an_item = digest_item(I)
|
||||
return did_an_item
|
||||
|
||||
/obj/belly/proc/handle_digestion_death(mob/living/M)
|
||||
var/digest_alert_owner = pick(digest_messages_owner)
|
||||
var/digest_alert_prey = pick(digest_messages_prey)
|
||||
var/compensation = M.getOxyLoss() //How much of the prey's damage was caused by passive crit oxyloss to compensate the lost nutrition.
|
||||
|
||||
//Replace placeholder vars
|
||||
digest_alert_owner = replacetext(digest_alert_owner, "%pred", owner)
|
||||
digest_alert_owner = replacetext(digest_alert_owner, "%prey", M)
|
||||
digest_alert_owner = replacetext(digest_alert_owner, "%belly", lowertext(name))
|
||||
|
||||
digest_alert_prey = replacetext(digest_alert_prey, "%pred", owner)
|
||||
digest_alert_prey = replacetext(digest_alert_prey, "%prey", M)
|
||||
digest_alert_prey = replacetext(digest_alert_prey, "%belly", lowertext(name))
|
||||
|
||||
//Send messages
|
||||
to_chat(owner, "<span class='notice'>[digest_alert_owner]</span>")
|
||||
to_chat(M, "<span class='notice'>[digest_alert_prey]</span>")
|
||||
|
||||
if((mode_flags & DM_FLAG_LEAVEREMAINS) && M.digest_leave_remains)
|
||||
handle_remains_leaving(M)
|
||||
digestion_death(M)
|
||||
if(!ishuman(owner))
|
||||
owner.update_icons()
|
||||
if(compensation == 0) //Slightly sloppy way at making sure certain mobs don't give ZERO nutrition (fish and so on)
|
||||
compensation = 21 //This reads as 20*4.5 due to the calculations afterward, making the backup nutrition value 94.5 per mob. Not op compared to regular prey.
|
||||
if(compensation > 0)
|
||||
if(isrobot(owner))
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
R.cell.charge += 25*compensation
|
||||
else
|
||||
owner.nutrition += (nutrition_percent / 100)*4.5*compensation
|
||||
|
||||
/obj/belly/proc/steal_nutrition(mob/living/L)
|
||||
if(L.nutrition >= 100)
|
||||
var/oldnutrition = (L.nutrition * 0.05)
|
||||
L.nutrition = (L.nutrition * 0.95)
|
||||
owner.nutrition += oldnutrition
|
||||
|
||||
/obj/belly/proc/updateVRPanels()
|
||||
for(var/mob/living/M in contents)
|
||||
if(M.client)
|
||||
M.updateVRPanel()
|
||||
if(owner.client)
|
||||
owner.updateVRPanel()
|
||||
@@ -22,7 +22,7 @@ var/list/gurgled_overlays = list(
|
||||
var/cleandesc
|
||||
var/gurgled_color
|
||||
|
||||
/obj/item/proc/gurgle_contaminate(var/atom/movable/item_storage = null, var/contamination_flavor = "Generic", var/contamination_color = "green")
|
||||
/obj/item/proc/gurgle_contaminate(atom/movable/item_storage = null, contamination_flavor = "Generic", contamination_color = "green")
|
||||
if(!can_gurgle())
|
||||
return FALSE
|
||||
|
||||
@@ -65,28 +65,16 @@ var/list/gurgled_overlays = list(
|
||||
if(gurgled)
|
||||
decontaminate()
|
||||
|
||||
/obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob) //Wash the soggy item before it can interact with the sink.
|
||||
if(O.gurgled)
|
||||
var/turf/location = user.loc
|
||||
if(!isturf(location)) return
|
||||
|
||||
var/obj/item/I = O
|
||||
if(!I || !istype(I,/obj/item)) return
|
||||
|
||||
to_chat(usr, "<span class='notice'>You start washing \the [I].</span>")
|
||||
/obj/structure/sink/attackby(obj/item/I, mob/user) //Wash the soggy item before it can interact with the sink.
|
||||
if(istype(I) && I.gurgled)
|
||||
to_chat(user, "<span class='notice'>You start washing [I].</span>")
|
||||
|
||||
busy = TRUE
|
||||
sleep(40)
|
||||
if(do_after(user, 40, src))
|
||||
I.clean_blood()
|
||||
user.visible_message("<span class='notice'>[user] washes [I] using [src].</span>",
|
||||
"<span class='notice'>You wash [I] using [src].</span>")
|
||||
busy = FALSE
|
||||
|
||||
if(user.loc != location) return //User has moved
|
||||
if(!I) return //Item's been destroyed while washing
|
||||
if(user.get_active_hand() != I) return //Person has switched hands or the item in their hands
|
||||
|
||||
O.clean_blood()
|
||||
user.visible_message( \
|
||||
"<span class='notice'>[user] washes \a [I] using \the [src].</span>", \
|
||||
"<span class='notice'>You wash \a [I] using \the [src].</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
//return non-negative integer: Amount of nutrition/charge gained (scaled to nutrition, other end can multiply for charge scale).
|
||||
|
||||
// Ye default implementation.
|
||||
/obj/item/proc/digest_act(var/atom/movable/item_storage = null)
|
||||
if(istype(item_storage,/obj/item/device/dogborg/sleeper))
|
||||
/obj/item/proc/digest_act(atom/movable/item_storage = null)
|
||||
if(istype(item_storage, /obj/item/device/dogborg/sleeper))
|
||||
for(var/obj/item/O in contents)
|
||||
if(istype(O,/obj/item/weapon/storage/internal)) //Dump contents from dummy pockets.
|
||||
if(istype(O, /obj/item/weapon/storage/internal)) //Dump contents from dummy pockets.
|
||||
for(var/obj/item/SO in O)
|
||||
if(item_storage)
|
||||
SO.forceMove(item_storage)
|
||||
@@ -15,12 +15,15 @@
|
||||
O.forceMove(item_storage)
|
||||
qdel(src)
|
||||
return w_class
|
||||
|
||||
var/g_damage = 1
|
||||
if(digest_stage == null)
|
||||
digest_stage = w_class
|
||||
|
||||
if(isbelly(item_storage))
|
||||
var/obj/belly/B = item_storage
|
||||
g_damage = 0.25 * (B.digest_brute + B.digest_burn)
|
||||
|
||||
if(digest_stage > 0)
|
||||
if(g_damage > digest_stage)
|
||||
g_damage = digest_stage
|
||||
@@ -65,16 +68,16 @@
|
||||
// Some special treatment
|
||||
/////////////
|
||||
//PDAs need to lose their ID to not take it with them, so we can get a digested ID
|
||||
/obj/item/device/pda/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/device/pda/digest_act(atom/movable/item_storage = null)
|
||||
if(id)
|
||||
if(istype(item_storage,/obj/item/device/dogborg/sleeper) || (!isnull(digest_stage) && digest_stage <= 0))
|
||||
if(istype(item_storage, /obj/item/device/dogborg/sleeper) || (!isnull(digest_stage) && digest_stage <= 0))
|
||||
id = null
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/card/id
|
||||
var/lost_access = list()
|
||||
|
||||
/obj/item/weapon/card/id/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/weapon/card/id/digest_act(atom/movable/item_storage = null)
|
||||
desc = "A partially digested card that has seen better days. The damage appears to be only cosmetic, but the access codes need to be reprogrammed at the HoP office."
|
||||
icon = 'icons/obj/card_vr.dmi'
|
||||
icon_state = "[initial(icon_state)]_digested"
|
||||
@@ -83,7 +86,7 @@
|
||||
access = list() // Then lose it
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/weapon/reagent_containers/food/digest_act(atom/movable/item_storage = null)
|
||||
if(isbelly(item_storage))
|
||||
var/obj/belly/B = item_storage
|
||||
if(ishuman(B.owner))
|
||||
@@ -96,7 +99,7 @@
|
||||
return w_class
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/holder/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/weapon/holder/digest_act(atom/movable/item_storage = null)
|
||||
for(var/mob/living/M in contents)
|
||||
if(item_storage)
|
||||
M.forceMove(item_storage)
|
||||
@@ -104,7 +107,7 @@
|
||||
|
||||
. = ..()
|
||||
|
||||
/obj/item/organ/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/organ/digest_act(atom/movable/item_storage = null)
|
||||
if((. = ..()))
|
||||
if(isbelly(item_storage))
|
||||
var/obj/belly/B = item_storage
|
||||
@@ -112,7 +115,7 @@
|
||||
else
|
||||
. += 30 //Organs give a little more
|
||||
|
||||
/obj/item/weapon/storage/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/weapon/storage/digest_act(atom/movable/item_storage = null)
|
||||
for(var/obj/item/I in contents)
|
||||
I.screen_loc = null
|
||||
|
||||
@@ -121,7 +124,7 @@
|
||||
/////////////
|
||||
// Some more complicated stuff
|
||||
/////////////
|
||||
/obj/item/device/mmi/digital/posibrain/digest_act(var/atom/movable/item_storage = null)
|
||||
/obj/item/device/mmi/digital/posibrain/digest_act(atom/movable/item_storage = null)
|
||||
//Replace this with a VORE setting so all types of posibrains can/can't be digested on a whim
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -1,72 +1,62 @@
|
||||
/datum/species
|
||||
var/skull_type = /obj/item/weapon/digestion_remains/skull
|
||||
/datum/species/tajaran
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/tajaran
|
||||
/datum/species/unathi
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/unathi
|
||||
/datum/species/skrell
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/skrell
|
||||
/datum/species/spider
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/vasilissan
|
||||
/datum/species/akula
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/akula
|
||||
/datum/species/harpy
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/rapala
|
||||
/datum/species/vulpkanin
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/vulpkanin
|
||||
/datum/species/sergal
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/sergal
|
||||
/datum/species/hi_zorren
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/zorren
|
||||
/datum/species/nevrean
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/nevrean
|
||||
/datum/species/teshari
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/teshari
|
||||
/datum/species/vox
|
||||
skull_type = /obj/item/weapon/digestion_remains/skull/vox
|
||||
|
||||
/obj/belly/proc/handle_remains_leaving(var/mob/living/M)
|
||||
|
||||
if(istype(M,/mob/living/carbon/human)) //Are we even humanoid?
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if((H.species.name in remainless_species) || H.isSynthetic()) //Don't leave anything if there is nothing to leave
|
||||
return
|
||||
|
||||
else
|
||||
var/bones_amount = rand(2,3) //some random variety in amount of bones left
|
||||
|
||||
if(prob(20)) //ribcage surviving whole is some luck
|
||||
new /obj/item/weapon/digestion_remains/ribcage(src,owner)
|
||||
bones_amount--
|
||||
|
||||
while(bones_amount) //throw in the rest
|
||||
new /obj/item/weapon/digestion_remains(src,owner)
|
||||
bones_amount--
|
||||
|
||||
var/skull_amount = 1
|
||||
switch(H.species.name) //oh boy here we go, finding us a right skull
|
||||
if(SPECIES_HUMAN)
|
||||
new /obj/item/weapon/digestion_remains/skull(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_TAJ)
|
||||
new /obj/item/weapon/digestion_remains/skull/tajaran(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_UNATHI)
|
||||
new /obj/item/weapon/digestion_remains/skull/unathi(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_SKRELL)
|
||||
new /obj/item/weapon/digestion_remains/skull/skrell(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_VASILISSAN)
|
||||
new /obj/item/weapon/digestion_remains/skull/vasilissan(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_AKULA)
|
||||
new /obj/item/weapon/digestion_remains/skull/akula(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_RAPALA)
|
||||
new /obj/item/weapon/digestion_remains/skull/rapala(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_VULPKANIN)
|
||||
new /obj/item/weapon/digestion_remains/skull/vulpkanin(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_SERGAL)
|
||||
new /obj/item/weapon/digestion_remains/skull/sergal(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_ZORREN_HIGH)
|
||||
new /obj/item/weapon/digestion_remains/skull/zorren(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_NEVREAN)
|
||||
new /obj/item/weapon/digestion_remains/skull/nevrean(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_TESHARI)
|
||||
new /obj/item/weapon/digestion_remains/skull/teshari(src,owner)
|
||||
skull_amount--
|
||||
if(SPECIES_VOX)
|
||||
new /obj/item/weapon/digestion_remains/skull/vox(src,owner)
|
||||
skull_amount--
|
||||
if(skull_amount && H.species.selects_bodytype) //We still haven't found correct skull...
|
||||
if(H.species.base_species == SPECIES_HUMAN)
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
|
||||
else
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown/anthro(src,owner)
|
||||
else if(skull_amount) //Something entirely different...
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
|
||||
else
|
||||
if(!ishuman(M)) //Are we even humanoid?
|
||||
return
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if((H.species.name in remainless_species) || H.isSynthetic()) //Don't leave anything if there is nothing to leave
|
||||
return
|
||||
|
||||
var/bones_amount = rand(2,3) //some random variety in amount of bones left
|
||||
if(prob(20)) //ribcage surviving whole is some luck
|
||||
new /obj/item/weapon/digestion_remains/ribcage(src,owner)
|
||||
bones_amount--
|
||||
|
||||
while(bones_amount) //throw in the rest
|
||||
new /obj/item/weapon/digestion_remains(src,owner)
|
||||
bones_amount--
|
||||
|
||||
var/skull_amount = 1
|
||||
if(H.species.skull_type)
|
||||
new H.species.skull_type(src, owner)
|
||||
skull_amount--
|
||||
|
||||
if(skull_amount && H.species.selects_bodytype)
|
||||
// We still haven't found correct skull...
|
||||
if(H.species.base_species == SPECIES_HUMAN)
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
|
||||
else
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown/anthro(src,owner)
|
||||
else if(skull_amount)
|
||||
// Something entirely different...
|
||||
new /obj/item/weapon/digestion_remains/skull/unknown(src,owner)
|
||||
|
||||
|
||||
/obj/item/weapon/digestion_remains
|
||||
name = "bone"
|
||||
@@ -80,7 +70,7 @@
|
||||
var/pred_ckey
|
||||
var/pred_name
|
||||
|
||||
/obj/item/weapon/digestion_remains/New(var/newloc,var/mob/living/pred)
|
||||
/obj/item/weapon/digestion_remains/New(newloc, mob/living/pred)
|
||||
..(newloc)
|
||||
pred_ckey = pred.ckey
|
||||
pred_name = pred.name
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
var/metabolism = 0.0015
|
||||
var/vore_taste = null // What the character tastes like
|
||||
var/no_vore = FALSE // If the character/mob can vore.
|
||||
var/openpanel = FALSE // Is the vore panel open?
|
||||
var/noisy = FALSE // Toggle audible hunger.
|
||||
var/absorbing_prey = 0 // Determines if the person is using the succubus drain or not. See station_special_abilities_vr.
|
||||
var/drain_finalized = 0 // Determines if the succubus drain will be KO'd/absorbed. Can be toggled on at any time.
|
||||
@@ -41,6 +40,7 @@
|
||||
M.verbs += /mob/living/proc/switch_scaling
|
||||
if(M.no_vore) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
|
||||
return TRUE
|
||||
M.vorePanel = new
|
||||
M.verbs += /mob/living/proc/insidePanel
|
||||
|
||||
//Tries to load prefs if a client is present otherwise gives freebie stomach
|
||||
@@ -88,26 +88,25 @@
|
||||
//
|
||||
// Handle being clicked, perhaps with something to devour
|
||||
//
|
||||
/mob/living/proc/vore_attackby(obj/item/I,mob/user)
|
||||
/mob/living/proc/vore_attackby(obj/item/I, mob/user)
|
||||
//Handle case: /obj/item/weapon/grab
|
||||
if(istype(I,/obj/item/weapon/grab))
|
||||
if(istype(I, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = I
|
||||
|
||||
//Has to be aggressive grab, has to be living click-er and non-silicon grabbed
|
||||
if((G.state >= GRAB_AGGRESSIVE) && (isliving(user) && !issilicon(G.affecting)))
|
||||
|
||||
if(G.state >= GRAB_AGGRESSIVE && (isliving(user) && !issilicon(G.affecting)))
|
||||
var/mob/living/attacker = user // Typecast to living
|
||||
|
||||
// src is the mob clicked on and attempted predator
|
||||
|
||||
///// If user clicked on themselves
|
||||
if((src == G.assailant) && (is_vore_predator(src)))
|
||||
if(!(G.affecting.devourable))
|
||||
if(src == G.assailant && is_vore_predator(src))
|
||||
if(!G.affecting.devourable)
|
||||
to_chat(user, "<span class='notice'>They aren't able to be devoured.</span>")
|
||||
log_and_message_admins("[key_name(src)] ([src.real_name]) attempted to devour [key_name(G.affecting)] ([G.affecting.real_name]) against their prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
|
||||
|
||||
log_and_message_admins("[key_name_admin(src)] attempted to devour [key_name_admin(G.affecting)] against their prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
|
||||
return FALSE
|
||||
if(src.feed_grabbed_to_self(src, G.affecting))
|
||||
|
||||
if(feed_grabbed_to_self(src, G.affecting))
|
||||
qdel(G)
|
||||
return TRUE
|
||||
else
|
||||
@@ -115,57 +114,62 @@
|
||||
|
||||
///// If user clicked on their grabbed target
|
||||
else if((src == G.affecting) && (attacker.a_intent == I_GRAB) && (attacker.zone_sel.selecting == BP_TORSO) && (is_vore_predator(G.affecting)))
|
||||
if(!(G.affecting.feeding))
|
||||
if(!G.affecting.feeding)
|
||||
to_chat(user, "<span class='notice'>[G.affecting] isn't willing to be fed.</span>")
|
||||
log_and_message_admins("[key_name(src)] ([src.real_name]) attempted to feed themselves to [key_name(G.affecting)] ([G.affecting.real_name]) against their prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
|
||||
log_and_message_admins("[key_name_admin(src)] attempted to feed themselves to [key_name_admin(G.affecting)] against their prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
|
||||
return FALSE
|
||||
if (attacker.feed_self_to_grabbed(attacker, G.affecting))
|
||||
|
||||
if(attacker.feed_self_to_grabbed(attacker, G.affecting))
|
||||
qdel(G)
|
||||
return TRUE
|
||||
else
|
||||
log_debug("[attacker] attempted to feed [user] to [G.affecting] ([G.affecting.type]) but it failed.")
|
||||
log_debug("[attacker] attempted to feed [user] to [G.affecting] ([G.affecting ? G.affecting.type : "null"]) but it failed.")
|
||||
|
||||
///// If user clicked on anyone else but their grabbed target
|
||||
else if((src != G.affecting) && (src != G.assailant) && (is_vore_predator(src)))
|
||||
if(!(src.feeding))
|
||||
if(!feeding)
|
||||
to_chat(user, "<span class='notice'>[src] isn't willing to be fed.</span>")
|
||||
log_and_message_admins("[key_name(attacker)] ([attacker.real_name]) attempted to feed [key_name(G.affecting)] ([G.affecting.real_name]) to [key_name(src)] ([src.real_name]) against predator's prefs ([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
|
||||
log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against predator's prefs ([src ? ADMIN_JMP(src) : "null"])")
|
||||
return FALSE
|
||||
if(!(G.affecting.devourable))
|
||||
to_chat(user, "<span class='notice'>[G.affecting] isn't able to be devoured.</span>")
|
||||
log_and_message_admins("[key_name(attacker)] ([attacker.real_name]) attempted to feed [key_name(G.affecting)] ([G.affecting.real_name]) to [key_name(src)] ([src.real_name]) against prey's prefs ([G.affecting ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[G.affecting.x];Y=[G.affecting.y];Z=[G.affecting.z]'>JMP</a>" : "null"])")
|
||||
log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against prey's prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])")
|
||||
return FALSE
|
||||
|
||||
if (attacker.feed_grabbed_to_other(attacker, G.affecting, src))
|
||||
if(attacker.feed_grabbed_to_other(attacker, G.affecting, src))
|
||||
qdel(G)
|
||||
return TRUE
|
||||
else
|
||||
log_debug("[attacker] attempted to feed [G.affecting] to [src] ([src.type]) but it failed.")
|
||||
log_debug("[attacker] attempted to feed [G.affecting] to [src] ([type]) but it failed.")
|
||||
|
||||
//Handle case: /obj/item/weapon/holder
|
||||
else if(istype(I,/obj/item/weapon/holder))
|
||||
else if(istype(I, /obj/item/weapon/holder))
|
||||
var/obj/item/weapon/holder/H = I
|
||||
|
||||
if(!isliving(user)) return FALSE // return FALSE to continue upper procs
|
||||
if(!isliving(user))
|
||||
return FALSE // return FALSE to continue upper procs
|
||||
|
||||
var/mob/living/attacker = user // Typecast to living
|
||||
|
||||
if (is_vore_predator(src))
|
||||
for (var/mob/living/M in H.contents)
|
||||
if (attacker.eat_held_mob(attacker, M, src))
|
||||
if (H.held_mob == M)
|
||||
if(is_vore_predator(src))
|
||||
for(var/mob/living/M in H.contents)
|
||||
if(attacker.eat_held_mob(attacker, M, src))
|
||||
if(H.held_mob == M)
|
||||
H.held_mob = null
|
||||
return TRUE //return TRUE to exit upper procs
|
||||
else
|
||||
log_debug("[attacker] attempted to feed [H.contents] to [src] ([src.type]) but it failed.")
|
||||
log_debug("[attacker] attempted to feed [H.contents] to [src] ([type]) but it failed.")
|
||||
|
||||
//Handle case: /obj/item/device/radio/beacon
|
||||
else if(istype(I,/obj/item/device/radio/beacon))
|
||||
var/confirm = alert(user, "[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]", "Confirmation", "Yes!", "Cancel")
|
||||
var/confirm = alert(user,
|
||||
"[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]",
|
||||
"Confirmation",
|
||||
"Yes!", "Cancel")
|
||||
if(confirm == "Yes!")
|
||||
var/obj/belly/B = input("Which belly?","Select A Belly") as null|anything in vore_organs
|
||||
var/obj/belly/B = input("Which belly?", "Select A Belly") as null|anything in vore_organs
|
||||
if(!istype(B))
|
||||
return TRUE
|
||||
visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [lowertext(B.name)]!</span>","<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
|
||||
visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [lowertext(B.name)]!</span>",
|
||||
"<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
|
||||
if(do_after(user,30,src))
|
||||
user.drop_item()
|
||||
I.forceMove(B)
|
||||
@@ -179,7 +183,6 @@
|
||||
// Our custom resist catches for /mob/living
|
||||
//
|
||||
/mob/living/proc/vore_process_resist()
|
||||
|
||||
//Are we resisting from inside a belly?
|
||||
if(isbelly(loc))
|
||||
var/obj/belly/B = loc
|
||||
@@ -187,7 +190,6 @@
|
||||
return TRUE //resist() on living does this TRUE thing.
|
||||
|
||||
//Other overridden resists go here
|
||||
|
||||
return FALSE
|
||||
|
||||
//
|
||||
@@ -310,13 +312,12 @@
|
||||
if(suit.hides_bulges)
|
||||
return FALSE
|
||||
|
||||
|
||||
return ..()
|
||||
|
||||
//
|
||||
// Clearly super important. Obviously.
|
||||
//
|
||||
/mob/living/proc/lick(var/mob/living/tasted in living_mobs(1))
|
||||
/mob/living/proc/lick(mob/living/tasted in living_mobs(1))
|
||||
set name = "Lick"
|
||||
set category = "IC"
|
||||
set desc = "Lick someone nearby!"
|
||||
@@ -402,11 +403,11 @@
|
||||
//
|
||||
// Eating procs depending on who clicked what
|
||||
//
|
||||
/mob/living/proc/feed_grabbed_to_self(var/mob/living/user, var/mob/living/prey)
|
||||
/mob/living/proc/feed_grabbed_to_self(mob/living/user, mob/living/prey)
|
||||
var/belly = user.vore_selected
|
||||
return perform_the_nom(user, prey, user, belly)
|
||||
|
||||
/mob/living/proc/eat_held_mob(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
|
||||
/mob/living/proc/eat_held_mob(mob/living/user, mob/living/prey, mob/living/pred)
|
||||
var/belly
|
||||
if(user != pred)
|
||||
belly = input("Choose Belly") in pred.vore_organs
|
||||
@@ -414,18 +415,18 @@
|
||||
belly = pred.vore_selected
|
||||
return perform_the_nom(user, prey, pred, belly)
|
||||
|
||||
/mob/living/proc/feed_self_to_grabbed(var/mob/living/user, var/mob/living/pred)
|
||||
/mob/living/proc/feed_self_to_grabbed(mob/living/user, mob/living/pred)
|
||||
var/belly = input("Choose Belly") in pred.vore_organs
|
||||
return perform_the_nom(user, user, pred, belly)
|
||||
|
||||
/mob/living/proc/feed_grabbed_to_other(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
|
||||
/mob/living/proc/feed_grabbed_to_other(mob/living/user, mob/living/prey, mob/living/pred)
|
||||
var/belly = input("Choose Belly") in pred.vore_organs
|
||||
return perform_the_nom(user, prey, pred, belly)
|
||||
|
||||
//
|
||||
// Master vore proc that actually does vore procedures
|
||||
//
|
||||
/mob/living/proc/perform_the_nom(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/obj/belly/belly, var/delay)
|
||||
/mob/living/proc/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay)
|
||||
//Sanity
|
||||
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs))
|
||||
log_debug("[user] attempted to feed [prey] to [pred], via [belly ? lowertext(belly.name) : "*null*"] but it went wrong.")
|
||||
@@ -444,11 +445,11 @@
|
||||
|
||||
// Prepare messages
|
||||
if(user == pred) //Feeding someone to yourself
|
||||
attempt_msg = text("<span class='warning'>[] is attempting to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
|
||||
success_msg = text("<span class='warning'>[] manages to [] [] into their []!</span>",pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
|
||||
attempt_msg = "<span class='warning'>[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
|
||||
success_msg = "<span class='warning'>[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
|
||||
else //Feeding someone to another person
|
||||
attempt_msg = text("<span class='warning'>[] is attempting to make [] [] [] into their []!</span>",user,pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
|
||||
success_msg = text("<span class='warning'>[] manages to make [] [] [] into their []!</span>",user,pred,lowertext(belly.vore_verb),prey,lowertext(belly.name))
|
||||
attempt_msg = "<span class='warning'>[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
|
||||
success_msg = "<span class='warning'>[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!</span>"
|
||||
|
||||
// Announce that we start the attempt!
|
||||
user.visible_message(attempt_msg)
|
||||
@@ -477,10 +478,10 @@
|
||||
to_chat(belly.owner, "<span class='notice'>[prey] tastes of [prey.get_taste_message(FALSE)].</span>")
|
||||
|
||||
// Inform Admins
|
||||
if (pred == user)
|
||||
add_attack_logs(pred,prey,"Eaten via [belly.name]")
|
||||
if(pred == user)
|
||||
add_attack_logs(pred, prey, "Eaten via [belly.name]")
|
||||
else
|
||||
add_attack_logs(user,pred,"Forced to eat [key_name(prey)]")
|
||||
add_attack_logs(user, pred, "Forced to eat [key_name(prey)]")
|
||||
return TRUE
|
||||
|
||||
//
|
||||
@@ -522,7 +523,7 @@
|
||||
to_chat(src,"<font color='red'>You're pinned back underfoot!</font>")
|
||||
to_chat(H,"<font color='blue'>You pin the escapee back underfoot!</font>")
|
||||
return
|
||||
if(src.loc != C)
|
||||
if(loc != C)
|
||||
return
|
||||
sleep(1)
|
||||
|
||||
@@ -538,7 +539,7 @@
|
||||
to_chat(src,"<font color='red'>You're pinned underfoot!</font>")
|
||||
to_chat(H,"<font color='blue'>You pin the escapee underfoot!</font>")
|
||||
return
|
||||
if(src.loc != C)
|
||||
if(loc != C)
|
||||
return
|
||||
sleep(1)
|
||||
to_chat(src,"<font color='blue'>You manage to escape \the [C]!</font>")
|
||||
@@ -599,7 +600,7 @@
|
||||
if(is_type_in_list(I,edible_trash) | adminbus_trash)
|
||||
if(I.hidden_uplink)
|
||||
to_chat(src, "<span class='warning'>You really should not be eating this.</span>")
|
||||
message_admins("[key_name(src)] has attempted to ingest an uplink item. ([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
|
||||
message_admins("[key_name(src)] has attempted to ingest an uplink item. ([src ? ADMIN_JMP(src) : "null"])")
|
||||
return
|
||||
if(istype(I,/obj/item/device/pda))
|
||||
var/obj/item/device/pda/P = I
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
playsound('sound/effects/stealthoff.ogg',50,0)
|
||||
bellied.forceMove(get_turf(src))
|
||||
bellied.Weaken(2)
|
||||
bellied.visible_message("[bellied] flops out of \the [src].","You flop out of \the [src].","You hear a thud.")
|
||||
bellied.visible_message("[bellied] flops out of [src].","You flop out of [src].","You hear a thud.")
|
||||
bellied = null
|
||||
|
||||
desc = "[initial(desc)]"
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
//Already full
|
||||
if (hologram.bellied)
|
||||
var/choice = alert("You can only contain one person. [hologram.bellied] is in you.","Already Full","Drop Mob","Cancel")
|
||||
var/choice = alert("You can only contain one person. [hologram.bellied] is in you.", "Already Full", "Drop Mob", "Cancel")
|
||||
if(choice == "Drop Mob")
|
||||
hologram.drop_prey()
|
||||
return
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
/mob/living/AIShiftClick(var/mob/user) //Shift-click as AI overridden on mobs to examine.
|
||||
if(user.client)
|
||||
src.examine(user)
|
||||
examine(user)
|
||||
return
|
||||
|
||||
//This can go here with all the references.
|
||||
|
||||
@@ -6,21 +6,22 @@
|
||||
//
|
||||
// Simple nom proc for if you get ckey'd into a simple_mob mob! Avoids grabs.
|
||||
//
|
||||
/mob/living/simple_mob/proc/animal_nom(var/mob/living/T in living_mobs(1))
|
||||
/mob/living/simple_mob/proc/animal_nom(mob/living/T in living_mobs(1))
|
||||
set name = "Animal Nom"
|
||||
set category = "IC"
|
||||
set desc = "Since you can't grab, you get a verb!"
|
||||
|
||||
if (stat != CONSCIOUS)
|
||||
if(stat != CONSCIOUS)
|
||||
return
|
||||
if (istype(src,/mob/living/simple_mob/animal/passive/mouse) && T.ckey == null)
|
||||
// Verbs are horrifying. They don't call overrides. So we're stuck with this.
|
||||
if(istype(src, /mob/living/simple_mob/animal/passive/mouse) && !T.ckey)
|
||||
// Mice can't eat logged out players!
|
||||
return
|
||||
if (client && IsAdvancedToolUser())
|
||||
if(client && IsAdvancedToolUser())
|
||||
to_chat(src, "<span class='warning'>Put your hands to good use instead!</span>")
|
||||
return
|
||||
feed_grabbed_to_self(src,T)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
//
|
||||
// Simple proc for animals to have their digestion toggled on/off externally
|
||||
@@ -45,8 +46,7 @@
|
||||
var/confirm = alert(user, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will reset after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel")
|
||||
if(confirm == "Enable")
|
||||
vore_selected.digest_mode = DM_DIGEST
|
||||
spawn(20 MINUTES)
|
||||
if(src) vore_selected.digest_mode = vore_default_mode
|
||||
addtimer(VARSET_CALLBACK(vore_selected, digest_mode, vore_default_mode), 20 MINUTES)
|
||||
else
|
||||
var/confirm = alert(user, "This mob is currently set to process all stomach contents. Do you want to disable this?", "Disabling [name]'s Digestion", "Disable", "Cancel")
|
||||
if(confirm == "Disable")
|
||||
@@ -69,28 +69,31 @@
|
||||
to_chat(user, "[src] is now using [vore_selected.fancy_vore ? "Fancy" : "Classic"] vore sounds.")
|
||||
|
||||
/mob/living/simple_mob/attackby(var/obj/item/O, var/mob/user)
|
||||
if (istype(O, /obj/item/weapon/newspaper) && !(ckey || (ai_holder.hostile && faction != user.faction)) && isturf(user.loc))
|
||||
if (ai_holder.retaliate && prob(vore_pounce_chance/2)) // This is a gamble!
|
||||
if(istype(O, /obj/item/weapon/newspaper) && !(ckey || (ai_holder.hostile && faction != user.faction)) && isturf(user.loc))
|
||||
if(ai_holder.retaliate && prob(vore_pounce_chance/2)) // This is a gamble!
|
||||
user.Weaken(5) //They get tackled anyway whether they're edible or not.
|
||||
user.visible_message("<span class='danger'>\the [user] swats \the [src] with \the [O] and promptly gets tackled!</span>!")
|
||||
if (will_eat(user))
|
||||
user.visible_message("<span class='danger'>[user] swats [src] with [O] and promptly gets tackled!</span>!")
|
||||
if(will_eat(user))
|
||||
set_AI_busy(TRUE)
|
||||
animal_nom(user)
|
||||
update_icon()
|
||||
set_AI_busy(FALSE)
|
||||
else if (!ai_holder.target) // no using this to clear a retaliate mob's target
|
||||
else if(!ai_holder.target) // no using this to clear a retaliate mob's target
|
||||
ai_holder.target = user //just because you're not tasty doesn't mean you get off the hook. A swat for a swat.
|
||||
//AttackTarget() //VOREStation AI Temporary Removal
|
||||
//LoseTarget() // only make one attempt at an attack rather than going into full rage mode
|
||||
else
|
||||
user.visible_message("<span class='info'>\the [user] swats \the [src] with \the [O]!</span>!")
|
||||
user.visible_message("<span class='info'>[user] swats [src] with [O]!</span>")
|
||||
release_vore_contents()
|
||||
for(var/mob/living/L in living_mobs(0)) //add everyone on the tile to the do-not-eat list for a while
|
||||
if(!(L in prey_excludes)) // Unless they're already on it, just to avoid fuckery.
|
||||
prey_excludes += L
|
||||
spawn(5 MINUTES)
|
||||
if(src && L)
|
||||
prey_excludes -= L
|
||||
addtimer(CALLBACK(src, .proc/removeMobFromPreyExcludes, weakref(L)), 5 MINUTES)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/proc/removeMobFromPreyExcludes(weakref/target)
|
||||
if(isweakref(target))
|
||||
var/mob/living/L = target.resolve()
|
||||
if(L)
|
||||
LAZYREMOVE(prey_excludes, L)
|
||||
|
||||
@@ -241,7 +241,6 @@
|
||||
BI.forceMove(torso)
|
||||
torso.implants += BI
|
||||
|
||||
|
||||
if(message)
|
||||
to_chat(M, "<span class='notice'>You lose sensation of your body, feeling only the warmth of everything around you... </span>")
|
||||
to_chat(O, "<span class='notice'>Your body shifts as you make dramatic changes to your captive's body.</span>")
|
||||
|
||||
@@ -70,7 +70,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
//
|
||||
// Check if an object is capable of eating things, based on vore_organs
|
||||
//
|
||||
/proc/is_vore_predator(var/mob/living/O)
|
||||
/proc/is_vore_predator(mob/living/O)
|
||||
if(istype(O,/mob/living))
|
||||
if(O.vore_organs.len > 0)
|
||||
return TRUE
|
||||
@@ -87,8 +87,9 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
//
|
||||
// Save/Load Vore Preferences
|
||||
//
|
||||
/datum/vore_preferences/proc/load_path(ckey,slot,filename="character",ext="json")
|
||||
if(!ckey || !slot) return
|
||||
/datum/vore_preferences/proc/load_path(ckey, slot, filename="character", ext="json")
|
||||
if(!ckey || !slot)
|
||||
return
|
||||
path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/vore/[filename][slot].[ext]"
|
||||
|
||||
|
||||
@@ -102,7 +103,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
|
||||
load_path(client_ckey,slot)
|
||||
|
||||
if(!path) return FALSE //Path couldn't be set?
|
||||
if(!path)
|
||||
return FALSE //Path couldn't be set?
|
||||
if(!fexists(path)) //Never saved before
|
||||
save_vore() //Make the file first
|
||||
return TRUE
|
||||
@@ -151,7 +153,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
return TRUE
|
||||
|
||||
/datum/vore_preferences/proc/save_vore()
|
||||
if(!path) return FALSE
|
||||
if(!path)
|
||||
return FALSE
|
||||
|
||||
var/version = VORE_VERSION //For "good times" use in the future
|
||||
var/list/settings_list = list(
|
||||
|
||||
@@ -8,68 +8,72 @@
|
||||
#define BELLIES_DESC_MAX 2048
|
||||
#define FLAVOR_MAX 40
|
||||
|
||||
/mob/living
|
||||
var/datum/vore_look/vorePanel
|
||||
|
||||
/mob/living/proc/insidePanel()
|
||||
set name = "Vore Panel"
|
||||
set category = "IC"
|
||||
|
||||
var/datum/vore_look/picker_holder = new()
|
||||
picker_holder.loop = picker_holder
|
||||
picker_holder.selected = vore_selected
|
||||
if(!vorePanel)
|
||||
log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and tried to use the verb.")
|
||||
vorePanel = new
|
||||
|
||||
var/dat = picker_holder.gen_ui(src)
|
||||
|
||||
picker_holder.popup = new(src, "insidePanel","Inside!", 450, 700, picker_holder)
|
||||
picker_holder.popup.set_content(dat)
|
||||
picker_holder.popup.open()
|
||||
src.openpanel = 1
|
||||
vorePanel.selected = vore_selected
|
||||
vorePanel.show(src)
|
||||
|
||||
/mob/living/proc/updateVRPanel() //Panel popup update call from belly events.
|
||||
if(src.openpanel == 1)
|
||||
var/datum/vore_look/picker_holder = new()
|
||||
picker_holder.loop = picker_holder
|
||||
picker_holder.selected = vore_selected
|
||||
if(!vorePanel)
|
||||
log_debug("[src] ([type], \ref[src]) didn't have a vorePanel and something tried to update it.")
|
||||
vorePanel = new
|
||||
|
||||
var/dat = picker_holder.gen_ui(src)
|
||||
|
||||
picker_holder.popup = new(src, "insidePanel","Inside!", 450, 700, picker_holder)
|
||||
picker_holder.popup.set_content(dat)
|
||||
picker_holder.popup.open()
|
||||
if(vorePanel.open)
|
||||
vorePanel.selected = vore_selected
|
||||
vorePanel.show(src)
|
||||
|
||||
//
|
||||
// Callback Handler for the Inside form
|
||||
//
|
||||
/datum/vore_look
|
||||
var/datum/browser/popup
|
||||
var/obj/belly/selected
|
||||
var/show_interacts = 0
|
||||
var/datum/browser/popup
|
||||
var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.
|
||||
var/open = FALSE
|
||||
|
||||
/datum/vore_look/Destroy()
|
||||
loop = null
|
||||
selected = null
|
||||
return QDEL_HINT_HARDDEL // TODO - Until I can better analyze how this weird thing works, lets be safe
|
||||
QDEL_NULL(popup)
|
||||
. = ..()
|
||||
|
||||
/datum/vore_look/Topic(href,href_list[])
|
||||
if (vp_interact(href, href_list))
|
||||
if(vp_interact(href, href_list))
|
||||
popup.set_content(gen_ui(usr))
|
||||
usr << output(popup.get_content(), "insidePanel.browser")
|
||||
|
||||
/datum/vore_look/proc/show(mob/living/user)
|
||||
if(popup)
|
||||
QDEL_NULL(popup)
|
||||
popup = new(user, "insidePanel", "Inside!", 450, 700, src)
|
||||
popup.set_content(gen_ui(user))
|
||||
popup.open()
|
||||
open = TRUE
|
||||
|
||||
/datum/vore_look/proc/gen_ui(var/mob/living/user)
|
||||
var/dat
|
||||
|
||||
var/atom/userloc = user.loc
|
||||
if (isbelly(userloc))
|
||||
if(isbelly(userloc))
|
||||
var/obj/belly/inside_belly = userloc
|
||||
var/mob/living/eater = inside_belly.owner
|
||||
|
||||
//Don't display this part if we couldn't find the belly since could be held in hand.
|
||||
if(inside_belly)
|
||||
dat += "<font color = 'green'>You are currently [user.absorbed ? "absorbed into " : "inside "]</font> <font color = 'yellow'>[eater]'s</font> <font color = 'red'>[inside_belly]</font>!<br><br>"
|
||||
dat += "<font color='green'>You are currently [user.absorbed ? "absorbed into " : "inside "]</font> <font color = 'yellow'>[eater]'s</font> <font color = 'red'>[inside_belly]</font>!<br><br>"
|
||||
|
||||
if(inside_belly.desc)
|
||||
dat += "[inside_belly.desc]<br><br>"
|
||||
|
||||
if (inside_belly.contents.len > 1)
|
||||
if(inside_belly.contents.len > 1)
|
||||
dat += "You can see the following around you:<br>"
|
||||
for (var/atom/movable/O in inside_belly)
|
||||
if(istype(O,/mob/living))
|
||||
@@ -374,11 +378,9 @@
|
||||
|
||||
/datum/vore_look/proc/vp_interact(href, href_list)
|
||||
var/mob/living/user = usr
|
||||
for(var/H in href_list)
|
||||
|
||||
if(href_list["close"])
|
||||
qdel(src) // Cleanup
|
||||
user.openpanel = 0
|
||||
open = FALSE
|
||||
QDEL_NULL(popup)
|
||||
return
|
||||
|
||||
if(href_list["show_int"])
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
/datum/effect/effect/system/grav_pull/start()
|
||||
spawn(0)
|
||||
if(holder)
|
||||
src.location = get_turf(holder)
|
||||
for(var/i=0, i < number, i++)
|
||||
location = get_turf(holder)
|
||||
for(var/i = 0, i < number, i++)
|
||||
do_pull()
|
||||
sleep(25)
|
||||
|
||||
@@ -29,35 +29,35 @@
|
||||
defer_powernet_rebuild = 1
|
||||
|
||||
// Let's just make this one loop.
|
||||
for(var/atom/X in orange(pull_radius, location))
|
||||
for(var/X in orange(pull_radius, location))
|
||||
// Movable atoms only
|
||||
if(istype(X, /atom/movable))
|
||||
if(istype(X, /obj/effect/overlay)) continue
|
||||
if(X && !istype(X, /mob/living/carbon/human))
|
||||
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
|
||||
var/obj/structure/window/W = X
|
||||
W.ex_act(2.0)
|
||||
if(!ismovableatom(X) || istype(X, /obj/effect/overlay))
|
||||
continue
|
||||
|
||||
if(istype(X, /obj))
|
||||
var/obj/O = X
|
||||
if(O.anchored)
|
||||
if (!pull_anchored) continue // Don't pull anchored stuff unless configured
|
||||
step_towards(X, location) // step just once if anchored
|
||||
continue
|
||||
if(ishuman(X))
|
||||
var/mob/living/carbon/human/H = X
|
||||
if(istype(H.shoes, /obj/item/clothing/shoes/magboots))
|
||||
var/obj/item/clothing/shoes/magboots/M = H.shoes
|
||||
if(M.magpulse)
|
||||
step_towards(H, location) //step just once with magboots
|
||||
continue
|
||||
step_towards(H, location) //step twice
|
||||
step_towards(H, location)
|
||||
else
|
||||
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
|
||||
var/obj/structure/window/W = X
|
||||
W.ex_act(2.0)
|
||||
|
||||
step_towards(X, location) // Step twice
|
||||
step_towards(X, location)
|
||||
if(isobj(X))
|
||||
var/obj/O = X
|
||||
if(O.anchored)
|
||||
if(!pull_anchored)
|
||||
continue // Don't pull anchored stuff unless configured
|
||||
step_towards(X, location) // step just once if anchored
|
||||
continue
|
||||
|
||||
else if(istype(X,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = X
|
||||
if(istype(H.shoes,/obj/item/clothing/shoes/magboots))
|
||||
var/obj/item/clothing/shoes/magboots/M = H.shoes
|
||||
if(M.magpulse)
|
||||
step_towards(H, location) //step just once with magboots
|
||||
continue
|
||||
step_towards(H, location) //step twice
|
||||
step_towards(H, location)
|
||||
step_towards(X, location) // Step twice
|
||||
step_towards(X, location)
|
||||
|
||||
if(defer_powernet_rebuild != 2)
|
||||
defer_powernet_rebuild = 0
|
||||
return
|
||||
|
||||
@@ -10,36 +10,34 @@
|
||||
item_icons = list() // No in-hand sprites (for now, anyway, we could totally add some)
|
||||
pixel_y = 0 // Override value from parent.
|
||||
|
||||
/obj/item/weapon/holder/micro/examine(var/mob/user)
|
||||
/obj/item/weapon/holder/micro/examine(mob/user)
|
||||
for(var/mob/living/M in contents)
|
||||
M.examine(user)
|
||||
|
||||
/obj/item/weapon/holder/MouseDrop(mob/M as mob)
|
||||
/obj/item/weapon/holder/MouseDrop(mob/M)
|
||||
..()
|
||||
if(M != usr) return
|
||||
if(usr == src) return
|
||||
if(!Adjacent(usr)) return
|
||||
if(istype(M,/mob/living/silicon/ai)) return
|
||||
if(isAI(M)) return
|
||||
for(var/mob/living/carbon/human/O in contents)
|
||||
O.show_inv(usr)
|
||||
|
||||
/obj/item/weapon/holder/micro/attack_self(mob/living/carbon/user) //reworked so it works w/ nonhumans
|
||||
for(var/L in contents)
|
||||
if(!isliving(L))
|
||||
continue
|
||||
if(ishuman(L) && user.canClick())
|
||||
if(ishuman(L) && user.canClick()) // These canClicks() are repeated here to make sure users can't avoid the click delay
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.help_shake_act(user)
|
||||
user.setClickCooldown(user.get_attack_speed()) //uses the same cooldown as regular attack_hand
|
||||
return
|
||||
if(istype(L, /mob/living/simple_mob) && user.canClick())
|
||||
if(isanimal(L) && user.canClick())
|
||||
var/mob/living/simple_mob/S = L
|
||||
user.visible_message("<span class='notice'>[user] [S.response_help] \the [S].</span>")
|
||||
user.setClickCooldown(user.get_attack_speed())
|
||||
|
||||
|
||||
/obj/item/weapon/holder/micro/update_state()
|
||||
if(istype(loc,/turf) || !(held_mob) || !(held_mob.loc == src))
|
||||
if(isturf(loc) || !held_mob || held_mob.loc != src)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/holder/micro/Destroy()
|
||||
|
||||
@@ -43,7 +43,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
var/matrix/M = matrix()
|
||||
M.Scale(size_multiplier)
|
||||
M.Translate(0, 16*(size_multiplier-1))
|
||||
src.transform = M
|
||||
transform = M
|
||||
|
||||
/**
|
||||
* Get the effective size of a mob.
|
||||
@@ -55,7 +55,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
return 100000 //Whatever it is, it's too big to pick up, or it's a ghost, or something.
|
||||
|
||||
/mob/living/get_effective_size()
|
||||
return src.size_multiplier
|
||||
return size_multiplier
|
||||
|
||||
/**
|
||||
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
|
||||
@@ -111,10 +111,11 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
|
||||
var/nagmessage = "Adjust your mass to be a size between 25 to 200% (DO NOT ABUSE)"
|
||||
var/new_size = input(nagmessage, "Pick a Size") as num|null
|
||||
if(new_size && ISINRANGE(new_size,25,200))
|
||||
src.resize(new_size/100)
|
||||
message_admins("[key_name(src)] used the resize command in-game to be [new_size]% size. \
|
||||
([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
|
||||
if(new_size && ISINRANGE(new_size, 25, 200))
|
||||
resize(new_size/100)
|
||||
// I'm not entirely convinced that `src ? ADMIN_JMP(src) : "null"` here does anything
|
||||
// but just in case it does, I'm leaving the null-src checking
|
||||
message_admins("[key_name(src)] used the resize command in-game to be [new_size]% size. [src ? ADMIN_JMP(src) : "null"]")
|
||||
|
||||
/*
|
||||
//Add the set_size() proc to usable verbs. By commenting this out, we can leave the proc and hand it to species that need it.
|
||||
@@ -127,7 +128,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
* Attempt to scoop up this mob up into H's hands, if the size difference is large enough.
|
||||
* @return false if normal code should continue, 1 to prevent normal code.
|
||||
*/
|
||||
/mob/living/proc/attempt_to_scoop(var/mob/living/M, var/mob/living/G) //second one is for the Grabber, only exists for animals to self-grab
|
||||
/mob/living/proc/attempt_to_scoop(mob/living/M, mob/living/G) //second one is for the Grabber, only exists for animals to self-grab
|
||||
var/size_diff = M.get_effective_size() - get_effective_size()
|
||||
if(!holder_default && holder_type)
|
||||
holder_default = holder_type
|
||||
@@ -156,37 +157,42 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
* Called from /mob/living/Bump() in the 'brohugs all around' section.
|
||||
* @return false if normal code should continue, true to prevent normal code.
|
||||
*/
|
||||
/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
|
||||
/mob/living/proc/handle_micro_bump_helping(mob/living/tmob)
|
||||
//Both small! Go ahead and go.
|
||||
if(src.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
|
||||
if(get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
|
||||
return TRUE
|
||||
|
||||
//Worthy of doing messages at all
|
||||
if(abs(get_effective_size() - tmob.get_effective_size()) >= 0.50)
|
||||
var/src_message = null
|
||||
var/tmob_message = null
|
||||
|
||||
//Smaller person being stepped onto
|
||||
if(get_effective_size() > tmob.get_effective_size() && ishuman(src))
|
||||
src_message = "You carefully step over [tmob]."
|
||||
tmob_message = "[src] steps over you carefully!"
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(H.flying)
|
||||
return TRUE //Silently pass without a message.
|
||||
if(isTaurTail(H.tail_style))
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER(tail.msg_owner_help_run))
|
||||
to_chat(tmob,STEP_TEXT_PREY(tail.msg_prey_help_run))
|
||||
else
|
||||
to_chat(src,"You carefully step over [tmob].")
|
||||
to_chat(tmob,"[src] steps over you carefully!")
|
||||
src_message = tail.msg_owner_help_run
|
||||
tmob_message = tail.msg_prey_help_run
|
||||
|
||||
//Smaller person stepping under larger person
|
||||
else if(tmob.get_effective_size() > get_effective_size() && ishuman(tmob))
|
||||
else if(get_effective_size() < tmob.get_effective_size() && ishuman(tmob))
|
||||
src_message = "You run between [tmob]'s legs."
|
||||
tmob_message = "[src] runs between your legs."
|
||||
var/mob/living/carbon/human/H = tmob
|
||||
if(isTaurTail(H.tail_style))
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER(tail.msg_prey_stepunder))
|
||||
to_chat(tmob,STEP_TEXT_PREY(tail.msg_owner_stepunder))
|
||||
else
|
||||
to_chat(src,"You run between [tmob]'s legs.")
|
||||
to_chat(tmob,"[src] runs between your legs.")
|
||||
src_message = tail.msg_prey_stepunder
|
||||
tmob_message = tail.msg_owner_stepunder
|
||||
|
||||
if(src_message)
|
||||
to_chat(src, STEP_TEXT_OWNER(src_message))
|
||||
if(tmob_message)
|
||||
to_chat(tmob, STEP_TEXT_PREY(tmob_message))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -196,202 +202,124 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
*
|
||||
* @return false if normal code should continue, 1 to prevent normal code.
|
||||
*/
|
||||
/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
|
||||
/mob/living/proc/handle_micro_bump_other(mob/living/tmob)
|
||||
ASSERT(istype(tmob))
|
||||
|
||||
//If they're flying, don't do any special interactions.
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/P = src
|
||||
if(P.flying)
|
||||
return
|
||||
|
||||
//If we're flying, don't do any special interactions.
|
||||
if(flying)
|
||||
return
|
||||
//If the prey is flying, don't smush them.
|
||||
if(ishuman(tmob))
|
||||
var/mob/living/carbon/human/D = tmob
|
||||
if(D.flying)
|
||||
return
|
||||
|
||||
//They can't be stepping on anyone
|
||||
if(tmob.flying)
|
||||
return
|
||||
//We can't be stepping on anyone
|
||||
if(!canmove || buckled)
|
||||
return
|
||||
|
||||
//Test/set if human
|
||||
var/mob/living/carbon/human/H
|
||||
if(ishuman(src))
|
||||
H = src
|
||||
else
|
||||
var/mob/living/carbon/human/pred = src
|
||||
if(!istype(pred))
|
||||
//If we're not human, can't do the steppy
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/Ht
|
||||
if(ishuman(tmob))
|
||||
Ht = tmob
|
||||
else
|
||||
var/mob/living/carbon/human/prey = tmob
|
||||
if(!istype(prey))
|
||||
//If they're not human, steppy shouldn't happen
|
||||
return FALSE
|
||||
|
||||
//Depending on intent...
|
||||
switch(a_intent)
|
||||
// We need to be above a certain size ratio in order to do anything to the prey.
|
||||
// For DISARM and HURT intent, this is >=0.75, for GRAB it is >=0.5
|
||||
var/size_ratio = get_effective_size() - tmob.get_effective_size()
|
||||
if(a_intent == I_GRAB && size_ratio < 0.5)
|
||||
return FALSE
|
||||
if((a_intent == I_DISARM || a_intent == I_HURT) && size_ratio < 0.75)
|
||||
return FALSE
|
||||
if(a_intent == I_HELP) // Theoretically not possible, but just in case.
|
||||
return FALSE
|
||||
|
||||
//src stepped on someone with disarm intent
|
||||
if(I_DISARM)
|
||||
// If bigger than them by at least 0.75, move onto them and print message.
|
||||
if((get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
forceMove(tmob.loc)
|
||||
now_pushing = 0
|
||||
forceMove(tmob.loc)
|
||||
if(a_intent == I_GRAB || a_intent == I_DISARM)
|
||||
tmob.resting = 1
|
||||
|
||||
//Running on I_DISARM
|
||||
if(m_intent == "run")
|
||||
tmob.resting = 1 //Force them down to the ground.
|
||||
var/size_damage_multiplier = size_multiplier - tmob.size_multiplier
|
||||
// This technically means that I_GRAB will set this value to the same as I_HARM, but
|
||||
// I_GRAB won't ever trigger the damage-giving code, so it doesn't matter.
|
||||
// I_HARM: Rand 1-3 multiplied by 1 min or 1.75 max. 1 min 5.25 max damage to each limb.
|
||||
// I_DISARM: Perform some HALLOSS damage to the smaller.
|
||||
// Since stunned is broken, let's do this. Rand 15-30 multiplied by 1 min or 1.75 max. 15 holo to 52.5 holo, depending on RNG and size differnece.
|
||||
var/damage = (a_intent == I_DISARM) ? (rand(15, 30) * size_damage_multiplier) : (rand(1, 3) * size_damage_multiplier)
|
||||
// I_HARM only
|
||||
var/calculated_damage = damage / 2 //This will sting, but not kill. Does .5 to 2.625 damage, randomly, to each limb.
|
||||
|
||||
//Log it for admins (as opposed to walk which logs damage)
|
||||
add_attack_logs(src,tmob,"Pinned underfoot (run, no halloss)")
|
||||
var/message_pred = null
|
||||
var/message_prey = null
|
||||
var/datum/sprite_accessory/tail/taur/tail = null
|
||||
if(isTaurTail(pred.tail_style))
|
||||
tail = pred.tail_style
|
||||
|
||||
//Not a human, or not a taur, generic message only
|
||||
if(!H || !isTaurTail(H.tail_style))
|
||||
to_chat(src,"<span class='danger'>You quickly push [tmob] to the ground with your foot!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] pushes you down to the ground with their foot!</span>")
|
||||
if(a_intent == I_GRAB)
|
||||
// You can only grab prey if you have no shoes on.
|
||||
if(pred.shoes)
|
||||
message_pred = "You step down onto [prey], squishing them and forcing them down to the ground!"
|
||||
message_prey = "[pred] steps down and squishes you with their foot, forcing you down to the ground!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_grab_fail)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_grab_fail)
|
||||
add_attack_logs(pred, prey,"Grabbed underfoot ([tail ? "taur" : "nontaur"], shoes)")
|
||||
else
|
||||
message_pred = "You pin [prey] down onto the floor with your foot and curl your toes up around their body, trapping them inbetween them!"
|
||||
message_prey = "[pred] pins you down to the floor with their foot and curls their toes up around your body, trapping you inbetween them!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_grab_success)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_grab_success)
|
||||
equip_to_slot_if_possible(prey.get_scooped(pred), slot_shoes, 0, 1)
|
||||
add_attack_logs(pred, prey, "Grabbed underfoot ([tail ? "taur" : "nontaur"], no shoes)")
|
||||
|
||||
//Human with taur tail, special messages are sent
|
||||
else
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_disarm_run]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_disarm_run]</span>"))
|
||||
if(m_intent == "run")
|
||||
switch(a_intent)
|
||||
if(I_DISARM)
|
||||
message_pred = "You quickly push [prey] to the ground with your foot!"
|
||||
message_prey = "[pred] pushes you down to the ground with their foot!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_disarm_run)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_disarm_run)
|
||||
add_attack_logs(pred, prey, "Pinned underfoot (run, no halloss)")
|
||||
if(I_HURT)
|
||||
message_pred = "You carelessly step down onto [prey], crushing them!"
|
||||
message_prey = "[pred] steps carelessly on your body, crushing you!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_harm_run)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_harm_run)
|
||||
|
||||
//Walking on I_DISARM
|
||||
else
|
||||
//Perform some HALLOSS damage to the smaller.
|
||||
var/size_damage_multiplier = (src.size_multiplier - tmob.size_multiplier)
|
||||
var/damage = (rand(15,30)* size_damage_multiplier) //Since stunned is broken, let's do this. Rand 15-30 multiplied by 1 min or 1.75 max. 15 holo to 52.5 holo, depending on RNG and size differnece.
|
||||
tmob.apply_damage(damage, HALLOSS)
|
||||
tmob.resting = 1
|
||||
for(var/obj/item/organ/external/I in prey.organs)
|
||||
I.take_damage(calculated_damage, 0) // 5 damage min, 26.25 damage max, depending on size & RNG. If they're only stepped on once, the damage will (probably not...) heal over time.
|
||||
prey.drip(0.1)
|
||||
add_attack_logs(pred, prey, "Crushed underfoot (run, about [calculated_damage] damage)")
|
||||
else
|
||||
switch(a_intent)
|
||||
if(I_DISARM)
|
||||
message_pred = "You firmly push your foot down on [prey], painfully but harmlessly pinning them to the ground!"
|
||||
message_prey = "[pred] firmly pushes their foot down on you, quite painfully but harmlessly pinning you to the ground!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_disarm_walk)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_disarm_walk)
|
||||
add_attack_logs(pred, prey, "Pinned underfoot (walk, about [damage] halloss)")
|
||||
tmob.apply_damage(damage, HALLOSS)
|
||||
if(I_HURT)
|
||||
message_pred = "You methodically place your foot down upon [prey]'s body, slowly applying pressure, crushing them against the floor below!"
|
||||
message_prey = "[pred] methodically places their foot upon your body, slowly applying pressure, crushing you against the floor below!"
|
||||
if(tail)
|
||||
message_pred = STEP_TEXT_OWNER(tail.msg_owner_harm_walk)
|
||||
message_prey = STEP_TEXT_PREY(tail.msg_prey_harm_walk)
|
||||
// Multiplies the above damage by 3.5. This means a min of 1.75 damage, or a max of 9.1875. damage to each limb, depending on size and RNG.
|
||||
calculated_damage *= 3.5
|
||||
for(var/obj/item/organ/I in prey.organs)
|
||||
I.take_damage(calculated_damage, 0)
|
||||
prey.drip(3)
|
||||
add_attack_logs(pred, prey, "Crushed underfoot (walk, about [calculated_damage] damage)")
|
||||
|
||||
//Log it for admins (as opposed to run which logs no damage)
|
||||
add_attack_logs(src,tmob,"Pinned underfoot (walk, about [damage] halloss)")
|
||||
|
||||
//Not a human, or not a taur, generic message only
|
||||
if(!H || !isTaurTail(H.tail_style))
|
||||
to_chat(src,"<span class='danger'>You firmly push your foot down on [tmob], painfully but harmlessly pinning them to the ground!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] firmly pushes their foot down on you, quite painfully but harmlessly pinning you to the ground!</span>")
|
||||
|
||||
//Human with taur tail, special messages are sent
|
||||
else
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_disarm_walk]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_disarm_walk]</span>"))
|
||||
|
||||
//Return true, the sizediff was enough that we handled it.
|
||||
return TRUE
|
||||
|
||||
//Not enough sizediff for I_DISARM to do anything.
|
||||
else
|
||||
return FALSE
|
||||
|
||||
//src stepped on someone with harm intent
|
||||
if(I_HURT)
|
||||
// If bigger than them by at least 0.75, move onto them and print message.
|
||||
if((get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
forceMove(tmob.loc)
|
||||
|
||||
//Precalculate base damage
|
||||
var/size_damage_multiplier = (src.size_multiplier - tmob.size_multiplier)
|
||||
var/damage = (rand(1,3)* size_damage_multiplier) //Rand 1-3 multiplied by 1 min or 1.75 max. 1 min 5.25 max damage to each limb.
|
||||
var/calculated_damage = damage/2 //This will sting, but not kill. Does .5 to 2.625 damage, randomly, to each limb.
|
||||
|
||||
//Running on I_HURT
|
||||
if(m_intent == "run")
|
||||
|
||||
//Not a human, or not a taur, generic message only
|
||||
if(!H || !isTaurTail(H.tail_style))
|
||||
to_chat(src,"<span class='danger'>You carelessly step down onto [tmob], crushing them!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] steps carelessly on your body, crushing you!</span>")
|
||||
|
||||
//Human with taur tail, special messages are sent
|
||||
else
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_harm_run]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_harm_run]</span>"))
|
||||
|
||||
//If they are a human, do damage (doesn't hurt other mobs...?)
|
||||
if(Ht)
|
||||
for(var/obj/item/organ/external/I in Ht.organs)
|
||||
I.take_damage(calculated_damage, 0) // 5 damage min, 26.25 damage max, depending on size & RNG. If they're only stepped on once, the damage will (probably not...) heal over time.
|
||||
Ht.drip(0.1)
|
||||
add_attack_logs(src,tmob,"Crushed underfoot (run, about [calculated_damage] damage)")
|
||||
|
||||
//Walking on I_HURT
|
||||
else
|
||||
//Multiplies the above damage by 3.5. This means a min of 1.75 damage, or a max of 9.1875. damage to each limb, depending on size and RNG.
|
||||
calculated_damage *= 3.5
|
||||
|
||||
//If they are a human, do damage (doesn't hurt other mobs...?)
|
||||
if(Ht)
|
||||
for(var/obj/item/organ/I in Ht.organs)
|
||||
I.take_damage(calculated_damage, 0)
|
||||
Ht.drip(3)
|
||||
add_attack_logs(src,tmob,"Crushed underfoot (walk, about [calculated_damage] damage)")
|
||||
|
||||
//Not a human, or not a taur, generic message only
|
||||
if(!H || !isTaurTail(H.tail_style))
|
||||
to_chat(src,"<span class='danger'>You methodically place your foot down upon [tmob]'s body, slowly applying pressure, crushing them against the floor below!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] methodically places their foot upon your body, slowly applying pressure, crushing you against the floor below!</span>")
|
||||
|
||||
//Human with taur tail, special messages are sent
|
||||
else
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_harm_walk]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_harm_walk]</span>"))
|
||||
|
||||
//Return true, the sizediff was enough that we handled it.
|
||||
return TRUE
|
||||
|
||||
//Not enough sizediff for I_HURT to do anything.
|
||||
else
|
||||
return FALSE
|
||||
|
||||
//src stepped on someone with grab intent
|
||||
if(I_GRAB)
|
||||
// If bigger than them by at least 0.50, move onto them and print message.
|
||||
if((get_effective_size() - tmob.get_effective_size()) >= 0.50)
|
||||
now_pushing = 0
|
||||
tmob.resting = 1
|
||||
forceMove(tmob.loc)
|
||||
|
||||
//Not a human, or not a taur while wearing shoes = no grab
|
||||
if(!H || (!isTaurTail(H.tail_style) && H.shoes))
|
||||
to_chat(src,"<span class='danger'>You step down onto [tmob], squishing them and forcing them down to the ground!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] steps down and squishes you with their foot, forcing you down to the ground!</span>")
|
||||
add_attack_logs(src,tmob,"Grabbed underfoot (nontaur, shoes)")
|
||||
|
||||
//Human, not a taur, but not wearing shoes = yes grab
|
||||
else if(H && (!isTaurTail(H.tail_style) && !H.shoes))
|
||||
to_chat(src,"<span class='danger'>You pin [tmob] down onto the floor with your foot and curl your toes up around their body, trapping them inbetween them!</span>")
|
||||
to_chat(tmob,"<span class='danger'>[src] pins you down to the floor with their foot and curls their toes up around your body, trapping you inbetween them!</span>")
|
||||
equip_to_slot_if_possible(tmob.get_scooped(H), slot_shoes, 0, 1)
|
||||
add_attack_logs(src,tmob,"Grabbed underfoot (nontaur, no shoes)")
|
||||
|
||||
//Human, taur, shoes = no grab, special message
|
||||
else if(H.shoes)
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_grab_fail]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_grab_fail]</span>"))
|
||||
add_attack_logs(src,tmob,"Grabbed underfoot (taur, shoes)")
|
||||
|
||||
//Human, taur, no shoes = yes grab, special message
|
||||
else
|
||||
var/datum/sprite_accessory/tail/taur/tail = H.tail_style
|
||||
to_chat(src,STEP_TEXT_OWNER("<span class='danger'>[tail.msg_owner_grab_success]</span>"))
|
||||
to_chat(tmob,STEP_TEXT_PREY("<span class='danger'>[tail.msg_prey_grab_success]</span>"))
|
||||
equip_to_slot_if_possible(tmob.get_scooped(H), slot_shoes, 0, 1)
|
||||
add_attack_logs(src,tmob,"Grabbed underfoot (taur, no shoes)")
|
||||
|
||||
//Return true, the sizediff was enough that we handled it.
|
||||
return TRUE
|
||||
|
||||
//Not enough sizediff for I_GRAB to do anything.
|
||||
else
|
||||
return FALSE
|
||||
to_chat(pred, "<span class='danger'>[message_pred]</span>")
|
||||
to_chat(prey, "<span class='danger'>[message_prey]</span>")
|
||||
return TRUE
|
||||
|
||||
#undef STEP_TEXT_OWNER
|
||||
#undef STEP_TEXT_PREY
|
||||
@@ -41,8 +41,8 @@
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
var/size_select = input("Put the desired size (25-200%)", "Set Size", size_set_to*100) as num
|
||||
if(size_select>200 || size_select<25)
|
||||
var/size_select = input("Put the desired size (25-200%)", "Set Size", size_set_to * 100) as num
|
||||
if(size_select > 200 || size_select < 25)
|
||||
to_chat(usr, "<span class='notice'>Invalid size.</span>")
|
||||
return
|
||||
size_set_to = (size_select/100)
|
||||
@@ -69,24 +69,17 @@
|
||||
tracer_type = /obj/effect/projectile/tracer/xray
|
||||
impact_type = /obj/effect/projectile/impact/xray
|
||||
|
||||
on_hit(var/atom/target)
|
||||
var/mob/living/M = target
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.resize(set_size)
|
||||
H.show_message("<font color='blue'> The beam fires into your body, changing your size!</font>")
|
||||
H.updateicon()
|
||||
else if (istype(target, /mob/living/))
|
||||
var/mob/living/H = M
|
||||
H.resize(set_size)
|
||||
H.updateicon()
|
||||
else
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/beam/sizelaser/on_hit(var/atom/target)
|
||||
var/mob/living/M = target
|
||||
if(istype(M))
|
||||
M.resize(set_size)
|
||||
to_chat(M, "<font color='blue'> The beam fires into your body, changing your size!</font>")
|
||||
M.updateicon()
|
||||
return
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/beam/sizelaser/shrink
|
||||
set_size = 0.5 //50% of current size
|
||||
|
||||
|
||||
/obj/item/projectile/beam/sizelaser/grow
|
||||
set_size = 2.0 //200% of current size
|
||||
set_size = 2.0 //200% of current size
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/cooldown = 10
|
||||
var/weightloss_power = 1
|
||||
|
||||
/obj/machinery/fitness/attack_hand(var/mob/living/user)
|
||||
/obj/machinery/fitness/attack_hand(mob/living/user)
|
||||
if(user.nutrition < 70)
|
||||
to_chat(user, "<span class='notice'>You need more energy to workout with the [src]!</span>")
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
else //If they have enough nutrition and body weight, they can exercise.
|
||||
user.setClickCooldown(cooldown)
|
||||
user.nutrition -= 10 * weightloss_power
|
||||
user.weight -= 0.025 * weightloss_power * (0.01*user.weight_loss)
|
||||
flick("[icon_state]2",src)
|
||||
user.weight -= 0.025 * weightloss_power * (0.01 * user.weight_loss)
|
||||
flick("[icon_state]2", src)
|
||||
var/message = pick(messages)
|
||||
to_chat(user, "<span class='notice'>[message].</span>")
|
||||
for(var/s in workout_sounds)
|
||||
playsound(src.loc, s, 50, 1)
|
||||
playsound(loc, s, 50, 1)
|
||||
|
||||
/obj/machinery/fitness/punching_bag
|
||||
name = "punching bag"
|
||||
@@ -54,20 +54,20 @@
|
||||
"You hammer the clown right in it's face with your fist",
|
||||
"A honk emits from the punching bag as you hit it")
|
||||
|
||||
/obj/machinery/fitness/heavy/attackby(obj/item/W, var/mob/living/user)
|
||||
/obj/machinery/fitness/heavy/attackby(obj/item/W, mob/living/user)
|
||||
if(W.is_wrench())
|
||||
src.add_fingerprint(user)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("<span class='warning'>[user] has [anchored ? "un" : ""]secured \the [src].</span>", "<span class='notice'>You [anchored ? "un" : ""]secure \the [src].</span>")
|
||||
anchored = !anchored
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
return
|
||||
|
||||
/obj/machinery/fitness/heavy/attack_hand(var/mob/living/user)
|
||||
/obj/machinery/fitness/heavy/attack_hand(mob/living/user)
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='notice'>For safety reasons, you are required to have this equipment wrenched down before using it!</span>")
|
||||
return
|
||||
|
||||
else if(user.loc != src.loc)
|
||||
else if(user.loc != loc)
|
||||
to_chat(user, "<span class='notice'>For safety reasons, you need to be sitting in the [src] for it to work!</span>")
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user