From 4686f6fcc4cab6d0d4cfa43617226eb6aec7a83a Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 26 Feb 2018 00:33:03 -0500 Subject: [PATCH 1/5] POLARIS: Port's /tg/'s current sound.dm, plus pref It's mostly the same, just a little more efficient. I added a 'preferences' var to pass a datum and decide whether or not to play the sound for that client based on some preference. --- code/__defines/atmos.dm | 2 - code/__defines/sound.dm | 56 ++++++++ code/game/area/areas.dm | 13 +- code/game/sound.dm | 223 +++++++++++------------------- code/modules/mob/living/living.dm | 16 ++- code/modules/mob/mob_helpers.dm | 7 + polaris.dme | 1 + 7 files changed, 171 insertions(+), 147 deletions(-) create mode 100644 code/__defines/sound.dm diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm index bd9175aab1..13964a6f80 100644 --- a/code/__defines/atmos.dm +++ b/code/__defines/atmos.dm @@ -21,8 +21,6 @@ #define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD * BREATH_PERCENTAGE * 0.16) #define HUMAN_HEAT_CAPACITY 280000 //J/K For 80kg person -#define SOUND_MINIMUM_PRESSURE 10 - #define PRESSURE_DAMAGE_COEFFICIENT 4 // The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE. #define MAX_HIGH_PRESSURE_DAMAGE 4 // This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :( #define LOW_PRESSURE_DAMAGE 2 // The amount of damage someone takes when in a low pressure area. (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value). diff --git a/code/__defines/sound.dm b/code/__defines/sound.dm new file mode 100644 index 0000000000..6fae2fadcb --- /dev/null +++ b/code/__defines/sound.dm @@ -0,0 +1,56 @@ +//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on +#define CHANNEL_LOBBYMUSIC 1024 +#define CHANNEL_ADMIN 1023 +#define CHANNEL_VOX 1022 +#define CHANNEL_JUKEBOX 1021 +#define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats +#define CHANNEL_AMBIENCE_FORCED 1019 +#define CHANNEL_AMBIENCE 1018 +#define CHANNEL_BUZZ 1017 +#define CHANNEL_BICYCLE 1016 + +//THIS SHOULD ALWAYS BE THE LOWEST ONE! +//KEEP IT UPDATED + +#define CHANNEL_HIGHEST_AVAILABLE 1015 + +#define SOUND_MINIMUM_PRESSURE 10 +#define FALLOFF_SOUNDS 0.5 + +//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more. +#define GENERIC 0 +#define PADDED_CELL 1 +#define ROOM 2 +#define BATHROOM 3 +#define LIVINGROOM 4 +#define STONEROOM 5 +#define AUDITORIUM 6 +#define CONCERT_HALL 7 +#define CAVE 8 +#define ARENA 9 +#define HANGAR 10 +#define CARPETED_HALLWAY 11 +#define HALLWAY 12 +#define STONE_CORRIDOR 13 +#define ALLEY 14 +#define FOREST 15 +#define CITY 16 +#define MOUNTAINS 17 +#define QUARRY 18 +#define PLAIN 19 +#define PARKING_LOT 20 +#define SEWER_PIPE 21 +#define UNDERWATER 22 +#define DRUGGED 23 +#define DIZZY 24 +#define PSYCHOTIC 25 + +#define STANDARD_STATION STONEROOM +#define LARGE_ENCLOSED HANGAR +#define SMALL_ENCLOSED BATHROOM +#define TUNNEL_ENCLOSED CAVE +#define LARGE_SOFTFLOOR CARPETED_HALLWAY +#define MEDIUM_SOFTFLOOR LIVINGROOM +#define SMALL_SOFTFLOOR ROOM +#define ASTEROID CAVE +#define SPACE UNDERWATER diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index e9d93b48a3..54a3da3f75 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -248,23 +248,26 @@ var/list/mob/living/forced_ambiance_list = new // If we previously were in an area with force-played ambiance, stop it. if(L in forced_ambiance_list) - L << sound(null, channel = 1) + L << sound(null, channel = CHANNEL_AMBIENCE_FORCED) forced_ambiance_list -= L if(!L.client.ambience_playing) L.client.ambience_playing = 1 - L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) + L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_AMBIENCE) if(forced_ambience) if(forced_ambience.len) forced_ambiance_list |= L - L << sound(pick(forced_ambience), repeat = 1, wait = 0, volume = 25, channel = 1) + var/sound/chosen_ambiance = pick(forced_ambience) + if(!istype(chosen_ambiance)) + chosen_ambiance = sound(chosen_ambiance, repeat = 1, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE_FORCED) + L << chosen_ambiance else - L << sound(null, channel = 1) + L << sound(null, channel = CHANNEL_AMBIENCE_FORCED) else if(src.ambience.len && prob(35)) if((world.time >= L.client.played + 600)) var/sound = pick(ambience) - L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1) + L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE) L.client.played = world.time /area/proc/gravitychange(var/gravitystate = 0, var/area/A) diff --git a/code/game/sound.dm b/code/game/sound.dm index afeeaafcae..2db1e433bd 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,107 +1,50 @@ -//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more. -#define GENERIC 0 -#define PADDED_CELL 1 -#define ROOM 2 -#define BATHROOM 3 -#define LIVINGROOM 4 -#define STONEROOM 5 -#define AUDITORIUM 6 -#define CONCERT_HALL 7 -#define CAVE 8 -#define ARENA 9 -#define HANGAR 10 -#define CARPETED_HALLWAY 11 -#define HALLWAY 12 -#define STONE_CORRIDOR 13 -#define ALLEY 14 -#define FOREST 15 -#define CITY 16 -#define MOUNTAINS 17 -#define QUARRY 18 -#define PLAIN 19 -#define PARKING_LOT 20 -#define SEWER_PIPE 21 -#define UNDERWATER 22 -#define DRUGGED 23 -#define DIZZY 24 -#define PSYCHOTIC 25 - -#define STANDARD_STATION STONEROOM -#define LARGE_ENCLOSED HANGAR -#define SMALL_ENCLOSED BATHROOM -#define TUNNEL_ENCLOSED CAVE -#define LARGE_SOFTFLOOR CARPETED_HALLWAY -#define MEDIUM_SOFTFLOOR LIVINGROOM -#define SMALL_SOFTFLOOR ROOM -#define ASTEROID CAVE -#define SPACE UNDERWATER - -var/list/shatter_sound = list('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') -var/list/explosion_sound = list('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') -var/list/spark_sound = list('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg') -var/list/rustle_sound = list('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') -var/list/punch_sound = list('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') -var/list/clown_sound = list('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') -var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') -var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') -var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') -var/list/fracture_sound = list('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') -var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg') -var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg') -var/list/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') -var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') -var/list/can_sound = list('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') -var/list/geiger_sound = list('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') -var/list/geiger_weak_sound = list('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') - -//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') - -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/frequency) - - soundin = get_sfx(soundin) // same sound for everyone - +/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, preference = null) if(isarea(source)) - error("[source] is an area and is trying to make the sound: [soundin]") + throw EXCEPTION("playsound(): source is an area") return - frequency = isnull(frequency) ? get_rand_frequency() : frequency // Same frequency for everybody var/turf/turf_source = get_turf(source) + //allocate a channel if necessary now so its the same for everyone + channel = channel || open_sound_channel() + // Looping through the player list has the added bonus of working for mobs inside containers - for (var/P in player_list) + var/sound/S = sound(get_sfx(soundin)) + var/maxdistance = (world.view + extrarange) * 3 + var/list/listeners = player_list + if(!ignore_walls) //these sounds don't carry through walls + listeners = listeners & hearers(maxdistance,turf_source) + for(var/P in listeners) var/mob/M = P if(!M || !M.client) continue + var/turf/T = get_turf(M) + var/distance = get_dist(T, turf_source) - var/distance = get_dist(M, turf_source) - if(distance <= (world.view + extrarange) * 3) - var/turf/T = get_turf(M) - + if(distance <= maxdistance) if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S) -var/const/FALLOFF_SOUNDS = 0.5 +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, channel = 0, pressure_affected = TRUE, sound/S, preference) + if(!client || ear_deaf > 0) + return + if(preference && !client.is_preference_enabled(preference)) + return -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global) - if(!src.client || ear_deaf > 0) return - soundin = get_sfx(soundin) + if(!S) + S = sound(get_sfx(soundin)) - var/sound/S = sound(soundin) S.wait = 0 //No queue - S.channel = 0 //Any channel + S.channel = channel || open_sound_channel() S.volume = vol - S.environment = -1 - if (vary) + + if(vary) if(frequency) S.frequency = frequency else S.frequency = get_rand_frequency() - //sound volume falloff with pressure - var/pressure_factor = 1.0 - if(isturf(turf_source)) - // 3D sounds, the technology is here! var/turf/T = get_turf(src) //sound volume falloff with distance @@ -109,24 +52,32 @@ var/const/FALLOFF_SOUNDS = 0.5 S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. - var/datum/gas_mixture/hearer_env = T.return_air() - var/datum/gas_mixture/source_env = turf_source.return_air() + //Atmosphere affects sound + var/pressure_factor = 1 + if(pressure_affected) + var/datum/gas_mixture/hearer_env = T.return_air() + var/datum/gas_mixture/source_env = turf_source.return_air() - if (hearer_env && source_env) - var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(hearer_env && source_env) + var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(pressure < ONE_ATMOSPHERE) + pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) + else //space + pressure_factor = 0 - if (pressure < ONE_ATMOSPHERE) - pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) - else //in space - pressure_factor = 0 + if(distance <= 1) + pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound - if (distance <= 1) - pressure_factor = max(pressure_factor, 0.15) //hearing through contact + S.volume *= pressure_factor + //End Atmosphere affecting sound - S.volume *= pressure_factor + //Don't bother with doing anything below. + if(S.volume <= 0) + return //No sound - if (S.volume <= 0) - return //no volume means no sound + //Apply a sound environment. + if(!is_global) + S.environment = get_sound_env(pressure_factor) var/dx = turf_source.x - T.x // Hearing from the right/left S.x = dx @@ -136,58 +87,52 @@ var/const/FALLOFF_SOUNDS = 0.5 S.y = 1 S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) - if(!is_global) - - if(istype(src,/mob/living/)) - var/mob/living/M = src - if (M.hallucination) - S.environment = PSYCHOTIC - else if (M.druggy) - S.environment = DRUGGED - else if (M.drowsyness) - S.environment = DIZZY - else if (M.confused) - S.environment = DIZZY - else if (M.sleeping) - S.environment = UNDERWATER - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env - - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env - src << S +/proc/sound_to_playing_players(sound, volume = 100, vary) + sound = get_sfx(sound) + for(var/M in player_list) + if(ismob(M) && !isnewplayer(M)) + var/mob/MO = M + MO.playsound_local(get_turf(MO), sound, volume, vary, pressure_affected = FALSE) + +/proc/open_sound_channel() + var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used + . = ++next_channel + if(next_channel > CHANNEL_HIGHEST_AVAILABLE) + next_channel = 1 + +/mob/proc/stop_sound_channel(chan) + src << sound(null, repeat = 0, wait = 0, channel = chan) + +/proc/get_rand_frequency() + return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. + /client/proc/playtitlemusic() if(!ticker || !ticker.login_music) return if(is_preference_enabled(/datum/client_preference/play_lobby_music)) src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS -/proc/get_rand_frequency() - return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. - /proc/get_sfx(soundin) if(istext(soundin)) switch(soundin) - if ("shatter") soundin = pick(shatter_sound) - if ("explosion") soundin = pick(explosion_sound) - if ("sparks") soundin = pick(spark_sound) - if ("rustle") soundin = pick(rustle_sound) - if ("punch") soundin = pick(punch_sound) - if ("clownstep") soundin = pick(clown_sound) - if ("swing_hit") soundin = pick(swing_hit_sound) - if ("hiss") soundin = pick(hiss_sound) - if ("pageturn") soundin = pick(page_sound) - if ("fracture") soundin = pick(fracture_sound) - if ("canopen") soundin = pick(can_sound) - if ("mechstep") soundin = pick(mechstep_sound) - //if ("gunshot") soundin = pick(gun_sound) - if("geiger") soundin = pick(geiger_sound) - if("geiger_weak") soundin = pick(geiger_weak_sound) + if ("shatter") soundin = pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') + if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') + if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg') + if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') + if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') + if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') + if ("swing_hit") soundin = pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') + if ("hiss") soundin = pick('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') + if ("pageturn") soundin = pick('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') + if ("fracture") soundin = pick('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') + if ("canopen") soundin = pick('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') + if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') + if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') + if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') return soundin + +//Are these even used? +var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg') +var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg') +var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 772af61eb7..9a7ba9fb0f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1169,6 +1169,20 @@ default behaviour is: item.throw_at(target, throw_range, item.throw_speed, src) +/mob/living/get_sound_env(var/pressure_factor) + if (hallucination) + return PSYCHOTIC + else if (druggy) + return DRUGGED + else if (drowsyness) + return DIZZY + else if (confused) + return DIZZY + else if (sleeping) + return UNDERWATER + else + return ..() + //Add an entry to overlays, assuming it exists /mob/living/proc/apply_hud(cache_index, var/image/I) hud_list[cache_index] = I @@ -1186,4 +1200,4 @@ default behaviour is: return I /mob/living/proc/make_hud_overlays() - return \ No newline at end of file + return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9671bcb0c9..6d7d0bdfb3 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -629,6 +629,13 @@ var/global/image/backplane return TRUE +/mob/proc/get_sound_env(var/pressure_factor) + if (pressure_factor < 0.5) + return SPACE + else + var/area/A = get_area(src) + return A.sound_env + /mob/proc/position_hud_item(var/obj/item/item, var/slot) if(!istype(hud_used) || !slot || !LAZYLEN(hud_used.slot_info)) return diff --git a/polaris.dme b/polaris.dme index 08797dc063..9cab1d0078 100644 --- a/polaris.dme +++ b/polaris.dme @@ -44,6 +44,7 @@ #include "code\__defines\process_scheduler.dm" #include "code\__defines\qdel.dm" #include "code\__defines\research.dm" +#include "code\__defines\sound.dm" #include "code\__defines\species_languages.dm" #include "code\__defines\stat_tracking.dm" #include "code\__defines\subsystems.dm" From 2b767b069fd5463bece3f40fce939fcd21b75324 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 26 Feb 2018 00:34:31 -0500 Subject: [PATCH 2/5] POLARIS: Hide things from lists in VV Like organs from contents. You can look at the organs and internal_organs list on the same page... don't clutter contents. --- .../admin/view_variables/view_variables.dm | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index e624d2df05..cb110d4e86 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -143,7 +143,12 @@ vtext = "\ref[C] - [C] ([C.type])" else if(islist(value)) var/list/L = value - vtext = "/list ([L.len])" + var/removed = 0 + if(varname == "contents") + var/list/original = value + L = original.Copy() //We'll take a copy to manipulate + removed = D.view_variables_filter_contents(L) + vtext = "/list ([L.len]+[removed]H)" if(!(varname in view_variables_dont_expand) && L.len > 0 && L.len < 100) extra = "