mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-24 21:40:55 +01:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user