mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-14 16:44:33 +01:00
New PVE Major Midround: Demonic Incursion (#29053)
* Initial commit. Event. * Started converting mobs to basic mobs. Migo and Creature. Needs aggressiveness AI * Makes CI happy * Fixes some file names * Ticks files * Fixes file again * Update code/modules/events/demon_incursion.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Announcement sound, spawn adjustments * Reduced spread when portals multiply * Elite spawns when portal count gets high * Fixes missing comma * Converted migo, blank, and most of hellhounds to basic mobs. Added new controllers and behaviors * Fixes * Linters! * Faithless moved to basic mob * LINTERS * Makes skeletons basic mobs * Fixes, Ranged Attacks, Ranged variants of nether mobs * Handles portal expansion chance * Linters * Fixes mobs not breaking shit * Fixes ranged attacks * Fixes ranged attacks * oops * Another oops. No config changes are needed here * Twenty percent chance that a nether mob is a grappler * Dimensional tear fixes * Adjusts awaken distance for hostile mobs, makes variable melee attack rate for basic mobs * Variable initial spawns, variable spread rates. * Whole lot of fixes from merge, hellhound completion * Updated lavaland winter biodome * Makes basic mobs able to hurt other mobs * Makes spawners properly rally basic mobs to beat up the attacker * Extra line * Removed comment * Makes hellhounds stop resting when attacked or when they find a new target * Fixed initial portal spawn amounts * Borgs now affected by basic mobs * Nerfs portal spawn rate, nerfs portal integrity, nerfs portal max mobs * Grapplers now teleport to missed turfs * Removes duplicate notices * Buff portals a small bit * Makes nether portals no longer RR - the body is now recoverable from the blank it became * Makes portals layer above mobs * Removed excess ranged attack var * Changes list for determining start count to rely on mobs with client instead of all clients * Nerfs portal max mobs * Portals can no longer spread to within 3 tiles of another portal except on initial event start * Adjusts target portal count for big mobs * Spawners now properly remove nest values of basic mobs * Portals now glow an evil red. When portals are destroyed, 50% chance per mob to slay the mob * add prowling and return to home behaviors * cut this down * be a tiny bit smarter * Some code cleanup * Removes hostile base type, removing excess code * Gives /obj/ a basic mob attack handler. Fixes turrets * Gives basic mobs a HUD * Fixes skeleton death flag * Adjusted initial spawns * Incursion portals now slowly convert turfs, up to range 3 of them, to hellish flooring * Increases reward per destroyed portal * Makes the final portal of an incursion play a sound on destruction, couple portal fixes * Fixes basic mob xenobiology interactions * Non-shit portal sprites * Adds hostile machine element, mobs now actively target turrets and emitters * Properly gibs things when they should gib * Linter fix * Portals now layer under living mobs but over dead ones * Adds blackbox checking for demon incursion portal counts * Increases mob sight range slightly to account for widescreen, adds alt-color for grappler, delays incursion announcement a bit more * Portals now are more likely to spread the less there are * Incursion portals now repair themselves after not being damaged for some time * Grilles now shock basic mobs * Portals will now clean up basic mob corpses near them by gibbing them * Portal spread chance is now exponential regression * Portal mob spawns now linearly scale in time * Fixes some skeleton oversights in ruin mapping * Demon incursions no longer can spread to tiles in a space area, such as near brig plating * Moves corpse cleanup to mobs via component * Portals now drop bodies that are being eaten when they're destroyed. * Addresses code review * Docs some vars --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/// If there's something between us and our target then we need to queue a behaviour to make it not be there
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path
|
||||
/// Blackboard key containing current target
|
||||
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
|
||||
/// The action to execute, extend to add a different cooldown or something
|
||||
var/attack_behaviour = /datum/ai_behavior/attack_obstructions
|
||||
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
. = ..()
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(QDELETED(target))
|
||||
return
|
||||
|
||||
var/turf/next_step = get_step_towards(controller.pawn, target)
|
||||
if(!next_step.is_blocked_turf(exclude_mobs = TRUE, source_atom = controller.pawn))
|
||||
return
|
||||
|
||||
controller.queue_behavior(attack_behaviour, target_key)
|
||||
// Don't cancel future planning, maybe we can move now
|
||||
|
||||
/// Something is in our way, get it outta here
|
||||
/datum/ai_behavior/attack_obstructions
|
||||
action_cooldown = 2 SECONDS
|
||||
/// If we should attack walls, be prepared for complaints about breaches
|
||||
var/can_attack_turfs = FALSE
|
||||
/// For if you want your mob to be able to attack dense objects
|
||||
var/can_attack_dense_objects = TRUE
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
|
||||
var/mob/living/basic/basic_mob = controller.pawn
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
|
||||
if(QDELETED(target))
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
|
||||
|
||||
var/turf/next_step = get_step_towards(basic_mob, target)
|
||||
var/dir_to_next_step = get_dir(basic_mob, next_step)
|
||||
// If moving diagonally we need to punch both ways, or more accurately the one we are blocked in
|
||||
var/list/dirs_to_move = list()
|
||||
if(dir_to_next_step && GLOB.diagonals)
|
||||
for(var/direction in GLOB.cardinal)
|
||||
if(direction & dir_to_next_step)
|
||||
dirs_to_move += direction
|
||||
else
|
||||
dirs_to_move += dir_to_next_step
|
||||
|
||||
for(var/direction in dirs_to_move)
|
||||
if(attack_in_direction(controller, basic_mob, direction))
|
||||
return AI_BEHAVIOR_DELAY
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/proc/attack_in_direction(datum/ai_controller/controller, mob/living/basic/basic_mob, direction)
|
||||
var/turf/next_step = get_step(basic_mob, direction)
|
||||
if(!next_step.is_blocked_turf(exclude_mobs = TRUE, source_atom = controller.pawn))
|
||||
return FALSE
|
||||
|
||||
for(var/obj/object as anything in next_step.contents)
|
||||
if(!can_smash_object(basic_mob, object))
|
||||
continue
|
||||
basic_mob.melee_attack(object)
|
||||
return TRUE
|
||||
|
||||
if(can_attack_turfs)
|
||||
basic_mob.melee_attack(next_step)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/proc/can_smash_object(mob/living/basic/basic_mob, obj/object)
|
||||
if(!object.density && !can_attack_dense_objects)
|
||||
return FALSE
|
||||
if(object.IsObscured())
|
||||
return FALSE
|
||||
if(basic_mob.see_invisible < object.invisibility)
|
||||
return FALSE
|
||||
var/list/whitelist = basic_mob.ai_controller.blackboard[BB_OBSTACLE_TARGETING_WHITELIST]
|
||||
if(whitelist && !is_type_in_typecache(object, whitelist))
|
||||
return FALSE
|
||||
if((!ismachinery(object) && !isstructure(object)))
|
||||
return FALSE
|
||||
|
||||
return TRUE // It's in our way, let's get it out of our way
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/avoid_breaches
|
||||
|
||||
/datum/ai_behavior/attack_obstructions/avoid_breaches/can_smash_object(mob/living/basic/basic_mob, obj/object)
|
||||
. = ..()
|
||||
if(istype(object, /obj/structure/window) || istype(object, /obj/machinery/door/airlock/external))
|
||||
for(var/dir in GLOB.alldirs)
|
||||
if(isspaceturf(get_step(object, dir)))
|
||||
return FALSE
|
||||
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/low_priority_target
|
||||
target_key = BB_LOW_PRIORITY_HUNTING_TARGET
|
||||
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/pet_target
|
||||
target_key = BB_CURRENT_PET_TARGET
|
||||
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path/prowl
|
||||
attack_behaviour = /datum/ai_behavior/attack_obstructions/avoid_breaches
|
||||
target_key = BB_PROWL_TARGET
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/ai_behavior/find_hunt_target/prowl
|
||||
search_turf_types = TRUE
|
||||
|
||||
/datum/ai_behavior/find_hunt_target/prowl/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range)
|
||||
var/mob/living/living_mob = controller.pawn
|
||||
var/list/interesting_objects = search_turf_types ? RANGE_TURFS(hunt_range, living_mob) : oview(hunt_range, living_mob)
|
||||
shuffle_inplace(interesting_objects)
|
||||
for(var/atom/possible_dinner as anything in typecache_filter_list(interesting_objects, types_to_hunt))
|
||||
if(!valid_dinner(living_mob, possible_dinner, hunt_range, controller, seconds_per_tick))
|
||||
continue
|
||||
controller.set_blackboard_key(hunting_target_key, possible_dinner)
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
|
||||
|
||||
/datum/ai_behavior/hunt_target/prowl
|
||||
always_reset_target = TRUE
|
||||
behavior_flags = parent_type::behavior_flags | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
|
||||
|
||||
/datum/ai_behavior/hunt_target/prowl/target_caught(mob/living/hunter, atom/hunted)
|
||||
return // We're just going there
|
||||
|
||||
/datum/ai_planning_subtree/find_and_hunt_target/prowl
|
||||
target_key = BB_PROWL_TARGET
|
||||
finding_behavior = /datum/ai_behavior/find_hunt_target/prowl
|
||||
hunting_behavior = /datum/ai_behavior/hunt_target/prowl
|
||||
hunt_targets = list(/turf/simulated/floor/plasteel)
|
||||
hunt_range = 8
|
||||
hunt_chance = 50
|
||||
@@ -0,0 +1,50 @@
|
||||
/// Fire a ranged attack without interrupting movement.
|
||||
/datum/ai_planning_subtree/ranged_skirmish
|
||||
operational_datums = list(/datum/component/ranged_attacks)
|
||||
/// Blackboard key holding target atom
|
||||
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
|
||||
/// What AI behaviour do we actually run?
|
||||
var/attack_behavior = /datum/ai_behavior/ranged_skirmish
|
||||
/// If target is further away than this we don't fire
|
||||
var/max_range = 9
|
||||
/// If target is closer than this we don't fire
|
||||
var/min_range = 2
|
||||
|
||||
/datum/ai_planning_subtree/ranged_skirmish/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
. = ..()
|
||||
if(!controller.blackboard_key_exists(target_key))
|
||||
return
|
||||
controller.queue_behavior(attack_behavior, target_key, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION, max_range, min_range)
|
||||
|
||||
/// How often will we try to perform our ranged attack?
|
||||
/datum/ai_behavior/ranged_skirmish
|
||||
action_cooldown = 0.5 SECONDS
|
||||
|
||||
/datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range)
|
||||
. = ..()
|
||||
var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key]
|
||||
return !QDELETED(target)
|
||||
|
||||
/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range)
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(QDELETED(target))
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
|
||||
|
||||
var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])
|
||||
if(!targeting_strategy.can_attack(controller.pawn, target))
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
|
||||
|
||||
var/hiding_target = targeting_strategy.find_hidden_mobs(controller.pawn, target)
|
||||
controller.set_blackboard_key(hiding_location_key, hiding_target)
|
||||
|
||||
target = hiding_target || target
|
||||
|
||||
var/distance = get_dist(controller.pawn, target)
|
||||
if(distance > max_range || distance < min_range)
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
|
||||
|
||||
controller.ai_interact(target = target, intent = INTENT_HARM)
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
|
||||
|
||||
/datum/ai_planning_subtree/ranged_skirmish/no_minimum
|
||||
min_range = 0
|
||||
Reference in New Issue
Block a user