From d5b3b537bf92ab7fb4e3f6b91710028b6d666fc5 Mon Sep 17 00:00:00 2001 From: "giacomand@gmail.com" Date: Sat, 11 Aug 2012 07:08:58 +0000 Subject: [PATCH] Added recursive_mob_check() proc. It will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, being unable to hear people due to being in a box within a bag. I then changed the get_mobs_in_view() to use this proc for gathering mobs and radios. The old system would loop through lists for a total of 5000 per function call, in an empty server. This new system will loop at around 1000 in an empty server. I made get_mobs_in_radio_ranges() use a level parameter to help make it more effecient by only bothering with the mobs that are in the Z level that are getting the radio message. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4365 316c924e-a436-60f5-8080-3fe189b3f50e --- code/defines/procs/gamehelpers.dm | 140 +++++-------------- code/game/machinery/telecomms/broadcaster.dm | 2 +- 2 files changed, 38 insertions(+), 104 deletions(-) diff --git a/code/defines/procs/gamehelpers.dm b/code/defines/procs/gamehelpers.dm index 25a4a136dc3..8e28fc272e6 100644 --- a/code/defines/procs/gamehelpers.dm +++ b/code/defines/procs/gamehelpers.dm @@ -119,116 +119,51 @@ +//var/debug_mob = 0 + +// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. +// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, +// being unable to hear people due to being in a box within a bag. + +/proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/client_check = 1, var/sight_check = 1, var/include_radio = 1) + + //debug_mob += O.contents.len + for(var/atom/A in O) + if(ismob(A)) + var/mob/M = A + if(client_check && !M.client) + L = recursive_mob_check(A, L) + continue + if(sight_check && !isInSight(A, O)) + continue + L += M + + else if(include_radio && istype(A, /obj/item/device/radio)) + if(sight_check && isInSight(A, O)) + L += A + L = recursive_mob_check(A, L) + return L + +// The old system would loop through lists for a total of 5000 per function call, in an empty server. +// This new system will loop at around 1000 in an empty server. + /proc/get_mobs_in_view(var/R, var/atom/source) // Returns a list of mobs in range of R from source. Used in radio and say code. var/turf/T = get_turf(source) - var/list/hear = hearers(R, T) - var/list/V = range(R, T) - - // Search for closets: - for(var/obj/structure/closet/C in V) - for(var/mob/M in C.contents) - if(isInSight(source,C)) - if(M.client) - hear += M - - // Search for Mulebots. A person might be riding in it's load. - for(var/obj/machinery/bot/mulebot/C in V) - if(C.load && ismob(C.load)) - if(isInSight(source,C)) - var/mob/M = C.load - if(M.client) - hear += M - - // Cryos: - for(var/obj/machinery/atmospherics/unary/cryo_cell/C in V) - if(C.occupant) - if(isInSight(source,C)) - if(C.occupant.client) - hear += C.occupant - - // Intelicards - for(var/obj/item/device/aicard/C in V) - for(var/mob/living/silicon/ai/M in C) - if(isInSight(source,C)) - if(M.client) - hear += M - - // Kind of a hacky fix, but should fix most cases without undo issues. - for(var/mob/M as mob in V) - for(var/obj/item/device/aicard/C in M.contents) - for(var/mob/living/silicon/ai/A in C) - if(isInSight(source,A)) - if(A.client) - hear += A - - // Soulstones - for(var/obj/item/device/soulstone/C in V) - for(var/mob/living/simple_animal/shade/M in C) - if(isInSight(source,C)) - if(M.client) - hear += M - - // Kind of a hacky fix, but should fix most cases without undo issues. - for(var/mob/M as mob in V) - for(var/obj/item/device/soulstone/C in M.contents) - for(var/mob/living/simple_animal/shade/A in C) - if(isInSight(source,A)) - if(A.client) - hear += A - - - - // Brains/MMIs/pAIs - for(var/mob/living/carbon/brain/C in player_list) - if(get_turf(C) in V) - if(isInSight(source,C)) - hear += C - for(var/mob/living/silicon/pai/C in player_list) - if(get_turf(C) in V) - if(isInSight(source,C)) - hear += C - -/* -- Handled above. WHY IS THIS HERE? WHYYYYYYY - // Personal AIs - for(var/obj/item/device/paicard/C in V) - if(C.pai) - if(isInSight(source,C)) - if(C.pai.client) - hear += C.pai -*/ - // Exosuits - for(var/obj/mecha/C in V) - if(C.occupant) - if(isInSight(source,C)) - if(C.occupant.client) - hear += C.occupant - - // Disposal Machines - for(var/obj/machinery/disposal/C in V) - for(var/mob/M in C.contents) - if(isInSight(source,C)) - if(M.client) - hear += M - - //Borg rechargers - for(var/obj/machinery/recharge_station/C in V) - if(C.occupant) - if(isInSight(source,C)) - if(C.occupant.client) - hear += C.occupant - - for(var/obj/item/device/radio/theradio in V) - if(isInSight(source,theradio)) - hear += theradio - + var/list/hear = list() + var/list/range = range(R, T) + //debug_mob += range.len + for(var/turf/A in range) + hear += recursive_mob_check(A) + //world.log << "NEW: [debug_mob]" + //debug_mob = 0 return hear -/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios) +/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios, var/level = 0) . = list() // Returns a list of mobs who can hear any of the radios given in @radios @@ -242,13 +177,12 @@ // Try to find all the players who can hear the message for(var/mob/M in player_list) var/turf/ear = get_turf(M) - if(ear) + if(isnull(level) || level == ear.z) if(ear in speaker_coverage) . += M return . - #define SIGN(X) ((X<0)?-1:1) proc diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 409f53f4ce0..1585c2055c1 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -255,7 +255,7 @@ var/list/recentmessages = list() // global list of recent messages broadcasted : radios += R // Get a list of mobs who can hear from the radios we collected. - var/list/receive = get_mobs_in_radio_ranges(radios) + var/list/receive = get_mobs_in_radio_ranges(radios, level) /* ###### Organize the receivers into categories for displaying the message ###### */