mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-18 18:42:08 +01:00
145 lines
5.5 KiB
Plaintext
145 lines
5.5 KiB
Plaintext
#define PPM 9 //Protein per meat, used for calculating the quantity of protein in an animal
|
|
|
|
/**
|
|
* Attempt to devour victim
|
|
*
|
|
* Returns TRUE on success, FALSE on failure
|
|
*/
|
|
/mob/living/carbon/human/proc/devour(atom/movable/victim)
|
|
var/can_eat = can_devour(victim)
|
|
if(!can_eat)
|
|
return FALSE
|
|
|
|
var/eat_speed = 100
|
|
if(can_eat == DEVOUR_FAST)
|
|
eat_speed = 30
|
|
if((species?.gluttonous & GLUT_MESSY) && ismob(victim))
|
|
eat_speed *= 3 //We want our bites to take a lot so as to not spam the chat.
|
|
do_gradual_devour(victim, eat_speed)
|
|
return
|
|
src.visible_message(SPAN_DANGER("\The [src] is attempting to devour \the [victim] whole!"))
|
|
var/mob/target = victim
|
|
if(isobj(victim))
|
|
target = src
|
|
if(!do_mob(src,target,eat_speed))
|
|
return FALSE
|
|
src.visible_message(SPAN_DANGER("\The [src] devours \the [victim] whole!"))
|
|
if(ismob(victim))
|
|
admin_attack_log(src, victim, "Devoured.", "Was devoured by.", "devoured")
|
|
else
|
|
src.drop_from_inventory(victim)
|
|
move_to_stomach(victim)
|
|
|
|
return TRUE
|
|
|
|
// Snowflake procs for unathi. Because lore said so.
|
|
|
|
/mob/living/carbon/human/proc/do_gradual_devour(var/mob/living/victim, var/eat_speed)
|
|
set waitfor = FALSE
|
|
|
|
//This function will start consuming the victim by taking bites out of them.
|
|
//Victim or attacker moving will interrupt it
|
|
//A bite will be taken every 4 seconds
|
|
var/bite_delay = 4
|
|
var/bite_size = mouth_size * 0.5
|
|
var/num_bites_needed = (victim.mob_size * 2)/bite_size //Total bites needed to eat it from full health
|
|
var/PEPB = 1/num_bites_needed //Percentage eaten per bite
|
|
var/turf/ourloc = src.loc
|
|
var/turf/victimloc = victim.loc
|
|
var/messes = 0 //Number of bloodstains we've placed
|
|
if(!victim.composition_reagent_quantity)
|
|
victim.calculate_composition()
|
|
var/dam_multiplier = 1
|
|
|
|
var/victim_maxhealth = victim.maxHealth //We cache this here in case we need to edit it.
|
|
|
|
var/damage_dealt = victim_maxhealth * PEPB * dam_multiplier
|
|
|
|
//Now, incase we're resuming an earlier feeding session on the same creature
|
|
//We calculate the actual bites needed to fully eat it based on how eaten it already is
|
|
if(victim.getBruteLoss())
|
|
var/percentageDamaged = victim.getBruteLoss() / victim_maxhealth
|
|
var/percentageRemaining = 1 - percentageDamaged
|
|
num_bites_needed = percentageRemaining / PEPB
|
|
|
|
var/time_needed_seconds = num_bites_needed*bite_delay//in seconds for now
|
|
var/time_needed_minutes
|
|
var/time_needed_string
|
|
if (time_needed_seconds > 60)
|
|
time_needed_minutes = round((time_needed_seconds/60))
|
|
time_needed_seconds = time_needed_seconds % 60
|
|
time_needed_string = "[time_needed_minutes] minutes and [time_needed_seconds] seconds"
|
|
else
|
|
time_needed_string = "[time_needed_seconds] seconds"
|
|
|
|
src.visible_message(SPAN_DANGER("[src] starts to devour [victim]!"), \
|
|
SPAN_DANGER("You start devouring [victim], this will take approximately [time_needed_string]. You and the victim must remain still to continue, \
|
|
but you can interrupt feeding anytime and leave with what you've already eaten."))
|
|
|
|
for (var/i = 0 to num_bites_needed)
|
|
if(do_mob(src, victim, bite_delay * 10, extra_checks = CALLBACK(src, PROC_REF(devouring_equals), victim)))
|
|
face_atom(victim)
|
|
victim.apply_damage(damage_dealt, DAMAGE_BRUTE)
|
|
var/obj/item/organ/internal/stomach/S = internal_organs_by_name[BP_STOMACH]
|
|
if(S)
|
|
S.ingested.add_reagent(victim.composition_reagent, (victim.composition_reagent_quantity * 0.5) * PEPB)
|
|
visible_message(SPAN_DANGER("[src] bites a chunk out of [victim]!"),
|
|
SPAN_DANGER("[bitemessage(victim)]"))
|
|
if(messes < victim.mob_size - 1 && prob(50))
|
|
handle_devour_mess(src, victim)
|
|
if(victim.getBruteLoss() >= victim_maxhealth)
|
|
visible_message(SPAN_DANGER("[src] finishes devouring [victim]."),SPAN_WARNING("You finish devouring [victim]."))
|
|
handle_devour_mess(src, victim, TRUE)
|
|
qdel(victim)
|
|
else
|
|
if(nutrition >= (max_nutrition - 60))
|
|
to_chat(src, SPAN_DANGER("Your stomach is full!"))
|
|
if (victim && !QDELETED(victim) && victimloc != victim.loc) //This procs when the victim gets moved to nullspace.
|
|
to_chat(src, SPAN_DANGER("[victim] moved away, you need to keep it still. Try grabbing, stunning or killing it first."))
|
|
else if (ourloc != src.loc)
|
|
to_chat(src, SPAN_DANGER("You moved! Devouring cancelled."))
|
|
break
|
|
|
|
/mob/living/carbon/human/proc/devouring_equals(var/mob/victim)
|
|
for(var/obj/item/grab/G in victim.grabbed_by)
|
|
if(G && G.state >= GRAB_NECK)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
//Helpers
|
|
/proc/bitemessage(var/mob/living/victim)
|
|
return pick(
|
|
"You take a bite out of \the [victim].",
|
|
"You rip a chunk off of \the [victim].",
|
|
"You consume a piece of \the [victim].",
|
|
"You feast upon your prey.",
|
|
"You chow down on \the [victim].",
|
|
"You gobble \the [victim]'s flesh.")
|
|
|
|
/proc/handle_devour_mess(var/mob/user, var/mob/living/victim, var/finish = 0)
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
H.add_blood(victim)
|
|
if (!turf_hasblood(get_turf(victim)))
|
|
blood_splatter(get_turf(victim), victim, TRUE)
|
|
|
|
if (finish)
|
|
//A bigger victim makes more gibs
|
|
if (victim.mob_size >= MOB_TINY)
|
|
new /obj/effect/decal/cleanable/blood/gibs(get_turf(victim))
|
|
if (victim.mob_size >= MOB_SMALL)
|
|
new /obj/effect/decal/cleanable/blood/gibs(get_turf(victim))
|
|
if (victim.mob_size >= MOB_MEDIUM)
|
|
new /obj/effect/decal/cleanable/blood/gibs(get_turf(victim))
|
|
if (victim.mob_size >= MOB_LARGE)
|
|
new /obj/effect/decal/cleanable/blood/gibs(get_turf(victim))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/proc/turf_hasblood(var/turf/test)
|
|
for (var/obj/effect/decal/cleanable/blood/b in test)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
#undef PPM
|