diff --git a/code/__HELPERS/~skyrat_helpers/unsorted.dm b/code/__HELPERS/~skyrat_helpers/unsorted.dm index 041934e8ee7..4f0cda57ecc 100644 --- a/code/__HELPERS/~skyrat_helpers/unsorted.dm +++ b/code/__HELPERS/~skyrat_helpers/unsorted.dm @@ -13,3 +13,36 @@ M.Scale(squishx, squishy) animate(src, transform = M, time = halftime, easing = BOUNCE_EASING) animate(src, transform = OM, time = halftime, easing = BOUNCE_EASING) + +/** Get all hearers in range, ignores walls and such. Code stolen from `/proc/get_hearers_in_view()` + * Much faster and less expensive than range() +*/ +/proc/get_hearers_in_range(range_radius, atom/source) + var/turf/center_turf = get_turf(source) + if(!center_turf) + return + + . = list() + var/old_luminosity = center_turf.luminosity + if(range_radius <= 0) //special case for if only source cares + for(var/atom/movable/target as anything in center_turf) + var/list/recursive_contents = target.important_recursive_contents?[RECURSIVE_CONTENTS_HEARING_SENSITIVE] + if(recursive_contents) + . += recursive_contents + return . + + var/list/hearables_from_grid = SSspatial_grid.orthogonal_range_search(source, RECURSIVE_CONTENTS_HEARING_SENSITIVE, range_radius) + + 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 + return . + + var/list/assigned_oranges_ears = SSspatial_grid.assign_oranges_ears(hearables_from_grid) + + for(var/mob/oranges_ear/ear in range(range_radius, center_turf)) + . += ear.references + + for(var/mob/oranges_ear/remaining_ear as anything in assigned_oranges_ears) //we need to clean up our mess + remaining_ear.unassign() + + center_turf.luminosity = old_luminosity + return . diff --git a/modular_skyrat/modules/verbs/code/looc.dm b/modular_skyrat/modules/verbs/code/looc.dm index c1df1e968e1..6c07d89c8e1 100644 --- a/modular_skyrat/modules/verbs/code/looc.dm +++ b/modular_skyrat/modules/verbs/code/looc.dm @@ -1,10 +1,22 @@ +#define LOOC_RANGE 7 + /client/verb/looc(msg as text) set name = "LOOC" set desc = "Local OOC, seen only by those in view." set category = "OOC" - if(GLOB.say_disabled) //This is here to try to identify lag problems - to_chat(usr, span_danger(" Speech is currently admin-disabled.")) + looc_message(msg) + +/client/verb/looc_wallpierce(msg as text) + set name = "LOOC (Wallpierce)" + set desc = "Local OOC, seen by anyone within 7 tiles of you." + set category = "OOC" + + looc_message(msg, TRUE) + +/client/proc/looc_message(msg, wall_pierce) + if(GLOB.say_disabled) + to_chat(usr, span_danger("Speech is currently admin-disabled.")) return if(!mob) @@ -16,9 +28,9 @@ if(!holder) if(!GLOB.looc_allowed) - to_chat(src, span_danger(" LOOC is globally muted")) + to_chat(src, span_danger("LOOC is globally muted.")) return - if(handle_spam_prevention(msg,MUTE_OOC)) + if(handle_spam_prevention(msg, MUTE_OOC)) return if(findtext(msg, "byond://")) to_chat(src, span_boldannounce("Advertising other servers is not allowed.")) @@ -28,7 +40,7 @@ to_chat(src, span_danger("You cannot use LOOC (muted).")) return if(mob.stat) - to_chat(src, span_danger("You cannot use LOOC while unconscious or dead.")) //Skyrat change + to_chat(src, span_danger("You cannot use LOOC while unconscious or dead.")) return if(istype(mob, /mob/dead)) to_chat(src, span_danger("You cannot use LOOC while ghosting.")) @@ -37,35 +49,43 @@ msg = emoji_parse(msg) mob.log_talk(msg,LOG_OOC, tag="LOOC") - - var/list/heard = get_hearers_in_view(7, get_top_level_mob(src.mob)) + var/list/heard + if(wall_pierce) + heard = get_hearers_in_range(LOOC_RANGE, get_top_level_mob(src.mob)) + else + heard = get_hearers_in_view(LOOC_RANGE, get_top_level_mob(src.mob)) //so the ai can post looc text - if(istype(mob,/mob/living/silicon/ai)) + if(istype(mob, /mob/living/silicon/ai)) var/mob/living/silicon/ai/ai = mob - heard = get_hearers_in_view(7, ai.eyeobj) + if(wall_pierce) + heard = get_hearers_in_range(LOOC_RANGE, ai.eyeobj) + else + heard = get_hearers_in_view(LOOC_RANGE, ai.eyeobj) //so the ai can see looc text for(var/mob/living/silicon/ai/ai as anything in GLOB.ai_list) if(ai.client && !(ai in heard) && (ai.eyeobj in heard)) heard += ai var/list/admin_seen = list() - for(var/mob/M in heard) - if(!M.client) + for(var/mob/hearing in heard) + if(!hearing.client) continue - var/client/C = M.client - if (C.holder) - admin_seen[C] = TRUE + var/client/hearing_client = hearing.client + if (hearing_client.holder) + admin_seen[hearing_client] = TRUE continue //they are handled after that - if (isobserver(M)) + if (isobserver(hearing)) continue //Also handled later. - to_chat(C, span_looc(span_prefix("LOOC: [src.mob.name]: [msg]"))) + to_chat(hearing_client, span_looc(span_prefix("LOOC: [src.mob.name]: [msg]"))) for(var/cli in GLOB.admins) - var/client/C = cli - if (admin_seen[C]) - to_chat(C, span_looc("[ADMIN_FLW(usr)] LOOC: [src.key]/[src.mob.name]: [msg]")) - else if (C.prefs.read_preference(/datum/preference/toggle/admin/see_looc)) - to_chat(C, span_rlooc("[ADMIN_FLW(usr)] (R)LOOC: [src.key]/[src.mob.name]: [msg]")) + var/client/cli_client = cli + if (admin_seen[cli_client]) + to_chat(cli_client, span_looc("[ADMIN_FLW(usr)] LOOC: [src.key]/[src.mob.name]: [msg]")) + else if (cli_client.prefs.read_preference(/datum/preference/toggle/admin/see_looc)) + to_chat(cli_client, span_rlooc("[ADMIN_FLW(usr)] (R)LOOC: [src.key]/[src.mob.name]: [msg]")) + +#undef LOOC_RANGE