Files
2024-05-19 16:37:29 +00:00

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