From 37e8ca6194d19e7d6990a6ee717c03a89fd1a032 Mon Sep 17 00:00:00 2001 From: Cameron Lennox Date: Fri, 27 Dec 2024 18:43:15 -0500 Subject: [PATCH] Turret & Sound Optimizations (#16754) * Portable Turret Optimization Optimizes portable turrets. Takes from Chomp PR here: https://github.com/CHOMPStation2/CHOMPStation2/pull/8088 Optimizes them further by changing mobs_in_xray_view to mobs_in_view. Reason: mobs_in_xray_view was adding mobs that were out of sight (behind walls) to the target list and trying to do pathfinding to shoot them. If you had 20 mobs around a PoI with turrets, it'd use a LOT of CPU needlessly. Also adds in Chomp's /mobs.dm helpers as they're helpful. * Ports over Chompstation Sound Optimizations - Replaces for( listeners) with a check that sees if a listener is ALSO a hearer - Makes it so even if there is no vary, if someone has a frequency it uses the frequency for playsound_local From https://github.com/CHOMPStation2/CHOMPStation2/pull/8088 --- code/_helpers/mobs.dm | 37 +++++++++++++++++ code/game/machinery/portable_turret.dm | 40 +++++++------------ code/game/sound.dm | 21 +++++----- .../modules/mob/living/silicon/robot/robot.dm | 9 +++++ 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index e78123fe64e..0efc265b490 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -1,3 +1,40 @@ +/atom/movable/proc/get_mob() + if(buckled_mobs) return buckled_mobs.Copy() + +/obj/mecha/get_mob() + return occupant + +/obj/vehicle_old/train/get_mob() + return buckled_mobs + +/mob/get_mob() + return src + +/mob/living/bot/mulebot/get_mob() + if(load && istype(load, /mob/living)) + return list(src, load) + return src + +/proc/mobs_in_view(range, source) + var/list/mobs = list() + for(var/atom/movable/AM in view(range, source)) + var/M = AM.get_mob() + if(M) + mobs += M + + return mobs + +/// This gets a list of mobs ALL around us as if we had xray vision and can see through walls. +/// Currently only used in portable_turret.dm if you wish to see an example of how to use it. +/proc/mobs_in_xray_view(range, source) + var/list/mobs = list() + for(var/atom/movable/AM in orange(range, source)) + var/M = AM.get_mob() + if(M) + mobs += M + + return mobs + /proc/random_hair_style(gender, species = SPECIES_HUMAN) var/h_style = "Bald" diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 117ab2cda28..ecdc2e959ac 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -378,7 +378,7 @@ /obj/machinery/porta_turret/proc/isLocked(mob/user) if(locked && !issilicon(user)) to_chat(user, span_notice("Controls locked.")) - return 1 + return TRUE if(HasController()) return TRUE if(isrobot(user) || isAI(user)) @@ -656,7 +656,7 @@ /obj/machinery/porta_turret/proc/die() //called when the turret dies, ie, health <= 0 health = 0 stat |= BROKEN //enables the BROKEN bit - spark_system.start() //creates some sparks because they look cool + spark_system?.start() //creates some sparks because they look cool update_icon() /obj/machinery/porta_turret/process() @@ -675,27 +675,8 @@ var/list/targets = list() //list of primary targets var/list/secondarytargets = list() //targets that are least important - var/list/seenturfs = list() - for(var/turf/T in oview(world.view, src)) - seenturfs += T - - for(var/mob/M as anything in living_mob_list) - if(M.z != z || !(get_turf(M) in seenturfs)) // Skip - continue - switch(assess_living(M)) - if(TURRET_PRIORITY_TARGET) - targets += M - if(TURRET_SECONDARY_TARGET) - secondarytargets += M - - for(var/obj/mecha/M as anything in mechas_list) - if(M.z != z || !(get_turf(M) in seenturfs)) // Skip - continue - switch(assess_mecha(M)) - if(TURRET_PRIORITY_TARGET) - targets += M - if(TURRET_SECONDARY_TARGET) - secondarytargets += M + for(var/mob/M in mobs_in_view(world.view, src)) + assess_and_assign(M, targets, secondarytargets) if(!tryToShootAt(targets) && !tryToShootAt(secondarytargets) && --timeout <= 0) popDown() // no valid targets, close the cover @@ -704,6 +685,13 @@ use_power(20000) health = min(health+1, maxhealth) // 1HP for 20kJ +/obj/machinery/porta_turret/proc/assess_and_assign(mob/living/L, list/targets, list/secondarytargets) + switch(assess_living(L)) + if(TURRET_PRIORITY_TARGET) + targets += L + if(TURRET_SECONDARY_TARGET) + secondarytargets += L + /obj/machinery/porta_turret/proc/assess_living(var/mob/living/L) if(!istype(L)) return TURRET_NOT_TARGET @@ -714,7 +702,7 @@ if(faction && L.faction == faction) return TURRET_NOT_TARGET - if(!emagged && issilicon(L) && check_all == FALSE) // Don't target silica, unless told to neutralize everything. + if((!emagged && siliconaccess(L) && check_all == FALSE) || (issilicon(L) && !check_access && !check_all)) // Don't target silica, unless told to neutralize everything. return TURRET_NOT_TARGET if(L.stat == DEAD && !emagged) //if the perp is dead, no need to bother really @@ -730,7 +718,7 @@ return TURRET_NOT_TARGET if(check_synth || check_all) //If it's set to attack all non-silicons or everything, target them! - if(L.lying) + if(L.lying && (L.incapacitated(INCAPACITATION_KNOCKOUT) || L.incapacitated(INCAPACITATION_STUNNED))) // Crawling targets are dangerous, if they are able. return check_down ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET return TURRET_PRIORITY_TARGET @@ -747,7 +735,7 @@ if(assess_perp(L) < 4) return TURRET_NOT_TARGET //if threat level < 4, keep going - if(L.lying) //if the perp is lying down, it's still a target but a less-important target + if(L.lying && (L.incapacitated(INCAPACITATION_KNOCKOUT) || L.incapacitated(INCAPACITATION_STUNNED))) //if the perp is lying down, it's still a target but a less-important target - Crawling targets are dangerous, if they are able. return check_down ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee diff --git a/code/game/sound.dm b/code/game/sound.dm index bf178e51563..4b188cbff7c 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -14,10 +14,6 @@ var/sound/S = sound(get_sfx(soundin)) var/maxdistance = (world.view + extrarange) * 2 //VOREStation Edit - 3 to 2 var/list/listeners = player_list.Copy() - if(!ignore_walls) //these sounds don't carry through walls - for(var/mob/listen in listeners) - if(!(get_turf(listen) in hear(maxdistance,source))) - listeners -= listen for(var/mob/M as anything in listeners) if(!M || !M.client) continue @@ -27,11 +23,16 @@ var/area/A = T.loc if((A.flag_check(AREA_SOUNDPROOF) || area_source.flag_check(AREA_SOUNDPROOF)) && (A != area_source)) continue - var/distance = get_dist(T, turf_source) + //var/distance = get_dist(T, turf_source) Save get_dist for later because it's more expensive - if(distance <= maxdistance) - if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S, preference, volume_channel) + if(!T || T.z != turf_source.z) //^ +1 + continue + if(get_dist(T, turf_source) > maxdistance) + continue + if(!ignore_walls && !can_see(turf_source, T, length = maxdistance * 2)) + continue + + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S, preference, volume_channel) /mob/proc/check_sound_preference(list/preference) if(!islist(preference)) @@ -64,7 +65,7 @@ vol *= client.get_preference_volume_channel(VOLUME_CHANNEL_MASTER) S.volume = vol - if(vary) + if(vary || frequency) if(frequency) S.frequency = frequency else @@ -308,8 +309,6 @@ var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/body var/list/teppi_sound = list('sound/voice/teppi/gyooh1.ogg', 'sound/voice/teppi/gyooh2.ogg', 'sound/voice/teppi/gyooh3.ogg', 'sound/voice/teppi/gyooh4.ogg', 'sound/voice/teppi/gyooh5.ogg', 'sound/voice/teppi/gyooh6.ogg', 'sound/voice/teppi/snoot1.ogg', 'sound/voice/teppi/snoot2.ogg') var/list/talk_sound = list('sound/talksounds/a.ogg','sound/talksounds/b.ogg','sound/talksounds/c.ogg','sound/talksounds/d.ogg','sound/talksounds/e.ogg','sound/talksounds/f.ogg','sound/talksounds/g.ogg','sound/talksounds/h.ogg') var/list/emote_sound = list('sound/talksounds/me_a.ogg','sound/talksounds/me_b.ogg','sound/talksounds/me_c.ogg','sound/talksounds/me_d.ogg','sound/talksounds/me_e.ogg','sound/talksounds/me_f.ogg') - -//Goon sounds var/list/goon_speak_one_sound = list('sound/talksounds/goon/speak_1.ogg', 'sound/talksounds/goon/speak_1_ask.ogg', 'sound/talksounds/goon/speak_1_exclaim.ogg') var/list/goon_speak_two_sound = list('sound/talksounds/goon/speak_2.ogg', 'sound/talksounds/goon/speak_2_ask.ogg', 'sound/talksounds/goon/speak_2_exclaim.ogg') var/list/goon_speak_three_sound = list('sound/talksounds/goon/speak_3.ogg', 'sound/talksounds/goon/speak_3_ask.ogg', 'sound/talksounds/goon/speak_3_exclaim.ogg') diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index d30ef613efd..8f0b9a34121 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1481,3 +1481,12 @@ robotact?.update_static_data_for_all_viewers() . = ..() + +/// This proc checks to see if a borg has access to whatever they're interacting with +/obj/proc/siliconaccess(mob/user) + var/mob/living/silicon/robot/R = user + if(istype(R)) + return check_access(R.idcard) + if(issilicon(user)) + return TRUE + return FALSE