mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
140 lines
4.1 KiB
Plaintext
140 lines
4.1 KiB
Plaintext
// This code is used to give a very rough estimate of how screwed an individual player might be at any given moment when fighting monsters.
|
|
// You could use this to have an effect trigger when someone is in serious danger, or as a means for an AI to guess which mob needs to die first.
|
|
// The idea and the code structure was taken from Dungeon Crawl Stone Soup.
|
|
|
|
/atom/movable/proc/get_threat(var/mob/living/threatened)
|
|
return 0
|
|
|
|
|
|
/atom/movable/proc/guess_threat_level(var/mob/living/threatened)
|
|
return 0
|
|
|
|
/mob/living/simple_mob
|
|
var/threat_level = null // Set this if you want an explicit danger rating.
|
|
|
|
/mob/living/simple_mob/guess_threat_level(var/mob/living/threatened)
|
|
if(threat_level) // If they have a predefined number, use it.
|
|
return threat_level
|
|
// Otherwise we need to guess how scary this thing is.
|
|
var/threat_guess = 0
|
|
|
|
// First lets consider their attack ability.
|
|
var/will_point_blank = FALSE
|
|
if(has_AI())
|
|
will_point_blank = ai_holder.pointblank
|
|
|
|
var/potential_damage = 0
|
|
if(!projectiletype || ( get_dist(src, threatened >= 1) && !will_point_blank ) ) // Melee damage.
|
|
potential_damage = (melee_damage_lower + melee_damage_upper) / 2
|
|
|
|
// Treat potential_damage as estimated DPS. If the enemy attacks twice as fast as usual, it will double the number.
|
|
potential_damage *= 1 SECOND / (base_attack_cooldown + melee_attack_delay)
|
|
else
|
|
var/obj/item/projectile/P = new projectiletype(src)
|
|
if(P.nodamage || P.taser_effect) // Tasers are somewhat less scary.
|
|
potential_damage = P.agony / 2
|
|
else
|
|
potential_damage = P.damage
|
|
if(P.damage_type == HALLOSS) // Not sure if any projectiles do this, but can't be too safe.
|
|
potential_damage /= 2
|
|
// Rubber bullets, I guess.
|
|
potential_damage += P.agony / 2
|
|
qdel(P)
|
|
|
|
potential_damage *= 1 SECOND / (base_attack_cooldown + ranged_attack_delay)
|
|
|
|
// Special attacks are ultra-specific to the mob so a generic threat assessment isn't really possible.
|
|
|
|
threat_guess += potential_damage
|
|
|
|
// Then consider their defense.
|
|
threat_guess += getMaxHealth() / 5 // 100 health translates to 20 threat.
|
|
|
|
return threat_guess
|
|
|
|
/mob/living/get_threat(var/mob/living/threatened)
|
|
if(stat)
|
|
return 0
|
|
|
|
|
|
/mob/living/simple_mob/get_threat(var/mob/living/threatened)
|
|
. = ..()
|
|
|
|
if(has_AI())
|
|
if(!ai_holder.hostile)
|
|
return 0 // Can't hurt anyone.
|
|
|
|
if(incapacitated(INCAPACITATION_DISABLED))
|
|
return 0 // Can't currently hurt you if it's stunned.
|
|
|
|
var/friendly = threatened.faction == faction
|
|
|
|
var/threat = guess_threat_level()
|
|
|
|
// Hurt entities contribute less tension.
|
|
threat *= health
|
|
threat /= getMaxHealth()
|
|
|
|
// Allies reduce tension instead of adding.
|
|
if(friendly)
|
|
threat = -threat
|
|
|
|
else
|
|
if(threatened.invisibility > see_invisible)
|
|
threat /= 2 // Target cannot be seen by src.
|
|
if(invisibility > threatened.see_invisible)
|
|
threat *= 2 // Target cannot see src.
|
|
|
|
// Handle statuses.
|
|
if(confused)
|
|
threat /= 2
|
|
|
|
if(has_modifier_of_type(/datum/modifier/berserk))
|
|
threat *= 2
|
|
|
|
// Handle ability to harm.
|
|
// Being five tiles away from some spiders is a lot less scary than being in melee range of five spiders at once.
|
|
if(!projectiletype)
|
|
threat /= max(get_dist(src, threatened), 1)
|
|
|
|
return threat
|
|
|
|
|
|
|
|
// Gives a rough idea of how much danger someone is in. Meant to be used for PvE things since PvP has too many unknown variables.
|
|
/mob/living/proc/get_tension()
|
|
var/tension = 0
|
|
var/list/potential_threats = list()
|
|
|
|
// First, get everything threatening to us.
|
|
for(var/thing in view(src))
|
|
if(isliving(thing))
|
|
potential_threats += thing
|
|
if(istype(thing, /obj/machinery/porta_turret))
|
|
potential_threats += thing
|
|
|
|
var/danger = FALSE
|
|
// Now to get all the threats.
|
|
for(var/atom/movable/AM in potential_threats)
|
|
var/tension_from_AM = AM.get_threat(src)
|
|
tension += tension_from_AM
|
|
if(tension_from_AM > 0)
|
|
danger = TRUE
|
|
|
|
if(!danger)
|
|
return 0
|
|
|
|
// Tension is roughly doubled when about to fall into crit.
|
|
var/max_health = getMaxHealth()
|
|
tension *= 2 * max_health / (health + max_health)
|
|
|
|
// Being unable to act is really tense.
|
|
if(incapacitated(INCAPACITATION_DISABLED) && !lying)
|
|
tension *= 10
|
|
return tension
|
|
|
|
if(confused)
|
|
tension *= 2
|
|
|
|
return tension
|