mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-17 13:12:37 +00:00
* Basic Mob Carp: Retaliate Element (#71593) ## About The Pull Request Adds an Element and AI behaviour intended to replicate the "retaliate" behaviour which made up an entire widely-populated subtype of simple mobs. The behaviour is pretty simply "If you fuck with me I fuck with you". Mobs with the component will "remember" being attacked and will try to attack people who attacked them, until they lose sight of those people. They don't have very long memories so breaking line of sight is enough to remove you from their grudge list. The implementation unfortunately requires registering to 600 different "I have been attacked by X" signals but c'est la vie. It will still be cleaner than `/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus` and `mob/living/simple_animal/hostile/retaliate/bat/sgt_araneus`. I attached it to the pig for testing and left it there because out of all the farm animals we have right now, a pig would probably get pissed off if you tried to kill it. Unfortunately it's got a sausage's chance in hell of ever killing anyone. ## Why It's Good For The Game It doesn't have much purpose yet but as we make more basic mobs this is going to see a **lot** of use. ## Changelog 🆑 add: Basic mobs have the capability of being upset that you kicked and punched them. add: Pigs destined for slaughter will now ineffectually attempt to resist their fate, at least until they lose sight of you. balance: Bar bots are better at noticing that you're trying to kill them. /🆑 * Basic Mob Carp: Retaliate Element Co-authored-by: Jacquerel <hnevard@gmail.com> Co-authored-by: tastyfish <crazychris32@gmail.com>
70 lines
3.0 KiB
Plaintext
70 lines
3.0 KiB
Plaintext
/// Sets the BB target to a mob which you can see and who has recently attacked you
|
|
/datum/ai_planning_subtree/target_retaliate
|
|
|
|
/datum/ai_planning_subtree/target_retaliate/SelectBehaviors(datum/ai_controller/controller, delta_time)
|
|
. = ..()
|
|
controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list, BB_BASIC_MOB_RETALIATE_LIST, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
|
|
|
|
/**
|
|
* Picks a target from a provided list of atoms who have been pissing you off
|
|
* You will probably need /datum/element/ai_retaliate to take advantage of this unless you're populating the blackboard yourself
|
|
*/
|
|
/datum/ai_behavior/target_from_retaliate_list
|
|
action_cooldown = 2 SECONDS
|
|
/// How far can we see stuff?
|
|
var/vision_range = 9
|
|
|
|
/datum/ai_behavior/target_from_retaliate_list/perform(delta_time, datum/ai_controller/controller, shitlist_key, target_key, targetting_datum_key, hiding_location_key)
|
|
. = ..()
|
|
var/mob/living/living_mob = controller.pawn
|
|
var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key]
|
|
if(!targetting_datum)
|
|
CRASH("No target datum was supplied in the blackboard for [controller.pawn]")
|
|
|
|
var/list/enemy_refs = controller.blackboard[shitlist_key]
|
|
if (!length(enemy_refs))
|
|
finish_action(controller, succeeded = FALSE)
|
|
return
|
|
|
|
var/list/enemies_list = list()
|
|
for (var/datum/weakref/enemy_ref as anything in enemy_refs)
|
|
var/atom/enemy = enemy_ref.resolve()
|
|
if (!can_attack_target(living_mob, enemy, targetting_datum))
|
|
controller.blackboard[shitlist_key] -= enemy_ref
|
|
continue
|
|
enemies_list += enemy
|
|
|
|
if (!length(enemies_list))
|
|
finish_action(controller, succeeded = FALSE)
|
|
return
|
|
|
|
var/datum/weakref/weak_target = controller.blackboard[target_key]
|
|
var/atom/target = weak_target?.resolve()
|
|
if (target && (locate(target) in enemies_list)) // Don't bother changing
|
|
finish_action(controller, succeeded = FALSE)
|
|
return
|
|
|
|
var/atom/new_target = pick_final_target(controller, enemies_list)
|
|
controller.blackboard[target_key] = WEAKREF(new_target)
|
|
|
|
var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, new_target)
|
|
|
|
if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially.
|
|
controller.blackboard[hiding_location_key] = WEAKREF(potential_hiding_location)
|
|
|
|
finish_action(controller, succeeded = TRUE)
|
|
|
|
/// Returns true if this target is valid for attacking based on current conditions
|
|
/datum/ai_behavior/target_from_retaliate_list/proc/can_attack_target(mob/living/living_mob, atom/target, datum/targetting_datum/targetting_datum)
|
|
if (!target)
|
|
return FALSE
|
|
if (target == living_mob)
|
|
return FALSE
|
|
if (!can_see(living_mob, target, vision_range))
|
|
return FALSE
|
|
return targetting_datum.can_attack(living_mob, target)
|
|
|
|
/// Returns the desired final target from the filtered list of enemies
|
|
/datum/ai_behavior/target_from_retaliate_list/proc/pick_final_target(datum/ai_controller/controller, list/enemies_list)
|
|
return pick(enemies_list)
|