diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 60e46d4ca66..9aa16f91b5a 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -156,37 +156,35 @@ // 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/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1) +/proc/recursive_content_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_mobs = 1, var/include_objects = 1) - //debug_mob += O.contents.len if(!recursion_limit) return L - for(var/atom/A in O.contents) - if(ismob(A)) - var/mob/M = A - if(client_check && !M.client) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) - continue - if(sight_check && !isInSight(A, O)) - continue - L |= M - //world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" + for(var/I in O.contents) - else if(include_radio && istype(A, /obj/item/device/radio)) - if(sight_check && !isInSight(A, O)) - continue - L |= A + if(ismob(I)) + if(!sight_check || isInSight(I, O)) + L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects) + if(include_mobs) + if(client_check) + var/mob/M = I + if(M.client) + L |= M + else + L |= I + + else if(istype(I,/obj/)) + if(!sight_check || isInSight(I, O)) + L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects) + if(include_objects) + L |= I - if(isobj(A) || ismob(A)) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) 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. +// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code. -/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. +/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1) var/turf/T = get_turf(source) var/list/hear = list() @@ -196,17 +194,17 @@ var/list/range = hear(R, T) - for(var/atom/A in range) - if(ismob(A)) - var/mob/M = A - if(M.client) - hear += M - //world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" - else if(istype(A, /obj/item/device/radio)) - hear += A - - if(isobj(A) || ismob(A)) - hear |= recursive_mob_check(A, hear, 3, 1, 0, 1) + for(var/I in range) + if(ismob(I)) + hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects) + if(include_mobs) + var/mob/M = I + if(M.client) + hear += M + else if(istype(I,/obj/)) + hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects) + if(include_objects) + hear += I return hear diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 742c6389a95..c789958dc94 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -459,3 +459,44 @@ its easier to just keep the beam vertical. return 1 else return 0 + +// Show a message to all mobs and objects in sight of this atom +// Use for objects performing visible actions +// message is output to anyone who can see, e.g. "The [src] does something!" +// blind_message (optional) is what blind people will hear e.g. "You hear something!" +/atom/proc/visible_message(var/message, var/blind_message) + + var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null) + + for(var/I in see) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 1, blind_message, 2) + else if(ismob(I)) + var/mob/M = I + if(M.see_invisible >= invisibility) // Cannot view the invisible + M.show_message( message, 1, blind_message, 2) + +// Show a message to all mobs and objects in earshot of this atom +// Use for objects performing audible actions +// message is the message output to anyone who can hear. +// deaf_message (optional) is what deaf people will see. +// hearing_distance (optional) is the range, how many tiles away the message can be heard. +/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance) + + var/range = world.view + if(hearing_distance) + range = hearing_distance + var/list/hear = get_mobs_or_objects_in_view(range,src) + + for(var/I in hear) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 2, deaf_message, 1) + else if(ismob(I)) + var/mob/M = I + M.show_message( message, 2, deaf_message, 1) \ No newline at end of file diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 0f8d666de98..ed315cf7473 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -252,18 +252,6 @@ radio.talk_into(M, text) return -/obj/mecha/see_emote(mob/living/M, text) - if(occupant && occupant.client) - var/rendered = "[text]" - occupant.show_message(rendered, 2) - ..() - -/obj/mecha/show_message(msg, type, alt, alt_type) - if(occupant && occupant.client) - var/rendered = "[msg]" - occupant.show_message(rendered, type) - ..() - //////////////////////////// ///// Action processing //// //////////////////////////// diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 0e5116f5d83..c131c846a73 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -456,7 +456,7 @@ var/range = receive_range(freq, level) if(range > -1) - return get_mobs_in_view(canhear_range, src) + return get_mobs_or_objects_in_view(canhear_range, src) /obj/item/device/radio/examine(mob/user) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index ee2138d0a22..2306c330577 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -444,24 +444,6 @@ src.quick_empty() return 1 -/obj/item/weapon/storage/hear_talk(mob/M as mob, text, verb, datum/language/speaking) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.hear_talk(M, text, verb, speaking) - -/obj/item/weapon/storage/see_emote(mob/M as mob, text, var/emote_type) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.see_emote(M, text, emote_type) - -/obj/item/weapon/storage/show_message(msg, type, alt, alt_type) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.show_message(msg, type, alt, alt_type) - //Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). //Returns -1 if the atom was not found on container. /atom/proc/storage_depth(atom/container) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 960eab6712c..09304d1ea2f 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -142,5 +142,5 @@ /obj/proc/see_emote(mob/M as mob, text, var/emote_type) return -/obj/proc/show_message(msg, type, alt, alt_type) +/obj/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index e9414957476..41cd5308f60 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -296,24 +296,6 @@ else icon_state = icon_opened -/obj/structure/closet/hear_talk(mob/M as mob, text, verb, datum/language/speaking) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.hear_talk(M, text, verb, speaking) - -/obj/structure/closet/see_emote(mob/M as mob, text, var/emote_type) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.see_emote(M, text, emote_type) - -/obj/structure/closet/show_message(msg, type, alt, alt_type) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.show_message(msg, type, alt, alt_type) - /obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys", var/wallbreaker) if(!damage || !wallbreaker) return diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 82fef02e97c..e35e4a6eb22 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -105,7 +105,7 @@ log_ooc("(LOCAL) [mob.name]/[key] : [msg]") var/mob/source = src.mob - var/list/heard = get_mobs_in_view(7, source) + var/list/heard = get_mobs_or_objects_in_view(7, source, 1, 0) var/display_name = source.key if(holder && holder.fakekey) diff --git a/code/modules/clothing/suits/storage.dm b/code/modules/clothing/suits/storage.dm index 8348e76ec90..f82eebc1cf3 100644 --- a/code/modules/clothing/suits/storage.dm +++ b/code/modules/clothing/suits/storage.dm @@ -29,18 +29,6 @@ pockets.emp_act(severity) ..() -/obj/item/clothing/suit/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking) - pockets.hear_talk(M, msg, verb, speaking) - ..() - -/obj/item/clothing/suit/storage/see_emote(mob/M as mob, text, var/emote_type) - pockets.see_emote(M, text, emote_type) - ..() - -/obj/item/clothing/suit/storage/show_message(msg, type, alt, alt_type) - pockets.show_message(msg, type, alt, alt_type) - ..() - //Jackets with buttons, used for labcoats, IA jackets, First Responder jackets, and brown jackets. /obj/item/clothing/suit/storage/toggle var/icon_open diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index 4b9f4410b19..82fb37de366 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -34,18 +34,6 @@ hold.emp_act(severity) ..() -/obj/item/clothing/accessory/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking) - hold.hear_talk(M, msg, verb, speaking) - ..() - -/obj/item/clothing/accessory/storage/see_emote(mob/M as mob, text, var/emote_type) - hold.see_emote(M, text, emote_type) - ..() - -/obj/item/clothing/accessory/storage/show_message(msg, type, alt, alt_type) - hold.show_message(msg, type, alt, alt_type) - ..() - /obj/item/clothing/accessory/storage/attack_self(mob/user as mob) user << "You empty [src]." var/turf/T = get_turf(src) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 5645773ea0b..54f31d5b5ba 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -24,8 +24,6 @@ if (message) log_emote("[name]/[key] : [message]") - var/list/seeing_obj = list() //For objs that need to see emotes. You can use see_emote(), which is based off of hear_talk() - //Hearing gasp and such every five seconds is not good emotes were not global for a reason. // Maybe some people are okay with that. @@ -37,58 +35,31 @@ if(findtext(message," snores.")) //Because we have so many sleeping people. break if(M.stat == 2 && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) + M.show_message(message, m_type) - for(var/I in view(world.view, get_turf(usr))) //get_turf is needed to stop weirdness with x-ray. - if(istype(I, /mob/)) - var/mob/M = I - for(var/obj/O in M.contents) - seeing_obj |= O - else if(istype(I, /obj/)) - var/obj/O = I - seeing_obj |= O - - // Type 1 (Visual) emotes are sent to anyone in view of the item if (m_type & 1) - //for (var/mob/O in viewers(src, null)) - for (var/mob/O in viewers(get_turf(src), null)) //This may break people with x-ray being able to see emotes across walls, - //but this saves many headaches down the road, involving mechs and pAIs. - //x-ray is so rare these days anyways. + var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null) + for(var/I in see) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.see_emote(src, message, 1) + else if(ismob(I)) + var/mob/M = I + M.show_message(message, 1) - if(O.status_flags & PASSEMOTES) - - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message(message, m_type) - - for(var/mob/living/M in O.contents) - M.show_message(message, m_type) - - O.show_message(message, m_type) - - for(var/obj/O in seeing_obj) - spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.see_emote(src, message, 1) - - // Type 2 (Audible) emotes are sent to anyone in hear range - // of the *LOCATION* -- this is important for AIs/pAIs to be heard else if (m_type & 2) - for (var/mob/O in hearers(get_turf(src), null)) - - if(O.status_flags & PASSEMOTES) - - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message(message, m_type) - - for(var/mob/living/M in O.contents) - M.show_message(message, m_type) - - O.show_message(message, m_type) - - for(var/obj/O in seeing_obj) - spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.see_emote(src, message, 2) + var/list/hear = get_mobs_or_objects_in_view(world.view,src) + for(var/I in hear) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.see_emote(src, message, 2) + else if(ismob(I)) + var/mob/M = I + M.show_message(message, 2) /mob/proc/emote_dead(var/message) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 8919ab0952a..a126bccc876 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -238,17 +238,15 @@ proc/get_radio_key_from_channel(var/channel) italics = 1 sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact - var/list/hear = hear(message_range, T) + var/list/hear = get_mobs_or_objects_in_view(message_range,src) var/list/hearturfs = list() for(var/I in hear) - if(istype(I, /mob/)) + if(ismob(I)) var/mob/M = I listening += M hearturfs += M.locs[1] - for(var/obj/O in M.contents) - listening_obj |= O - else if(istype(I, /obj/)) + else if(isobj(I)) var/obj/O = I hearturfs += O.locs[1] listening_obj |= O diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a983d649d8a..762c318fa4f 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -44,7 +44,7 @@ src << msg return -// Show a message to all mobs in sight of this one +// Show a message to all mobs and objects in sight of this one // This would be for visible actions by the src mob // message is the message output to anyone who can see e.g. "[src] does something!" // self_message (optional) is what the src mob sees e.g. "You do something!" @@ -52,77 +52,21 @@ /mob/visible_message(var/message, var/self_message, var/blind_message) - var/list/seeing_obj = list() + var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null) - for(var/I in view(world.view, get_turf(usr))) //get_turf is needed to stop weirdness with x-ray. - if(istype(I, /mob/)) + for(var/I in see) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 1, blind_message, 2) + else if(ismob(I)) var/mob/M = I - for(var/obj/O in M.contents) - seeing_obj |= O - else if(istype(I, /obj/)) - var/obj/O = I - seeing_obj |= O - - for (var/mob/O in viewers(get_turf(src), null)) - if(O.see_invisible < invisibility) - continue // Cannot view the invisible - var/msg = message - if(O.status_flags & PASSEMOTES) - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message( msg, 1, blind_message, 2) - for(var/mob/living/M in O.contents) + if(M.see_invisible >= invisibility) // Cannot view the invisible + var/msg = message + if(self_message && M==src) + msg = self_message M.show_message( msg, 1, blind_message, 2) - if(self_message && O==src) - msg = self_message - O.show_message( msg, 1, blind_message, 2) - - for(var/obj/O in seeing_obj) - spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.show_message( message, 1, blind_message, 2) - - /* - for(var/mob/M in viewers(src)) - if(M.see_invisible < invisibility) - continue // Cannot view the invisible - var/msg = message - if(self_message && M==src) - msg = self_message - M.show_message( msg, 1, blind_message, 2) - */ - -// Show a message to all mobs in sight of this atom -// Use for objects performing visible actions -// message is output to anyone who can see, e.g. "The [src] does something!" -// blind_message (optional) is what blind people will hear e.g. "You hear something!" -/atom/proc/visible_message(var/message, var/blind_message) - - var/list/seeing_obj = list() - - for(var/I in view(world.view, get_turf(src))) //get_turf is needed to stop weirdness with x-ray. - if(istype(I, /mob/)) - var/mob/M = I - for(var/obj/O in M.contents) - seeing_obj |= O - else if(istype(I, /obj/)) - var/obj/O = I - seeing_obj |= O - - for (var/mob/O in viewers(get_turf(src), null)) - if(O.see_invisible < invisibility) - continue // Cannot view the invisible - var/msg = message - if(O.status_flags & PASSEMOTES) - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message( msg, 1, blind_message, 2) - for(var/mob/living/M in O.contents) - M.show_message( msg, 1, blind_message, 2) - O.show_message( msg, 1, blind_message, 2) - - for(var/obj/O in seeing_obj) - spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.show_message( message, 1, blind_message, 2) // Returns an amount of power drawn from the object (-1 if it's not viable). // If drain_check is set it will not actually drain power, just return a value. @@ -131,33 +75,31 @@ /atom/proc/drain_power(var/drain_check,var/surge, var/amount = 0) return -1 -// Show a message to all mobs in earshot of this one +// Show a message to all mobs and objects in earshot of this one // This would be for audible actions by the src mob // message is the message output to anyone who can hear. // self_message (optional) is what the src mob hears. // deaf_message (optional) is what deaf people will see. // hearing_distance (optional) is the range, how many tiles away the message can be heard. /mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message) - var/range = 7 - if(hearing_distance) - range = hearing_distance - var/msg = message - for(var/mob/M in get_mobs_in_view(range, src)) - if(self_message && M==src) - msg = self_message - M.show_message( msg, 2, deaf_message, 1) -// Show a message to all mobs in earshot of this atom -// Use for objects performing audible actions -// message is the message output to anyone who can hear. -// deaf_message (optional) is what deaf people will see. -// hearing_distance (optional) is the range, how many tiles away the message can be heard. -/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance) - var/range = 7 + var/range = world.view if(hearing_distance) range = hearing_distance - for(var/mob/M in get_mobs_in_view(range, src)) - M.show_message( message, 2, deaf_message, 1) + var/list/hear = get_mobs_or_objects_in_view(range,src) + + for(var/I in hear) + if(isobj(I)) + spawn(0) + if(I) //It's possible that it could be deleted in the meantime. + var/obj/O = I + O.show_message( message, 2, deaf_message, 1) + else if(ismob(I)) + var/mob/M = I + var/msg = message + if(self_message && M==src) + msg = self_message + M.show_message( msg, 2, deaf_message, 1) /mob/proc/findname(msg)