[MIRROR] Redoes how merger datums store directions to neighboring members [MDB IGNORE] (#11238)

* Redoes how merger datums store directions to neighboring members (#64535)

The old logic broke down if
A: there were more then one eligable member on a tile
Or B: if the members were in anything but a line

The old code made the assumption that if a location had been talked to
ever, it was done talking forever. This isn't the case.

Also it kinda pissed me off that cost scaled with objects, not tiles. So
I changed how things were tracked to fix those things.

Makes me happy inside

* Redoes how merger datums store directions to neighboring members

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-02-03 12:54:54 +01:00
committed by GitHub
parent bc36a8c8fa
commit 7dd0797350
3 changed files with 61 additions and 33 deletions
+5
View File
@@ -0,0 +1,5 @@
// Defines relating to merger datums
// Indexes for the turf packet list
#define MERGE_TURF_PACKET_DIR 1
#define MERGE_TURF_PACKET_ATOMS 2
+55 -33
View File
@@ -11,7 +11,7 @@
/// The arbitrary "owner" member of the merge group
var/atom/origin
/// A list of all members in the group
/// Assoc list of all members in the group -> dirs from them to their connected nighbors
var/list/members = list()
#if MERGERS_DEBUG
@@ -83,56 +83,78 @@
addtimer(CALLBACK(src, .proc/Refresh), 1, TIMER_UNIQUE)
/datum/merger/proc/Refresh()
var/list/tips = list()
var/list/checked_turfs = list()
var/list/new_members = list()
// List of turf -> list(interesting dir, found matching atoms)
var/list/found_turfs = list()
if(origin)
tips[origin] = NORTH|EAST|SOUTH|WEST
new_members[origin] = NONE
while(length(tips))
var/atom/focus = tips[length(tips)]
var/dirs_to_check = tips[focus]
tips.len--
var/turf/starting = get_turf(origin)
check_turf(starting, found_turfs, NONE)
for(var/i = 1; i <= length(found_turfs), i++)
var/turf/focus = found_turfs[i]
var/list/focus_packet = found_turfs[focus]
var/dirs_checked = focus_packet[MERGE_TURF_PACKET_DIR]
for(var/dir in GLOB.cardinals)
if(!(dirs_to_check & dir))
if(dirs_checked & dir)
continue
var/turf/location = get_step(focus, dir)
if(!location || checked_turfs[location])
if(!location)
continue
checked_turfs[location] = TRUE
for(var/i in location)
var/atom/movable/thing = i
if(!merged_typecache[thing.type])
continue
if(attempt_merge_proc && !call(thing, attempt_merge_proc)(src, new_members))
continue
if(thing.mergers && thing.mergers[id] != src)
var/datum/merger/existing = thing.mergers[id]
qdel(src)
existing.Refresh()
if(!check_turf(location, found_turfs, dir))
if(QDELETED(src))
return
new_members[focus] |= dir // This is not a list, value of the members list is a bitfield of dirs
var/next_dirs = turn(dir, 180)
new_members[thing] |= next_dirs
next_dirs = ~next_dirs
var/existing = tips[thing] || (NORTH|EAST|SOUTH|WEST)
tips[thing] = existing & next_dirs
continue
focus_packet[MERGE_TURF_PACKET_DIR] |= dir
var/list/leaving_members = members - new_members
// Now that we have an idea of our connecting directions, build the fresh members list
var/list/fresh_members = list()
for(var/turf/location as anything in found_turfs)
var/list/turf_packet = found_turfs[location]
var/connected_dirs = turf_packet[MERGE_TURF_PACKET_DIR]
for(var/datum/member as anything in turf_packet[MERGE_TURF_PACKET_ATOMS])
fresh_members[member] = connected_dirs
var/list/leaving_members = members - fresh_members
for(var/atom/thing as anything in leaving_members)
RemoveMember(thing)
var/list/joining_members = new_members - members
var/list/joining_members = fresh_members - members
for(var/atom/thing as anything in joining_members)
AddMember(thing, joining_members[thing])
// They may not need a full update but the connected dirs could change
for(var/atom/thing as anything in new_members)
members[thing] = new_members[thing]
for(var/atom/thing as anything in fresh_members)
members[thing] = fresh_members[thing]
SEND_SIGNAL(src, COMSIG_MERGER_REFRESH_COMPLETE, leaving_members, joining_members)
if(!length(members))
qdel(src)
// Checks to see if the passed in location contains something interesting to us. If it does, return TRUE, otherwise return false
// If it is interesting, we add it to our processing list
/datum/merger/proc/check_turf(turf/location, list/found_turfs, asking_from)
var/found_something = FALSE
// if asking_from is invalid (like if it's 0), we get a random output. that's bad, let's check for falsyness
var/us_to_them = asking_from && turn(asking_from, 180)
if(found_turfs[location])
found_turfs[location][MERGE_TURF_PACKET_DIR] |= us_to_them
return TRUE
for(var/atom/movable/thing as anything in location)
if(!merged_typecache[thing.type])
continue
if(attempt_merge_proc && !call(thing, attempt_merge_proc)(src, found_turfs))
continue
if(thing.mergers && thing.mergers[id] != src)
var/datum/merger/existing = thing.mergers[id]
qdel(src)
existing.Refresh()
return FALSE
if(!found_turfs[location])
found_turfs[location] = list(us_to_them, list())
found_turfs[location][MERGE_TURF_PACKET_ATOMS] += thing
found_something = TRUE
return found_something
#undef MERGERS_DEBUG
+1
View File
@@ -107,6 +107,7 @@
#include "code\__DEFINES\mecha.dm"
#include "code\__DEFINES\melee.dm"
#include "code\__DEFINES\memory_defines.dm"
#include "code\__DEFINES\mergers.dm"
#include "code\__DEFINES\mob_spawn.dm"
#include "code\__DEFINES\mobs.dm"
#include "code\__DEFINES\mod.dm"