If hearers() is used in a nested for loop, with "in hearers()", it will return results through opaque atoms.
Numbered Steps to Reproduce Problem:
1. Atom with a proc to list hearers inside another for loop
2. Another atom hidden behind opaque turfs.
3. The atom will be listed as a hearer despite behind hidden.
Code Snippet (if applicable) to Reproduce Problem:
Testcase ZIP: https://www.dropbox.com/s/zaet5do431nrbyg/hearers-bug.zip
/obj/proc/print_hearers()
var/list/H = hearers(7, loc) // nothing printed
for(var/i in 1 to H.len)
var/mob/A2 = H[i]
world.log << "[A2]"
var/list/valid_turfs = list(loc) // atom printed!
for(var/turf_z as() in valid_turfs)
var/turf/T = valid_turfs[turf_z]
for(var/mob/A as() in hearers(7, T))
world.log << "[A]"
var/list/H2 = hearers(7, loc) // nothing printed
for(var/i2 in 1 to H2.len)
var/mob/A3 = H2[i2]
world.log << "[A3]"
Expected Results:
The atom should not be in the hearers list
Actual Results:
The atom IS in the hearers list
Does the problem occur:
Every time? Or how often? Always
In other games? In SS13 and a BYOND testcase
In other user accounts? N/A
On other computers? N/A
When does the problem NOT occur? When hearers() is used in other contexts
Did the problem NOT occur in any earlier versions? If so, what was the last version that worked?
Works in 514.1589
Workarounds:
Not using "in hearers()"
[edit]
Actually your test project and example code don't show a bug at all, unless hearers() from a null loc including anything at all is a bug. I added more output to make sense of the proc:
The resulting output makes it clear why the nested loop behaves differently, which I actually spotted as I was adding the debugging. You're looping through the valid_turfs list but then you're trying to grab T as an associated value that doesn't exist. Instead of using turf_z as the center for hearers(), you're using T which in that particular case is null.