mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 06:56:50 +01:00
155 lines
4.9 KiB
Plaintext
155 lines
4.9 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2025 Citadel Station developers. *//
|
|
|
|
/**
|
|
* Connects transitively to cardinals.
|
|
*
|
|
* Does something very, very evil to status_traits.
|
|
*/
|
|
/datum/object_system/adjacency_group
|
|
/// string key
|
|
var/key
|
|
/// current group
|
|
var/datum/adjacency_group/group
|
|
/// rebuild queued?
|
|
var/rebuild_queued = FALSE
|
|
/// connected directions
|
|
var/connected_directions = NONE
|
|
|
|
/datum/object_system/adjacency_group/New(obj/parent, key)
|
|
src.key = key
|
|
ASSERT(key)
|
|
LAZYSET(parent.status_traits, TRAIT_OBJ_ADJACENCY_GROUP(src.key), src)
|
|
queue_rebuild()
|
|
return ..()
|
|
|
|
/datum/object_system/adjacency_group/Destroy()
|
|
LAZYREMOVE(parent.status_traits, TRAIT_OBJ_ADJACENCY_GROUP(key))
|
|
QDEL_NULL(group)
|
|
rebuild_queued = FALSE
|
|
return ..()
|
|
|
|
/datum/object_system/adjacency_group/proc/parent_moved()
|
|
QDEL_NULL(group)
|
|
queue_rebuild()
|
|
|
|
/datum/object_system/adjacency_group/proc/create_initial_data()
|
|
if(rebuild_queued)
|
|
return
|
|
return parent.object_adjacency_group_create_initial_data(src)
|
|
|
|
/datum/object_system/adjacency_group/proc/queue_rebuild()
|
|
addtimer(CALLBACK(src, PROC_REF(rebuild_if_needed)), 0)
|
|
rebuild_queued = TRUE
|
|
|
|
/datum/object_system/adjacency_group/proc/rebuild_if_needed()
|
|
if(!rebuild_queued)
|
|
return
|
|
rebuild_queued = FALSE
|
|
if(group)
|
|
return
|
|
rebuild()
|
|
|
|
/datum/object_system/adjacency_group/proc/rebuild()
|
|
QDEL_NULL(group)
|
|
var/datum/adjacency_group/new_group = new(key, create_initial_data())
|
|
new_group.build(src)
|
|
|
|
/datum/adjacency_group
|
|
/// all systems in group
|
|
var/list/datum/object_system/adjacency_group/in_group
|
|
/// string key
|
|
var/key
|
|
/// arbitrary data variable you can set to whatever you want
|
|
var/data
|
|
|
|
/datum/adjacency_group/New(key)
|
|
src.key = key
|
|
src.data = data
|
|
in_group = list()
|
|
|
|
/datum/adjacency_group/Destroy()
|
|
teardown()
|
|
return ..()
|
|
|
|
/datum/adjacency_group/proc/build(datum/object_system/adjacency_group/from_node)
|
|
// very destructive build process; when encountering 'enemy', immediately destroy it and trample over
|
|
var/list/datum/object_system/adjacency_group/expanding = list(from_node)
|
|
var/trait = TRAIT_OBJ_ADJACENCY_GROUP(key)
|
|
while(length(expanding))
|
|
var/datum/object_system/adjacency_group/expand_this = expanding[length(expanding)]
|
|
--expanding.len
|
|
var/dirs_connecting = NONE
|
|
|
|
var/atom/expand_loc = expand_this.parent.loc
|
|
if(isturf(expand_loc))
|
|
for(var/dir in GLOB.cardinal)
|
|
for(var/obj/in_cardinal_tile in get_step(expand_loc, dir))
|
|
var/datum/object_system/adjacency_group/their_cardinal_group = in_cardinal_tile.status_traits?[trait]
|
|
if(their_cardinal_group)
|
|
dirs_connecting |= dir
|
|
if(their_cardinal_group.group == src)
|
|
break
|
|
expanding += in_cardinal_tile.status_traits[trait]
|
|
break
|
|
|
|
for(var/obj/in_tile in expand_loc)
|
|
var/datum/object_system/adjacency_group/their_group = in_tile.status_traits?[trait]
|
|
if(!their_group || their_group == expand_this)
|
|
continue
|
|
dirs_connecting |= ONTOP_BIT
|
|
if(their_group.group != src)
|
|
if(their_group.group)
|
|
qdel(their_group.group)
|
|
their_group.group = src
|
|
their_group.connected_directions = dirs_connecting
|
|
in_group += their_group
|
|
|
|
if(expand_this.group != src)
|
|
if(expand_this.group)
|
|
qdel(expand_this.group)
|
|
expand_this.group = src
|
|
expand_this.connected_directions = dirs_connecting
|
|
in_group += expand_this
|
|
|
|
for(var/datum/object_system/adjacency_group/member as anything in in_group)
|
|
member.parent.object_adjacency_group_join(member, src, member.connected_directions)
|
|
|
|
/datum/adjacency_group/proc/teardown()
|
|
for(var/datum/object_system/adjacency_group/member as anything in in_group)
|
|
member.parent.object_adjacency_group_leave(member, src, member.connected_directions)
|
|
member.group = null
|
|
member.connected_directions = NONE
|
|
member.queue_rebuild()
|
|
in_group = null
|
|
|
|
//* /obj hooks *//
|
|
|
|
/**
|
|
* Called when an adjacency group is being built from ourselves and initial data is needed
|
|
*/
|
|
/obj/proc/object_adjacency_group_create_initial_data(datum/object_system/adjacency_group/group_holder)
|
|
return null
|
|
|
|
/**
|
|
* Called on adjacency group join
|
|
*
|
|
* @params
|
|
* * group_holder - object system handling the group
|
|
* * group - the group in question
|
|
* * directions - directions we're connecting in, as X_BIT (e.g. NORTHEAST_BIT). This will only have cardinals and ONTOP_BIT if something is atop us.
|
|
*/
|
|
/obj/proc/object_adjacency_group_join(datum/object_system/adjacency_group/group_holder, datum/object_system/adjacency_group/group, directions)
|
|
return
|
|
|
|
/**
|
|
* Called on adjacency group leave
|
|
*
|
|
* @params
|
|
* * group_holder - object system handling the group
|
|
* * group - the group in question
|
|
* * directions - directions we **were** connected in, as X_BIT (e.g. NORTHEAST_BIT). This will only have cardinals and ONTOP_BIT if something was atop us.
|
|
*/
|
|
/obj/proc/object_adjacency_group_leave(datum/object_system/adjacency_group/group_holder, datum/object_system/adjacency_group/group, directions)
|
|
return
|