mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-01-03 14:03:25 +00:00
Slimes are smarter about opportunistic snacks (#9149)
* Slimes are smarter about opportunistic snacks * Prevent calling for help against non-mob targets * Ater's fix
This commit is contained in:
@@ -4,3 +4,6 @@
|
||||
|
||||
#define IS_WALKING(X) (X?.move_intent?.flags & MOVEMENT_INTENT_WALKING)
|
||||
#define IS_RUNNING(X) (X?.move_intent?.flags & MOVEMENT_INTENT_RUNNING)
|
||||
|
||||
// Causes AStar paths to be blocked by windows that can't be passed through; usually, they go straight through.
|
||||
#define ASTAR_BLOCKED_BY_WINDOWS 1
|
||||
|
||||
@@ -123,7 +123,7 @@ length to avoid portals or something i guess?? Not that they're counted right no
|
||||
/proc/PathWeightCompare(PathNode/a, PathNode/b)
|
||||
return a.estimated_cost - b.estimated_cost
|
||||
|
||||
/proc/AStar(var/start, var/end, var/adjacent, var/dist, var/max_nodes, var/max_node_depth = 30, var/min_target_dist = 0, var/min_node_dist, var/id, var/datum/exclude)
|
||||
/proc/AStar(var/start, var/end, var/adjacent, var/dist, var/max_nodes, var/max_node_depth = 30, var/min_target_dist = 0, var/min_node_dist, var/id, var/datum/exclude, flags = 0)
|
||||
var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare)
|
||||
var/list/closed = list()
|
||||
var/list/path
|
||||
@@ -158,7 +158,7 @@ length to avoid portals or something i guess?? Not that they're counted right no
|
||||
if(current.nodes_traversed >= max_node_depth)
|
||||
continue
|
||||
|
||||
for(var/datum/datum in call(current.position, adjacent)(id))
|
||||
for(var/datum/datum in call(current.position, adjacent)(id, flags))
|
||||
if(datum == exclude)
|
||||
continue
|
||||
|
||||
|
||||
@@ -112,30 +112,14 @@
|
||||
adjust_discipline(-1)
|
||||
last_discipline_decay = world.time
|
||||
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/find_target(list/possible_targets, has_targets_list)
|
||||
if (hostile)
|
||||
. = ..()
|
||||
if (target || leader || rabid) // Always prioritize mobs, if we can. Otherwise, check for loose things to eat if we're not otherwise busy
|
||||
return
|
||||
var/list/yummies
|
||||
for (var/atom/M in view(world.view, holder))
|
||||
if (M.is_slime_food())
|
||||
// Make sure that we can reach the object first, but don't try too hard at it and make sure that the thing is edible beforehand
|
||||
var/list/path = AStar(holder.loc, M.loc, astar_adjacent_proc, /turf/proc/Distance, min_target_dist = 1, max_node_depth = world.view * 2, id = holder.IGetID(), exclude = obstacles)
|
||||
if (path?.len)
|
||||
LAZYDISTINCTADD(yummies, M)
|
||||
if (!LAZYLEN(yummies))
|
||||
return
|
||||
var/atom/yummy
|
||||
var/closest_distance = INFINITY
|
||||
for (var/atom/M in yummies) // Find the closest snack!
|
||||
var/dist = get_dist(holder, M)
|
||||
if (dist < closest_distance)
|
||||
yummy = M
|
||||
closest_distance = dist
|
||||
give_target(yummy)
|
||||
give_destination(yummy.loc)
|
||||
return yummy
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/list_targets()
|
||||
. = ..()
|
||||
if (!locate(/mob) in . && !leader && !rabid)
|
||||
for(var/atom/movable/M in view(vision_range, holder))
|
||||
if (M.is_slime_food())
|
||||
var/list/path_to = AStar(holder.loc, M.loc, astar_adjacent_proc, /turf/proc/Distance, min_target_dist = 0, max_node_depth = world.view * 2, id = holder.IGetID(), exclude = obstacles, flags = ASTAR_BLOCKED_BY_WINDOWS)
|
||||
if (path_to?.len)
|
||||
. += M
|
||||
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic()
|
||||
evolve_and_reproduce()
|
||||
@@ -161,6 +145,16 @@
|
||||
target.slime_chomp(holder)
|
||||
target = null
|
||||
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/request_help()
|
||||
if (target && !ismob(target)) // we absolutely, completely do not need help from other slimes when targeting a pile of dirt
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/can_violently_breakthrough()
|
||||
if (target && !ismob(target))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
// Called when pushed too far (or a red slime core was used).
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/proc/enrage()
|
||||
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
|
||||
|
||||
@@ -386,7 +386,7 @@
|
||||
|
||||
// Returns the surrounding cardinal turfs with open links
|
||||
// Including through doors openable with the ID
|
||||
/turf/proc/CardinalTurfsWithAccess(var/obj/item/card/id/ID)
|
||||
/turf/proc/CardinalTurfsWithAccess(var/obj/item/card/id/ID, flags)
|
||||
var/L[] = new()
|
||||
|
||||
// for(var/turf/simulated/t in oview(src,1))
|
||||
@@ -394,44 +394,44 @@
|
||||
for(var/d in cardinal)
|
||||
var/turf/T = get_step(src, d)
|
||||
if(istype(T) && !T.density)
|
||||
if(!LinkBlockedWithAccess(src, T, ID))
|
||||
if(!LinkBlockedWithAccess(src, T, ID, flags))
|
||||
L.Add(T)
|
||||
return L
|
||||
|
||||
|
||||
// Similar to above but not restricted to just cardinal directions.
|
||||
/turf/proc/TurfsWithAccess(var/obj/item/card/id/ID)
|
||||
/turf/proc/TurfsWithAccess(var/obj/item/card/id/ID, flags)
|
||||
var/L[] = new()
|
||||
|
||||
for(var/d in alldirs)
|
||||
var/turf/T = get_step(src, d)
|
||||
if(istype(T) && !T.density)
|
||||
if(!LinkBlockedWithAccess(src, T, ID))
|
||||
if(!LinkBlockedWithAccess(src, T, ID, flags))
|
||||
L.Add(T)
|
||||
return L
|
||||
|
||||
|
||||
// Returns true if a link between A and B is blocked
|
||||
// Movement through doors allowed if ID has access
|
||||
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/card/id/ID)
|
||||
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/card/id/ID, flags)
|
||||
|
||||
if(A == null || B == null) return 1
|
||||
var/adir = get_dir(A,B)
|
||||
var/rdir = get_dir(B,A)
|
||||
if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal
|
||||
var/iStep = get_step(A,adir&(NORTH|SOUTH))
|
||||
if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID))
|
||||
if(!LinkBlockedWithAccess(A,iStep, ID, flags) && !LinkBlockedWithAccess(iStep,B,ID, flags))
|
||||
return 0
|
||||
|
||||
var/pStep = get_step(A,adir&(EAST|WEST))
|
||||
if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID))
|
||||
if(!LinkBlockedWithAccess(A,pStep,ID, flags) && !LinkBlockedWithAccess(pStep,B,ID, flags))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(A,adir, ID))
|
||||
if(DirBlockedWithAccess(A,adir, ID, flags))
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(B,rdir, ID))
|
||||
if(DirBlockedWithAccess(B,rdir, ID, flags))
|
||||
return 1
|
||||
|
||||
for(var/obj/O in B)
|
||||
@@ -442,11 +442,18 @@
|
||||
|
||||
// Returns true if direction is blocked from loc
|
||||
// Checks doors against access with given ID
|
||||
/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/card/id/ID)
|
||||
/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/card/id/ID, flags)
|
||||
for(var/obj/structure/window/D in loc)
|
||||
if(!D.density) continue
|
||||
if(D.dir == SOUTHWEST) return 1
|
||||
if(D.dir == dir) return 1
|
||||
if (flags & ASTAR_BLOCKED_BY_WINDOWS)
|
||||
if (D.is_fulltile())
|
||||
return TRUE
|
||||
else
|
||||
if(!D.density)
|
||||
continue
|
||||
if(D.dir == SOUTHWEST)
|
||||
return TRUE
|
||||
if (D.dir & dir)
|
||||
return TRUE
|
||||
|
||||
for(var/obj/machinery/door/D in loc)
|
||||
if(!D.density) continue
|
||||
|
||||
Reference in New Issue
Block a user