From 59d954fd59bb91ec993087a3f838893d00aa97ed Mon Sep 17 00:00:00 2001 From: Anewbe Date: Tue, 15 Jan 2019 16:40:33 -0600 Subject: [PATCH] Fixes a few mob AI bugs --- .../ai/aI_holder_subtypes/simple_mob_ai.dm | 2 ++ code/modules/ai/ai_holder_communication.dm | 6 ++-- code/modules/ai/ai_holder_targeting.dm | 31 ++++++++++++++----- .../subtypes/animal/sif/hooligan_crab.dm | 1 + .../simple_mob/subtypes/animal/sif/savik.dm | 3 ++ 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm b/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm index 2a16a3e091..8949e8c70e 100644 --- a/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm +++ b/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm @@ -3,6 +3,7 @@ /datum/ai_holder/simple_mob hostile = TRUE // The majority of simplemobs are hostile. + retaliate = TRUE // The majority of simplemobs will fight back. cooperative = TRUE returns_home = FALSE can_flee = FALSE @@ -13,6 +14,7 @@ // For non-hostile animals, and pets like Ian and Runtime. /datum/ai_holder/simple_mob/passive hostile = FALSE + retaliate = FALSE can_flee = TRUE violent_breakthrough = FALSE diff --git a/code/modules/ai/ai_holder_communication.dm b/code/modules/ai/ai_holder_communication.dm index 93267d19f4..4cfec6f7af 100644 --- a/code/modules/ai/ai_holder_communication.dm +++ b/code/modules/ai/ai_holder_communication.dm @@ -7,6 +7,7 @@ var/threaten_timeout = 1 MINUTE // If the mob threatens someone, they leave, and then come back before this timeout period, the mob escalates to fighting immediately. var/last_conflict_time = null // Last occurance of fighting being used, in world.time. var/last_threaten_time = null // Ditto but only for threats. + var/last_target_time = null // Ditto for when we last switched targets, used to stop retaliate from gimping mobs var/speak_chance = 0 // Probability that the mob talks (this is 'X in 200' chance since even 1/100 is pretty noisy) @@ -41,8 +42,6 @@ if(threaten_delay && last_threaten_time + threaten_delay < world.time) // Waited too long. should_escalate = TRUE - else if(last_conflict_time + threaten_timeout > world.time) // We got attacked while threatening them. - should_escalate = TRUE if(should_escalate) threatening = FALSE @@ -53,7 +52,8 @@ return // Wait a bit. else // They left, or so we think. - threatening = FALSE + if(last_threaten_time + threaten_timeout < world.time) // They've been gone long enough, probably safe to stand down + threatening = FALSE set_stance(STANCE_IDLE) if(holder.say_list) holder.ISay(safepick(holder.say_list.say_stand_down)) diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm index 37f064f8c0..bb86636485 100644 --- a/code/modules/ai/ai_holder_targeting.dm +++ b/code/modules/ai/ai_holder_targeting.dm @@ -3,6 +3,7 @@ /datum/ai_holder var/hostile = FALSE // Do we try to hurt others? var/retaliate = FALSE // Attacks whatever struck it first. Mobs will still attack back if this is false but hostile is true. + var/mauling = FALSE // Attacks unconscious mobs var/atom/movable/target = null // The thing (mob or object) we're trying to kill. var/atom/movable/preferred_target = null// If set, and if given the chance, we will always prefer to target this over other options. @@ -79,6 +80,7 @@ set_stance(STANCE_ALERT) else set_stance(STANCE_APPROACH) + last_target_time = world.time return TRUE // Filters return one or more 'preferred' targets. @@ -102,8 +104,17 @@ if(isliving(the_target)) var/mob/living/L = the_target - if(L.stat == DEAD) - return FALSE + if(ishuman(L) || issilicon(L)) + if(!L.client) // SSD players get a pass + return FALSE + if(L.stat) + if(L.stat == DEAD) // Leave dead things alone + return FALSE + if(L.stat == UNCONSCIOUS) // Do we have mauling? Yes? Then maul people who are sleeping but not SSD + if(mauling) + return TRUE + else + return FALSE if(holder.IIsAlly(L)) return FALSE return TRUE @@ -206,9 +217,14 @@ ai_log("react_to_attack() : Was attacked by [attacker], but they were an ally.", AI_LOG_TRACE) return FALSE if(target) // Already fighting someone. Switching every time we get hit would impact our combat performance. - ai_log("react_to_attack() : Was attacked by [attacker], but we already have a target.", AI_LOG_TRACE) - on_attacked(attacker) // So we attack immediately and not threaten. - return FALSE + if(!retaliate) // If we don't get to fight back, we don't fight back... + ai_log("react_to_attack() : Was attacked by [attacker], but we already have a target.", AI_LOG_TRACE) + on_attacked(attacker) // So we attack immediately and not threaten. + return FALSE + else if(attacker in attackers && world.time > last_target_time + 3 SECONDS) // Otherwise, let 'er rip + ai_log("react_to_attack() : Was attacked by [attacker]. Can retaliate, waited 3 seconds.", AI_LOG_INFO) + on_attacked(attacker) // So we attack immediately and not threaten. + return give_target(attacker) // Also handles setting the appropiate stance. if(stance == STANCE_SLEEP) // If we're asleep, try waking up if someone's wailing on us. ai_log("react_to_attack() : AI is asleep. Waking up.", AI_LOG_TRACE) @@ -220,10 +236,11 @@ // Sets a few vars so mobs that threaten will react faster to an attacker or someone who attacked them before. /datum/ai_holder/proc/on_attacked(atom/movable/AM) - last_conflict_time = world.time if(isliving(AM)) var/mob/living/L = AM - attackers |= L.name + if(!(L in attackers)) + attackers |= L.name + last_conflict_time = world.time // Causes targeting to prefer targeting the taunter if possible. // This generally occurs if more than one option is within striking distance, including the taunter. diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm index 3b7f279653..56e4725686 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm @@ -90,6 +90,7 @@ retaliate = TRUE returns_home = TRUE max_home_distance = 12 + mauling = TRUE var/random_follow = TRUE // Turn off if you want to bus with crabs. /datum/ai_holder/simple_mob/melee/hooligan/handle_stance_strategical() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/savik.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/savik.dm index e8d56d6bb4..88611f2c25 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/savik.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/savik.dm @@ -27,6 +27,7 @@ attacktext = list("mauled") say_list_type = /datum/say_list/savik + ai_holder_type = /datum/ai_holder/simple_mob/savik /datum/say_list/savik speak = list("Hruuugh!","Hrunnph") @@ -38,6 +39,8 @@ if(health <= (maxHealth * 0.5)) // At half health, and fighting someone currently. berserk() +/datum/ai_holder/simple_mob/savik + mauling = TRUE // So players can use it too. /mob/living/simple_mob/animal/sif/savik/verb/berserk()