mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 12:11:45 +00:00
## About The Pull Request Nother bit ripped out of #79498 [Implements a get_cooldown() proc to get around dumb manual overrides and empower me to optimize the findtarget logic](7047d294dd) [Adds modify_cooldown, uses it to optimize find_potential_targets further](4ebc8cedce) No sense running the behavior if we're just waiting on its output, so let's run it once a minute just in case, then push an update instantly if we find something [Optimizes connect_range and promxity_monitors](bcf7d7c5b3) We know what turfs exist before and after a move We can use this information to prevent trying to update turfs we don't care about. This is important because post these changes mobs with fields will be moving a lot more, so it's gotta be cheap [Implements a special kind of field to handle ai targeting](80b63b3445) If we run targeting and don't like, find anything, we should setup a field that listens for things coming near us and then handle those things as we find them. This incurs a slight startup cost but saves so much time on the churn of constant costs Note: We should also work to figure out a way to avoid waking ais if none is near them/they aren't doing anything interesting We don't need to do that immediately this acts as somewhat of a stopgap (and would be good regardless) but it is worth keeping in mind) ## IMPORTANT I am unsure whether this is worth it anymore since #82539 was merged. As I say it was done as a stopgap because ais didn't know how to idle. If not I'll rip er out and we'll keep the other refactoring/optimizations. ## Why It's Good For The Game Cleaner basic ai code, maybe? faster basic ai code, for sure faster proximity monitors (significantly)
220 lines
8.0 KiB
Plaintext
220 lines
8.0 KiB
Plaintext
#define FIELD_TURFS_KEY "field_turfs"
|
|
#define EDGE_TURFS_KEY "edge_turfs"
|
|
|
|
/**
|
|
* Movable and easily code-modified fields! Allows for custom AOE effects that affect movement
|
|
* and anything inside of them, and can do custom turf effects!
|
|
* Supports automatic recalculation/reset on movement.
|
|
*
|
|
* "What do I gain from using advanced over standard prox monitors?"
|
|
* - You can set different effects on edge vs field entrance
|
|
* - You can set effects when the proximity monitor starts and stops tracking a turf
|
|
*/
|
|
/datum/proximity_monitor/advanced
|
|
/// If TRUE, edge turfs will be included as "in the field" for effects
|
|
/// Can be used in certain situations where you may have effects that trigger only at the edge,
|
|
/// while also wanting the field effect to trigger at edge turfs as well
|
|
var/edge_is_a_field = FALSE
|
|
/// All turfs on the inside of the proximity monitor - range - 1 turfs
|
|
var/list/turf/field_turfs = list()
|
|
/// All turfs on the very last tile of the proximity monitor's radius
|
|
var/list/turf/edge_turfs = list()
|
|
|
|
/datum/proximity_monitor/advanced/Destroy()
|
|
cleanup_field()
|
|
return ..()
|
|
|
|
/datum/proximity_monitor/advanced/proc/cleanup_field()
|
|
for(var/turf/turf as anything in edge_turfs)
|
|
cleanup_edge_turf(turf)
|
|
edge_turfs = list()
|
|
for(var/turf/turf as anything in field_turfs)
|
|
cleanup_field_turf(turf)
|
|
field_turfs = list()
|
|
|
|
//Call every time the field moves (done automatically if you use update_center) or a setup specification is changed.
|
|
/datum/proximity_monitor/advanced/proc/recalculate_field(full_recalc = FALSE)
|
|
var/list/new_turfs = update_new_turfs()
|
|
|
|
var/list/old_field_turfs = field_turfs
|
|
var/list/old_edge_turfs = edge_turfs
|
|
field_turfs = new_turfs[FIELD_TURFS_KEY]
|
|
edge_turfs = new_turfs[EDGE_TURFS_KEY]
|
|
if(!full_recalc)
|
|
field_turfs = list()
|
|
edge_turfs = list()
|
|
|
|
for(var/turf/old_turf as anything in old_field_turfs - field_turfs)
|
|
if(QDELETED(src))
|
|
return
|
|
cleanup_field_turf(old_turf)
|
|
for(var/turf/old_turf as anything in old_edge_turfs - edge_turfs)
|
|
if(QDELETED(src))
|
|
return
|
|
cleanup_edge_turf(old_turf)
|
|
|
|
if(full_recalc)
|
|
old_field_turfs = list()
|
|
old_edge_turfs = list()
|
|
field_turfs = new_turfs[FIELD_TURFS_KEY]
|
|
edge_turfs = new_turfs[EDGE_TURFS_KEY]
|
|
|
|
for(var/turf/new_turf as anything in field_turfs - old_field_turfs)
|
|
if(QDELETED(src))
|
|
return
|
|
field_turfs += new_turf
|
|
setup_field_turf(new_turf)
|
|
for(var/turf/new_turf as anything in edge_turfs - old_edge_turfs)
|
|
if(QDELETED(src))
|
|
return
|
|
edge_turfs += new_turf
|
|
setup_edge_turf(new_turf)
|
|
|
|
/datum/proximity_monitor/advanced/on_initialized(turf/location, atom/created, init_flags)
|
|
. = ..()
|
|
on_entered(location, created, null)
|
|
|
|
/datum/proximity_monitor/advanced/on_entered(turf/source, atom/movable/entered, turf/old_loc)
|
|
. = ..()
|
|
if(get_dist(source, host) == current_range)
|
|
field_edge_crossed(entered, old_loc, source)
|
|
else
|
|
field_turf_crossed(entered, old_loc, source)
|
|
|
|
/datum/proximity_monitor/advanced/on_moved(atom/movable/movable, atom/old_loc)
|
|
. = ..()
|
|
if(ignore_if_not_on_turf)
|
|
//Early return if it's not the host that has moved.
|
|
if(movable != host)
|
|
return
|
|
//Cleanup the field if the host was on a turf but isn't anymore.
|
|
if(!isturf(host.loc))
|
|
if(isturf(old_loc))
|
|
cleanup_field()
|
|
return
|
|
recalculate_field(full_recalc = FALSE)
|
|
|
|
/datum/proximity_monitor/advanced/on_uncrossed(turf/source, atom/movable/gone, direction)
|
|
if(get_dist(source, host) == current_range)
|
|
field_edge_uncrossed(gone, source, get_turf(gone))
|
|
else
|
|
field_turf_uncrossed(gone, source, get_turf(gone))
|
|
|
|
/// Called when a turf in the field of the monitor is linked
|
|
/datum/proximity_monitor/advanced/proc/setup_field_turf(turf/target)
|
|
return
|
|
|
|
/// Called when a turf in the field of the monitor is unlinked
|
|
/// Do NOT call this manually, requires management of the field_turfs list
|
|
/datum/proximity_monitor/advanced/proc/cleanup_field_turf(turf/target)
|
|
return
|
|
|
|
/// Called when a turf in the edge of the monitor is linked
|
|
/datum/proximity_monitor/advanced/proc/setup_edge_turf(turf/target)
|
|
if(edge_is_a_field) // If the edge is considered a field, set it up like one
|
|
setup_field_turf(target)
|
|
|
|
/// Called when a turf in the edge of the monitor is unlinked
|
|
/// Do NOT call this manually, requires management of the edge_turfs list
|
|
/datum/proximity_monitor/advanced/proc/cleanup_edge_turf(turf/target)
|
|
if(edge_is_a_field) // If the edge is considered a field, clean it up like one
|
|
cleanup_field_turf(target)
|
|
|
|
/datum/proximity_monitor/advanced/proc/update_new_turfs()
|
|
if(ignore_if_not_on_turf && !isturf(host.loc))
|
|
return list(FIELD_TURFS_KEY = list(), EDGE_TURFS_KEY = list())
|
|
var/list/local_field_turfs = list()
|
|
var/list/local_edge_turfs = list()
|
|
var/turf/center = get_turf(host)
|
|
if(current_range > 0)
|
|
local_field_turfs += RANGE_TURFS(current_range - 1, center)
|
|
if(current_range > 1)
|
|
local_edge_turfs = local_field_turfs - RANGE_TURFS(current_range, center)
|
|
return list(FIELD_TURFS_KEY = local_field_turfs, EDGE_TURFS_KEY = local_edge_turfs)
|
|
|
|
//Gets edge direction/corner, only works with square radius/WDH fields!
|
|
/datum/proximity_monitor/advanced/proc/get_edgeturf_direction(turf/T, turf/center_override = null)
|
|
var/turf/checking_from = get_turf(host)
|
|
if(istype(center_override))
|
|
checking_from = center_override
|
|
if(!(T in edge_turfs))
|
|
return
|
|
if(((T.x == (checking_from.x + current_range)) || (T.x == (checking_from.x - current_range))) && ((T.y == (checking_from.y + current_range)) || (T.y == (checking_from.y - current_range))))
|
|
return get_dir(checking_from, T)
|
|
if(T.x == (checking_from.x + current_range))
|
|
return EAST
|
|
if(T.x == (checking_from.x - current_range))
|
|
return WEST
|
|
if(T.y == (checking_from.y - current_range))
|
|
return SOUTH
|
|
if(T.y == (checking_from.y + current_range))
|
|
return NORTH
|
|
|
|
/datum/proximity_monitor/advanced/proc/field_turf_crossed(atom/movable/movable, turf/old_location, turf/new_location)
|
|
return
|
|
|
|
/datum/proximity_monitor/advanced/proc/field_turf_uncrossed(atom/movable/movable, turf/old_location, turf/new_location)
|
|
return
|
|
|
|
/datum/proximity_monitor/advanced/proc/field_edge_crossed(atom/movable/movable, turf/old_location, turf/new_location)
|
|
if(edge_is_a_field) // If the edge is considered a field, pass crossed to that
|
|
field_turf_crossed(movable, old_location, new_location)
|
|
|
|
/datum/proximity_monitor/advanced/proc/field_edge_uncrossed(atom/movable/movable, turf/old_location, turf/new_location)
|
|
if(edge_is_a_field) // If the edge is considered a field, pass uncrossed to that
|
|
field_turf_uncrossed(movable, old_location, new_location)
|
|
|
|
//DEBUG FIELD ITEM
|
|
/obj/item/multitool/field_debug
|
|
name = "strange multitool"
|
|
desc = "Seems to project a colored field!"
|
|
var/operating = FALSE
|
|
var/datum/proximity_monitor/advanced/debug/current = null
|
|
|
|
/obj/item/multitool/field_debug/Destroy()
|
|
QDEL_NULL(current)
|
|
return ..()
|
|
|
|
/obj/item/multitool/field_debug/proc/setup_debug_field()
|
|
current = new(src, 5, FALSE)
|
|
current.set_fieldturf_color = "#aaffff"
|
|
current.set_edgeturf_color = "#ffaaff"
|
|
current.recalculate_field(full_recalc = TRUE)
|
|
|
|
/obj/item/multitool/field_debug/attack_self(mob/user)
|
|
operating = !operating
|
|
to_chat(user, span_notice("You turn [src] [operating? "on":"off"]."))
|
|
if(!istype(current) && operating)
|
|
setup_debug_field()
|
|
else if(!operating)
|
|
QDEL_NULL(current)
|
|
|
|
/obj/item/multitool/field_debug/attack_self_secondary(mob/user, modifiers)
|
|
current.edge_is_a_field = !current.edge_is_a_field
|
|
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
|
|
|
//DEBUG FIELDS
|
|
/datum/proximity_monitor/advanced/debug
|
|
current_range = 5
|
|
var/set_fieldturf_color = "#aaffff"
|
|
var/set_edgeturf_color = "#ffaaff"
|
|
|
|
/datum/proximity_monitor/advanced/debug/setup_edge_turf(turf/target)
|
|
. = ..()
|
|
target.color = set_edgeturf_color
|
|
|
|
/datum/proximity_monitor/advanced/debug/cleanup_edge_turf(turf/target)
|
|
. = ..()
|
|
target.color = initial(target.color)
|
|
|
|
/datum/proximity_monitor/advanced/debug/setup_field_turf(turf/target)
|
|
. = ..()
|
|
target.color = set_fieldturf_color
|
|
|
|
/datum/proximity_monitor/advanced/debug/cleanup_field_turf(turf/target)
|
|
. = ..()
|
|
target.color = initial(target.color)
|
|
|
|
#undef FIELD_TURFS_KEY
|
|
#undef EDGE_TURFS_KEY
|