Explosion Audio (#1057)

Adds directional audio for explosions and fixes a variety of sound issues with them.
Adds screenshaking for explosions
Tweaks volumes and adds missing sounds for several window/airlock interactions.

Also fixes some runtime errors here and there which were discovered during testing, mostly just adding safeties
This commit is contained in:
NanakoAC
2016-10-26 22:00:49 +03:00
committed by skull132
parent 479666a47d
commit e9f8cdf6b1
9 changed files with 149 additions and 61 deletions
+2 -4
View File
@@ -138,11 +138,9 @@
unload(0)
switch(severity)
if(2)
BITRESET(wires, rand(0,9))
BITRESET(wires, rand(0,9))
BITRESET(wires, rand(0,9))
wires.RandomCutAll(40)//Fix by nanako because the old code was throwing runtimes
if(3)
BITRESET(wires, rand(0,9))
wires.RandomCutAll(20)
..()
return
+4 -4
View File
@@ -928,9 +928,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1)
playsound(src.loc, open_sound_powered, 60, 1)
else
playsound(src.loc, open_sound_unpowered, 100, 1)
playsound(src.loc, open_sound_unpowered, 60, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -992,7 +992,7 @@ About the new airlock wires panel:
adjustBruteLoss(round(crush_damage / AIRLOCK_CRUSH_DIVISOR))
SetStunned(5)
SetWeakened(5)
var/turf/T = get_turf(src)
var/list/valid_turfs = list()
@@ -1004,7 +1004,7 @@ About the new airlock wires panel:
while(valid_turfs.len)
T = pick(valid_turfs)
valid_turfs -= T
if(src.forceMove(T))
return
+15 -7
View File
@@ -26,6 +26,7 @@
var/destroy_hits = 10 //How many strong hits it takes to destroy the door
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
var/hitsound_light = 'sound/effects/Glasshit.ogg'//Sound door makes when hit very gently
var/obj/item/stack/material/steel/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/close_door_at = 0 //When to automatically close the door, if possible
@@ -53,9 +54,11 @@
/obj/machinery/door/attack_generic(var/mob/user, var/damage)
if(damage >= 10)
visible_message("<span class='danger'>\The [user] smashes into the [src]!</span>")
playsound(src.loc, hitsound, 60, 1)
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")
playsound(src.loc, hitsound_light, 8, 1, -1)
user.do_attack_animation(src)
/obj/machinery/door/New()
@@ -226,7 +229,7 @@
if (Proj.damage > 90)
destroy_hits--
if (destroy_hits <= 0)
visible_message("\red <B>\The [src.name] disintegrates!</B>")
visible_message(span("danger","\The [src.name] disintegrates!"))
switch (Proj.damage_type)
if(BRUTE)
new /obj/item/stack/material/steel(src.loc, 2)
@@ -244,15 +247,20 @@
/obj/machinery/door/hitby(AM as mob|obj, var/speed=5)
..()
visible_message("\red <B>[src.name] was hit by [AM].</B>")
visible_message(span("danger","[src.name] was hit by [AM]."))
var/tforce = 0
if(ismob(AM))
tforce = 15 * (speed/5)
else
tforce = AM:throwforce * (speed/5)
playsound(src.loc, hitsound, 100, 1)
take_damage(tforce)
return
if (tforce > 0)
var/volume = 100
if (tforce < 20)//No more stupidly loud banging sound from throwing a piece of paper at a door
volume *= (tforce / 20)
playsound(src.loc, hitsound, volume, 1)
take_damage(tforce)
return
/obj/machinery/door/attack_ai(mob/user as mob)
return src.attack_hand(user)
@@ -330,9 +338,9 @@
if(W.damtype == BRUTE || W.damtype == BURN)
user.do_attack_animation(src)
if(W.force < min_force)
user.visible_message("\red <B>\The [user] hits \the [src] with \the [W] with no visible effect.</B>" )
user.visible_message(span("danger","\The [user] hits \the [src] with \the [W] with no visible effect." ))
else
user.visible_message("\red <B>\The [user] forcefully strikes \the [src] with \the [W]!</B>" )
user.visible_message(span("danger","\The [user] forcefully strikes \the [src] with \the [W]!" ))
playsound(src.loc, hitsound, 100, 1)
take_damage(W.force)
return
+57 -26
View File
@@ -5,8 +5,8 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
///// Z-Level Stuff
src = null //so we don't abort once src is deleted
spawn(0)
var/power = max(0,devastation_range) * 2 + max(0,heavy_impact_range) + max(0,light_impact_range)
if(config.use_recursive_explosions)
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
explosion_rec(epicenter, power)
return
@@ -18,7 +18,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
if(z_transfer && (devastation_range > 0 || heavy_impact_range > 0))
//transfer the explosion in both directions
explosion_z_transfer(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
///// Z-Level Stuff
///// Z-Level Stuffis
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
//playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) )
@@ -31,33 +31,65 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
// 3/7/14 will calculate to 80 + 35
var/far_dist = 0
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
var/volume = 10 + (power * 20)
var/frequency = get_rand_frequency()
for(var/mob/M in player_list)
// Double check for client
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z)
var/dist = get_dist(M_turf, epicenter)
// If inside the blast radius + world.view - 2
if(dist <= round(max_range + world.view - 2, 1))
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
var/closedist = round(max_range + world.view - 2, 1)
//You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
//Whether or not this explosion causes enough vibration to send sound or shockwaves through the station
var/vibration = 1
if (istype(epicenter,/turf/space))
vibration = 0
for (var/turf/T in range(src, max_range))
if (!istype(T,/turf/space))
//If there is a nonspace tile within the explosion radius
//Then we can reverberate shockwaves through that, and allow it to be felt in a vacuum
vibration = 1
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
if (vibration)
for(var/mob/M in player_list)
// Double check for client
var/reception = 2//Whether the person can be shaken or hear sound
//2 = BOTH
//1 = shockwaves only
//0 = no effect
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z)
if (istype(M_turf,/turf/space))
//If the person is standing in space, they wont hear
//But they may still feel the shaking
reception = 0
for (var/turf/T in range(M, 1))
if (!istype(T,/turf/space))
//If theyre touching the hull or on some extruding part of the station
reception = 1//They will get screenshake
break
if (!reception)
continue
var/dist = get_dist(M_turf, epicenter)
if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf))//Dont play sounds to deaf people
// If inside the blast radius + world.view - 2
if(dist <= closedist)
M.playsound_local(epicenter, get_sfx("explosion"), min(100, volume), 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
//You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else
volume = M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', volume, 1, frequency, usepressure = 0, falloff = 1000)
//Playsound local will return the final volume the sound is actually played at
//It will return 0 if the sound volume falls to 0 due to falloff or pressure
//Also return zero if sound playing failed for some other reason
//Deaf people will feel vibrations though
if (volume > 0)//Only shake camera if someone was close enough to hear it
shake_camera(M, min(60,max(2,(power*28) / dist)), min(3.5,((power*6) / dist)),0.05)
//Maximum duration is 6 seconds, and max strength is 3.5
//Becuse values higher than those just get really silly
var/close = range(world.view+round(devastation_range,1), epicenter)
// to all distanced mobs play a different sound
for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close))
// check if the mob can hear
if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space))
M << 'sound/effects/explosionfar.ogg'
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
@@ -115,7 +147,6 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
return 1
proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in range(range, epicenter))
tile.ex_act(2)
@@ -69,7 +69,7 @@
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
ui_interact(user)
/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
@@ -80,7 +80,7 @@
data["valveOpen"] = valve_open ? 1 : 0
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
@@ -149,7 +149,7 @@
tank_two = null
else
return
T.loc = get_turf(src)
update_icon()
@@ -165,18 +165,18 @@
/obj/item/device/transfer_valve/proc/split_gases()
if(!valve_open)
return
valve_open = 0
if(deleted(tank_one) || deleted(tank_two))
if(deleted(tank_one) || deleted(tank_two) || !tank_one.air_contents || !tank_two.air_contents)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
+4 -5
View File
@@ -174,7 +174,7 @@
/obj/structure/window/attack_tk(mob/user as mob)
user.visible_message("<span class='notice'>Something knocks on [src].</span>")
playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1)
playsound(loc, 'sound/effects/Glasshit.ogg', 60, 1)
/obj/structure/window/attack_hand(mob/user as mob)
if(HULK in user.mutations)
@@ -191,26 +191,25 @@
attack_generic(H,25)
return
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
playsound(src.loc, 'sound/effects/glassknock.ogg', 90, 1)
user.do_attack_animation(src)
usr.visible_message("\red [usr.name] bangs against the [src.name]!",
"\red You bang against the [src.name]!",
"You hear a banging sound.")
else
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
playsound(src.loc, 'sound/effects/glassknock.ogg', 60, 1)
usr.visible_message("[usr.name] knocks on the [src.name].",
"You knock on the [src.name].",
"You hear a knocking sound.")
return
/obj/structure/window/attack_generic(var/mob/user, var/damage)
if(!damage)
return
if(damage >= 10)
visible_message("<span class='danger'>[user] smashes into [src]!</span>")
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")
playsound(src.loc, 'sound/effects/Glasshit.ogg', 7, 1, -1)
user.do_attack_animation(src)
return 1
+4 -4
View File
@@ -48,11 +48,11 @@ var/list/footstepfx = list("defaultstep","concretestep","grassstep","dirtstep","
var/const/FALLOFF_SOUNDS = 0.5
/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, var/usepressure = 1, var/environment = -1)
if(!src.client || ear_deaf > 0) return
if(!src.client || ear_deaf > 0) return 0
if(soundin in footstepfx)
if(!(src.client.prefs.asfx_togs & ASFX_FOOTSTEPS))
return
return 0
soundin = get_sfx(soundin)
@@ -79,7 +79,6 @@ var/const/FALLOFF_SOUNDS = 0.5
//This extra falloff should probably be rewritten or removed, but for now ive implemented a quick fix by only setting S.volume to vol after calculations are done
//This fix allows feeding in high volume values (>100) to make longrange sounds audible
// -Nanako
if (usepressure)
//sound volume falloff with pressure. Pass usepressure = 0 to disable these calculations
var/pressure_factor = 1.0
@@ -101,7 +100,7 @@ var/const/FALLOFF_SOUNDS = 0.5
vol *= pressure_factor
if (vol <= 0)
return //no volume means no sound
return 0//no volume means no sound
S.volume = vol
var/dx = turf_source.x - T.x // Hearing from the right/left
@@ -117,6 +116,7 @@ var/const/FALLOFF_SOUNDS = 0.5
S.environment = A.sound_env
src << S
return S.volume
+17 -3
View File
@@ -456,14 +456,14 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return sanitize(t)
/proc/shake_camera(mob/M, duration, strength=1)
/proc/shake_camera(mob/M, duration, strength=1, var/taper = 0)
if(!M || !M.client || M.shakecamera)
return
M.shakecamera = 1
spawn(1)
spawn(2)
if(!M.client)
return
var/atom/oldeye=M.client.eye
var/aiEyeFlag = 0
if(istype(oldeye, /mob/eye/aiEye))
@@ -476,6 +476,20 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
else
M.client.eye = locate(dd_range(1,M.loc.x+rand(-strength,strength),world.maxx),dd_range(1,M.loc.y+rand(-strength,strength),world.maxy),M.loc.z)
sleep(1)
//Taper code added by nanako.
//Will make the strength falloff after the duration.
//This helps to reduce jarring effects of major screenshaking suddenly returning to stability
//Recommended taper values are 0.05-0.1
if (taper > 0)
while (strength > 0)
strength -= taper
if(aiEyeFlag)
M.client.eye = locate(dd_range(1,oldeye.loc.x+rand(-strength,strength),world.maxx),dd_range(1,oldeye.loc.y+rand(-strength,strength),world.maxy),oldeye.loc.z)
else
M.client.eye = locate(dd_range(1,M.loc.x+rand(-strength,strength),world.maxx),dd_range(1,M.loc.y+rand(-strength,strength),world.maxy),M.loc.z)
sleep(1)
M.client.eye=oldeye
M.shakecamera = 0