diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 7a51eb5defb..695ab933aeb 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -113,6 +113,10 @@ #define COMPANY_ALIGNMENTS list(COMPANY_LOYAL,COMPANY_SUPPORTATIVE,COMPANY_NEUTRAL,COMPANY_SKEPTICAL,COMPANY_OPPOSED) +// Defines the argument used for get_mobs_and_objs_in_view_fast +#define GHOSTS_ALL_HEAR 1 +#define ONLY_GHOSTS_IN_VIEW 0 + // Defines mob sizes, used by lockers and to determine what is considered a small sized mob, etc. #define MOB_LARGE 16 diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 1210ba9f3e8..85548fe6352 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -245,6 +245,41 @@ . += M return . +/proc/get_mobs_and_objs_in_view_fast(var/turf/T, var/range, var/list/mobs, var/list/objs, var/checkghosts = GHOSTS_ALL_HEAR) + + var/list/hear = list() + DVIEW(hear, range, T, INVISIBILITY_MAXIMUM) + var/list/hearturfs = list() + + for(var/am in hear) + var/atom/movable/AM = am + if(ismob(AM)) + mobs += AM + hearturfs += AM.locs[1] + else if(isobj(AM)) + objs += AM + hearturfs += AM.locs[1] + + + for(var/m in player_list) + var/mob/M = m + if(checkghosts == GHOSTS_ALL_HEAR && M.stat == DEAD && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS)) + mobs |= M + continue + if(M.loc && M.locs[1] in hearturfs) + mobs |= M + + + + for(var/o in listening_objects) + var/obj/O = o + if(O && O.loc && O.locs[1] in hearturfs) + objs |= O + + + + + #define SIGN(X) ((X<0)?-1:1) proc diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 132587422cb..44751295b56 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -458,22 +458,22 @@ its easier to just keep the beam vertical. // 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/messageturfs = list()//List of turfs we broadcast to. - var/list/messagemobs = list()//List of living mobs nearby who can hear it, and distant ghosts who've chosen to hear it - for (var/turf in view(world.view, get_turf(src))) - messageturfs += turf +/atom/proc/visible_message(var/message, var/blind_message, var/range = world.view) + var/turf/T = get_turf(src) + var/list/mobs = list() + var/list/objs = list() + get_mobs_and_objs_in_view_fast(T,range, mobs, objs, ONLY_GHOSTS_IN_VIEW) - for(var/A in player_list) - var/mob/M = A - if (!M.client || istype(M, /mob/new_player)) - continue - if(get_turf(M) in messageturfs) - messagemobs += M + for(var/o in objs) + var/obj/O = o + O.show_message(message,1,blind_message,2) - for(var/A in messagemobs) - var/mob/M = A - M.show_message(message, 1, blind_message, 2) + for(var/m in mobs) + var/mob/M = m + if(M.see_invisible >= invisibility) + M.show_message(message,1,blind_message,2) + else if(blind_message) + M.show_message(blind_message, 2) // Show a message to all mobs and objects in earshot of this atom // Use for objects performing audible actions @@ -485,18 +485,18 @@ its easier to just keep the beam vertical. var/range = world.view if(hearing_distance) range = hearing_distance - var/list/hear = get_mobs_or_objects_in_view(range,src) + var/turf/T = get_turf(src) + var/list/mobs = list() + var/list/objs = list() + get_mobs_and_objs_in_view_fast(T,range, mobs, objs, ONLY_GHOSTS_IN_VIEW) + + for(var/m in mobs) + var/mob/M = m + M.show_message(message,2,deaf_message,1) + for(var/o in objs) + var/obj/O = o + O.show_message(message,2,deaf_message,1) - 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) - /atom/proc/change_area(var/area/oldarea, var/area/newarea) change_area_name(oldarea.name, newarea.name) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 24faa63f439..008e9baef29 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -63,9 +63,11 @@ var/global/list/default_medbay_channels = list( ..() wires = new(src) internal_channels = default_internal_channels.Copy() + listening_objects += src /obj/item/device/radio/Destroy() qdel(wires) + listening_objects -= src wires = null if(radio_controller) radio_controller.remove_object(src, frequency) diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm index 063e7a85cea..7e591b4a679 100644 --- a/code/game/objects/items/devices/spy_bug.dm +++ b/code/game/objects/items/devices/spy_bug.dm @@ -23,6 +23,11 @@ ..() radio = new(src) camera = new(src) + listening_objects += src + +/obj/item/device/spy_bug/Destroy() + listening_objects -= src + return ..() /obj/item/device/spy_bug/examine(mob/user) . = ..(user, 0) @@ -62,6 +67,11 @@ /obj/item/device/spy_monitor/New() radio = new(src) + listening_objects += src + +/obj/item/device/spy_monitor/Destroy() + listening_objects -= src + return ..() /obj/item/device/spy_monitor/examine(mob/user) . = ..(user, 1) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index e59d3e993b5..3ed02fe7d3a 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -20,6 +20,14 @@ throw_speed = 4 throw_range = 20 +/obj/item/device/taperecorder/New() + ..() + listening_objects += src + +/obj/item/device/taperecorder/Destroy() + listening_objects -= src + return ..() + /obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg, var/verb="says", datum/language/speaking=null) if(recording) timestamp += timerecorded diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 3f262f84e17..ecd9a8a610f 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -50,7 +50,7 @@ Destroy() if(part) part.implants.Remove(src) - ..() + return ..() /obj/item/weapon/implant/tracking name = "tracking implant" @@ -162,6 +162,7 @@ Implant Specifics:
"} if (malfunction == MALFUNCTION_PERMANENT) return + var/need_gib = null if(istype(imp_in, /mob/)) var/mob/T = imp_in @@ -252,6 +253,15 @@ Implant Specifics:
"} explosion(get_turf(imp_in), -1, -1, 2, 3) qdel(src) +/obj/item/weapon/implant/explosive/New() + ..() + listening_objects += src + +/obj/item/weapon/implant/explosive/Destroy() + listening_objects -= src + return ..() + + /obj/item/weapon/implant/chem name = "chemical implant" desc = "Injects things." diff --git a/code/global.dm b/code/global.dm index 1ef56d9bf1b..0be6248f484 100644 --- a/code/global.dm +++ b/code/global.dm @@ -17,6 +17,8 @@ var/global/list/sec_hud_users = list() // List of all entities using var/global/list/hud_icon_reference = list() var/global/list/janitorial_supplies = list() // List of all the janitorial supplies on the map that the PDA cart may be tracking. +var/global/list/listening_objects = list() // List of objects that need to be able to hear, used to avoid recursive searching through contents. + var/global/list/global_mutations = list() // List of hidden mutation things. diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 021216f2181..c29731c677f 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -211,6 +211,15 @@ return 1 +/obj/item/device/assembly_holder/New() + ..() + listening_objects += src + +/obj/item/device/assembly_holder/Destroy() + listening_objects -= src + return ..() + + /obj/item/device/assembly_holder/hear_talk(mob/living/M as mob, msg, verb, datum/language/speaking) if(a_right) a_right.hear_talk(M,msg,verb,speaking) diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm index 7e8c89cc796..eac18f4afd1 100644 --- a/code/modules/assembly/voice.dm +++ b/code/modules/assembly/voice.dm @@ -7,6 +7,14 @@ var/listening = 0 var/recorded //the activation message +/obj/item/device/assembly/voice/New() + ..() + listening_objects += src + +/obj/item/device/assembly/voice/Destroy() + listening_objects -= src + return ..() + /obj/item/device/assembly/voice/hear_talk(mob/living/M as mob, msg) if(listening) recorded = msg @@ -33,4 +41,4 @@ /obj/item/device/assembly/voice/toggle_secure() . = ..() - listening = 0 \ No newline at end of file + listening = 0 diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index e2883537c81..98858cef311 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -225,10 +225,9 @@ proc/get_radio_key_from_channel(var/channel) if (speech_sound) sound_vol *= 0.5 - var/turf/T = get_turf(src) - var/list/listening = list() var/list/listening_obj = list() + var/turf/T = get_turf(src) if(T) //make sure the air can transmit speech - speaker's side @@ -241,26 +240,8 @@ 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/hearturfs = list() + get_mobs_and_objs_in_view_fast(T, message_range, listening, listening_obj) - for(var/I in hear) - if(ismob(I)) - var/mob/M = I - listening += M - hearturfs += M.locs[1] - else if(isobj(I)) - var/obj/O = I - hearturfs += O.locs[1] - listening_obj |= O - - - for(var/mob/M in player_list) - if(src.client && M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS)) - listening |= M - continue - if(M.loc && M.locs[1] in hearturfs) - listening |= M var/speech_bubble_test = say_test(message) var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]") diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 179fc231f79..ff44620e461 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -158,21 +158,26 @@ 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 - var/msg = message - if(self_message && M==src) - msg = self_message - M.show_message( msg, 2, deaf_message, 1) + var/turf/T = get_turf(src) + var/list/mobs = list() + var/list/objs = list() + get_mobs_and_objs_in_view_fast(T, range, mobs, objs) + + + for(var/m in mobs) + var/mob/M = m + if(self_message && M==src) + M.show_message(self_message,2,deaf_message,1) + continue + + M.show_message(message,2,deaf_message,1) + + + for(var/o in objs) + var/obj/O = o + O.show_message(message,2,deaf_message,1) /mob/proc/findname(msg) for(var/mob/M in mob_list) diff --git a/code/modules/projectiles/guns/energy/lawgiver.dm b/code/modules/projectiles/guns/energy/lawgiver.dm index d8d3d91e797..a4c578e8de3 100644 --- a/code/modules/projectiles/guns/energy/lawgiver.dm +++ b/code/modules/projectiles/guns/energy/lawgiver.dm @@ -65,12 +65,20 @@ ) ) +/obj/item/weapon/gun/energy/lawgiver/New() + ..() + listening_objects += src + +/obj/item/weapon/gun/energy/lawgiver/Destroy() + listening_objects -= src + return ..() + /obj/item/weapon/gun/energy/lawgiver/proc/play_message() while (message_enabled && !message_disable) //Shut down command issued. Inform user that boardcasting has been stopped usr.audible_message("[usr]'s [src.name] broadcasts: [message]","") playsound(get_turf(src), 'sound/voice/halt.ogg', 100, 1, vary = 0) sleep(message_delay) - usr << "\red Broadcasting Message disabled" + usr << "Broadcasting Message disabled" message_enabled = 0 message_disable = 0 @@ -80,7 +88,7 @@ else src.dna = user.dna.unique_enzymes src.owner_name = user.real_name - user << "\blue You feel your palm heat up as the gun reads your DNA profile." + user << "You feel your palm heat up as the gun reads your DNA profile." desc += "
Linked to: [user.real_name]" return @@ -93,7 +101,7 @@ var/obj/item/organ/external/RA = H.get_organ("r_arm") var/active_hand = H.hand playsound(user, 'sound/weapons/lawgiver_idfail.ogg', 40, 1) - user << "\red You hear a soft beep from the gun and 'ID FAIL' flashes across the screen." + user << "You hear a soft beep from the gun and 'ID FAIL' flashes across the screen." user << "You feel a tiny prick in your hand!" user.drop_item() //Blow up Unauthorized Users Hand @@ -132,50 +140,50 @@ sel_mode = 1 projectile_type=/obj/item/projectile/bullet/pistol fire_sound='sound/weapons/Gunshot_smg.ogg' - usr << "\red [src.name] is now set to single shot mode." + usr << "[src.name] is now set to single shot mode." else if(findtext(msg,"rapidfire")) sel_mode = 2 projectile_type=/obj/item/projectile/bullet/pistol fire_sound='sound/weapons/Gunshot_smg.ogg' - usr << "\red [src.name] is now set to rapid fire mode." + usr << "[src.name] is now set to rapid fire mode." else if(findtext(msg,"highex") || findtext(msg,"grenade")) sel_mode = 3 projectile_type=/obj/item/projectile/bullet/gyro/law fire_sound='sound/effects/Explosion1.ogg' - usr << "\red [src.name] is now set to high explosive mode." + usr << "[src.name] is now set to high explosive mode." else if(findtext(msg,"stun")) sel_mode = 4 projectile_type=/obj/item/projectile/beam/stun fire_sound='sound/weapons/Taser.ogg' - usr << "\red [src.name] is now set to stun mode." + usr << "[src.name] is now set to stun mode." else if(findtext(msg,"hotshot") || findtext(msg,"incendiary")) sel_mode = 5 projectile_type=/obj/item/projectile/bullet/shotgun/incendiary fire_sound='sound/weapons/Gunshot.ogg' - usr << "\red [src.name] is now set to incendiary mode." + usr << "[src.name] is now set to incendiary mode." else if(findtext(msg,"armorpiercing") || findtext(msg,"execution")) sel_mode = 6 projectile_type=/obj/item/projectile/bullet/rifle/a556 fire_sound='sound/weapons/Gunshot.ogg' - usr << "\red [src.name] is now set to armorpiercing mode." + usr << "[src.name] is now set to armorpiercing mode." else if(findtext(msg,"pellets")) sel_mode = 7 projectile_type=/obj/item/projectile/bullet/pellet/shotgun fire_sound='sound/weapons/Gunshot.ogg' - usr << "\red [src.name] is now set to pellet mode." + usr << "[src.name] is now set to pellet mode." /* Other Stuff */ else if(findtext(msg,"reset") && (findtext(msg,"user") || findtext(msg,"dna"))) dna = null desc = default_desc - usr << "\red [src.name]´s owner has been reset. Do not attempt to fire [src.name] without rebinding a new owner" + usr << "[src.name]´s owner has been reset. Do not attempt to fire [src.name] without rebinding a new owner." else if((findtext(msg,"disable") || findtext(msg,"deactivate")) && findtext(msg,"crowdcontrol")) message_disable = 1 - usr << "\red [src.name]´s crowdcontrol deactivation sequence started" + usr << "[src.name]´s crowdcontrol deactivation sequence started." else if((findtext(msg,"enable") || findtext(msg,"activate")) && findtext(msg,"crowdcontrol")) if(message_enabled) //Check if a message is already broadcasting -> abort - usr << "\red [src.name] is already broadcasting a message." + usr << "[src.name] is already broadcasting a message." return - usr << "\red [src.name]´s crowdcontrol activation sequence started" + usr << "[src.name]´s crowdcontrol activation sequence started." message = "Citizens stay calm. Stand back from the crime scene. Interference with the crime scene carries an automatic brig sentence." message_enabled = 1 message_disable = 0 diff --git a/code/modules/research/xenoarchaeology/finds/finds_special.dm b/code/modules/research/xenoarchaeology/finds/finds_special.dm index af73f541d60..359ba673603 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_special.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_special.dm @@ -10,6 +10,7 @@ processing_objects.Add(src) spawning_id = pick("blood","holywater","lube","stoxin","ethanol","ice","glycerol","fuel","cleaner") + /obj/item/weapon/reagent_containers/glass/replenishing/process() reagents.add_reagent(spawning_id, 0.3) @@ -23,6 +24,12 @@ /obj/item/clothing/mask/gas/poltergeist/New() processing_objects.Add(src) + listening_objects += src + +/obj/item/clothing/mask/gas/poltergeist/Destroy() + processing_objects.Remove(src) + listening_objects -= src + return ..() /obj/item/clothing/mask/gas/poltergeist/process() if(heard_talk.len && istype(src.loc, /mob/living) && prob(10)) @@ -57,6 +64,12 @@ /obj/item/weapon/vampiric/New() ..() processing_objects.Add(src) + listening_objects += src + +/obj/item/weapon/vampiric/Destroy() + processing_objects.Remove(src) + listening_objects -= src + return ..() /obj/item/weapon/vampiric/process() //see if we've identified anyone nearby @@ -146,6 +159,10 @@ processing_objects.Add(src) loc_last_process = src.loc +/obj/effect/decal/cleanable/blood/splatter/animated/Destroy() + processing_objects.Remove(src) + return ..() + /obj/effect/decal/cleanable/blood/splatter/animated/process() if(target_turf && src.loc != target_turf) step_towards(src,target_turf) @@ -175,6 +192,10 @@ /obj/effect/shadow_wight/New() processing_objects.Add(src) +/obj/effect/shadow_wight/Destroy() + processing_objects.Remove(src) + return ..() + /obj/effect/shadow_wight/process() if(src.loc) src.loc = get_turf(pick(orange(1,src))) @@ -200,4 +221,4 @@ processing_objects.Remove(src) /obj/effect/shadow_wight/Bump(var/atom/obstacle) - obstacle << "\red You feel a chill run down your spine!" + obstacle << "You feel a chill run down your spine!" diff --git a/html/changelogs/Ccomp5950-saycodefix.yml b/html/changelogs/Ccomp5950-saycodefix.yml new file mode 100644 index 00000000000..ac92d82e3a5 --- /dev/null +++ b/html/changelogs/Ccomp5950-saycodefix.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Ccomp5950 + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Objects in bags and other containers (including your hands and pocket) will now hear speach again. This impacts radios, explosive implants, and the universal recorder."