Skip to content

Commit d7e7524

Browse files
TiviPlusTiviPlus
authored andcommitted
Optimize playsound() even more (#89747)
## About The Pull Request Saw tgstation/tgstation#88517 and building on it Noticed we do some pointless stuff here, including A) looping over hearing sensitive mobs instead of cliented mobs for wall-respecting sounds B) Copying clients list even when we replace it like 10 lines later for wall respecting sounds C) scanning the entire client list when we could just use spatial search for non-wall respecting sounds D) looping over dead clients when we already have them in the cliented mobs list for non-wall respecting sounds (Notably arguably slightly more expensive now for wall respecting since its a new list += here but removing the . += for all loops is worth it imo) As a consequence I could also remove list ops for the return values, and could also remove the get_dist check since this is in the actual procs where we fetch the mobs C and D alone gave me a ~10% boost on a 5-npc 1 client AB test enviroment as below ![image](https://github.com/user-attachments/assets/880561f0-1971-4747-b097-29917c3e13ea) As a side consequence gave the spatial search helpers more flexibility with regards to what to look for so I'm sure someone who needs GBP can find something optimizable there --------- Co-authored-by: TiviPlus <[email protected]>
1 parent 2c953c3 commit d7e7524

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

code/__HELPERS/spatial_info.dm

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@
7878
*
7979
* * view_radius - what radius search circle we are using, worse performance as this increases
8080
* * source - object at the center of our search area. everything in get_turf(source) is guaranteed to be part of the search area
81+
* * contents_type - the type of contents we want to be looking for. defaults to hearing sensitive
8182
*/
82-
/proc/get_hearers_in_view(view_radius, atom/source)
83+
/proc/get_hearers_in_view(view_radius, atom/source, contents_type=RECURSIVE_CONTENTS_HEARING_SENSITIVE)
8384
var/turf/center_turf = get_turf(source)
8485
if(!center_turf)
8586
return
@@ -88,12 +89,12 @@
8889

8990
if(view_radius <= 0)//special case for if only source cares
9091
for(var/atom/movable/target as anything in center_turf)
91-
var/list/recursive_contents = target.important_recursive_contents?[RECURSIVE_CONTENTS_HEARING_SENSITIVE]
92+
var/list/recursive_contents = target.important_recursive_contents?[contents_type]
9293
if(recursive_contents)
9394
. += recursive_contents
9495
return .
9596

96-
var/list/hearables_from_grid = SSspatial_grid.orthogonal_range_search(source, RECURSIVE_CONTENTS_HEARING_SENSITIVE, view_radius)
97+
var/list/hearables_from_grid = SSspatial_grid.orthogonal_range_search(source, contents_type, view_radius)
9798

9899
if(!length(hearables_from_grid))//we know that something is returned by the grid, but we dont know if we need to actually filter down the output
99100
return .
@@ -126,8 +127,9 @@
126127
*
127128
* * radius - what radius search circle we are using, worse performance as this increases
128129
* * source - object at the center of our search area. everything in get_turf(source) is guaranteed to be part of the search area
130+
* * contents_type - the type of contents we want to be looking for. defaults to hearing sensitive
129131
*/
130-
/proc/get_hearers_in_range(range, atom/source)
132+
/proc/get_hearers_in_range(range, atom/source, contents_type=RECURSIVE_CONTENTS_HEARING_SENSITIVE)
131133
var/turf/center_turf = get_turf(source)
132134
if(!center_turf)
133135
return
@@ -136,12 +138,12 @@
136138

137139
if(range <= 0)//special case for if only source cares
138140
for(var/atom/movable/target as anything in center_turf)
139-
var/list/recursive_contents = target.important_recursive_contents?[RECURSIVE_CONTENTS_HEARING_SENSITIVE]
141+
var/list/recursive_contents = target.important_recursive_contents?[contents_type]
140142
if(recursive_contents)
141143
. += recursive_contents
142144
return .
143145

144-
var/list/hearables_from_grid = SSspatial_grid.orthogonal_range_search(source, RECURSIVE_CONTENTS_HEARING_SENSITIVE, range)
146+
var/list/hearables_from_grid = SSspatial_grid.orthogonal_range_search(source, contents_type, range)
145147

146148
if(!length(hearables_from_grid))//we know that something is returned by the grid, but we dont know if we need to actually filter down the output
147149
return .
@@ -161,20 +163,20 @@
161163
* * view_radius - what radius search circle we are using, worse performance as this increases but not as much as it used to
162164
* * source - object at the center of our search area. everything in get_turf(source) is guaranteed to be part of the search area
163165
*/
164-
/proc/get_hearers_in_LOS(view_radius, atom/source)
166+
/proc/get_hearers_in_LOS(view_radius, atom/source, contents_type=RECURSIVE_CONTENTS_HEARING_SENSITIVE)
165167
var/turf/center_turf = get_turf(source)
166168
if(!center_turf)
167169
return
168170

169171
if(view_radius <= 0)//special case for if only source cares
170172
. = list()
171173
for(var/atom/movable/target as anything in center_turf)
172-
var/list/hearing_contents = target.important_recursive_contents?[RECURSIVE_CONTENTS_HEARING_SENSITIVE]
174+
var/list/hearing_contents = target.important_recursive_contents?[contents_type]
173175
if(hearing_contents)
174176
. += hearing_contents
175177
return
176178

177-
. = SSspatial_grid.orthogonal_range_search(source, SPATIAL_GRID_CONTENTS_TYPE_HEARING, view_radius)
179+
. = SSspatial_grid.orthogonal_range_search(source, contents_type, view_radius)
178180

179181
for(var/atom/movable/target as anything in .)
180182
var/turf/target_turf = get_turf(target)
@@ -209,7 +211,7 @@
209211
. = list()
210212
// Returns a list of mobs who can hear any of the radios given in @radios
211213
for(var/obj/item/radio/radio as anything in radios)
212-
. |= get_hearers_in_LOS(radio.canhear_range, radio, FALSE)
214+
. |= get_hearers_in_LOS(radio.canhear_range, radio)
213215

214216
//Used when converting pixels to tiles to make them accurate
215217
#define OFFSET_X (0.5 / ICON_SIZE_X)

code/game/sound.dm

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,35 +62,41 @@
6262
var/sound/S = isdatum(soundin) ? soundin : sound(get_sfx(soundin))
6363
var/maxdistance = SOUND_RANGE + extrarange
6464
var/source_z = turf_source.z
65-
var/list/listeners = SSmobs.clients_by_zlevel[source_z].Copy()
6665

67-
. = list()//output everything that successfully heard the sound
66+
if(vary && !frequency)
67+
frequency = get_rand_frequency() // skips us having to do it per-sound later. should just make this a macro tbh
68+
69+
var/list/listeners
6870

6971
var/turf/above_turf = GET_TURF_ABOVE(turf_source)
7072
var/turf/below_turf = GET_TURF_BELOW(turf_source)
7173

7274
var/audible_distance = CALCULATE_MAX_SOUND_AUDIBLE_DISTANCE(vol, maxdistance, falloff_distance, falloff_exponent)
7375

7476
if(ignore_walls)
77+
listeners = get_hearers_in_range(audible_distance, turf_source, RECURSIVE_CONTENTS_CLIENT_MOBS)
7578
if(above_turf && istransparentturf(above_turf))
76-
listeners += SSmobs.clients_by_zlevel[above_turf.z]
79+
listeners += get_hearers_in_range(audible_distance, above_turf, RECURSIVE_CONTENTS_CLIENT_MOBS)
7780

7881
if(below_turf && istransparentturf(turf_source))
79-
listeners += SSmobs.clients_by_zlevel[below_turf.z]
82+
listeners += get_hearers_in_range(audible_distance, below_turf, RECURSIVE_CONTENTS_CLIENT_MOBS)
8083

8184
else //these sounds don't carry through walls
82-
listeners = get_hearers_in_view(audible_distance, turf_source)
85+
listeners = get_hearers_in_view(audible_distance, turf_source, RECURSIVE_CONTENTS_CLIENT_MOBS)
8386

8487
if(above_turf && istransparentturf(above_turf))
85-
listeners += get_hearers_in_view(audible_distance, above_turf)
88+
listeners += get_hearers_in_view(audible_distance, above_turf, RECURSIVE_CONTENTS_CLIENT_MOBS)
8689

8790
if(below_turf && istransparentturf(turf_source))
88-
listeners += get_hearers_in_view(audible_distance, below_turf)
91+
listeners += get_hearers_in_view(audible_distance, below_turf, RECURSIVE_CONTENTS_CLIENT_MOBS)
92+
for(var/mob/listening_ghost as anything in SSmobs.dead_players_by_zlevel[source_z])
93+
if(get_dist(listening_ghost, turf_source) <= audible_distance)
94+
listeners += listening_ghost
95+
96+
for(var/mob/listening_mob in listeners)//had nulls sneak in here, hence the typecheck
97+
listening_mob.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, 1, use_reverb)
8998

90-
for(var/mob/listening_mob in listeners | SSmobs.dead_players_by_zlevel[source_z])//observers always hear through walls
91-
if(get_dist(listening_mob, turf_source) <= audible_distance)
92-
listening_mob.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, 1, use_reverb)
93-
. += listening_mob
99+
return listeners
94100

95101
/**
96102
* Plays a sound with a specific point of origin for src mob

0 commit comments

Comments
 (0)