diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index 2fda22cd32d..7b894fa4669 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -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
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 934b4f629be..50dd01c87e3 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -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
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 8e7c952def7..0b508787a51 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -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("\The [user] smashes into the [src]!")
+ playsound(src.loc, hitsound, 60, 1)
take_damage(damage)
else
visible_message("\The [user] bonks \the [src] harmlessly.")
+ 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 \The [src.name] disintegrates!")
+ 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 [src.name] was hit by [AM].")
+ 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 \The [user] hits \the [src] with \the [W] with no visible effect." )
+ user.visible_message(span("danger","\The [user] hits \the [src] with \the [W] with no visible effect." ))
else
- user.visible_message("\red \The [user] forcefully strikes \the [src] with \the [W]!" )
+ 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
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 1b32185ace3..a99b771093a 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -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]) (JMP)")
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)
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index e44f7595470..7b7d7deab8d 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -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
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 70e599c5b06..7b7be9288ee 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -174,7 +174,7 @@
/obj/structure/window/attack_tk(mob/user as mob)
user.visible_message("Something knocks on [src].")
- 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("[user] smashes into [src]!")
take_damage(damage)
else
visible_message("\The [user] bonks \the [src] harmlessly.")
+ playsound(src.loc, 'sound/effects/Glasshit.ogg', 7, 1, -1)
user.do_attack_animation(src)
return 1
diff --git a/code/game/sound.dm b/code/game/sound.dm
index bb46b510585..2a98112276b 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -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
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 01e03aa3501..9a5eac6e374 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -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
diff --git a/html/changelogs/Nanako-AudioBomb.yml b/html/changelogs/Nanako-AudioBomb.yml
new file mode 100644
index 00000000000..2fde0e08f95
--- /dev/null
+++ b/html/changelogs/Nanako-AudioBomb.yml
@@ -0,0 +1,38 @@
+################################
+# 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: Nanako
+
+# 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:
+ - rscadd: "Explosions now have proper directional sounds, so you can tell the direction that something exploded in."
+ - rscadd: "Distant explosions now cause mild screen shaking proportional to power and distance."
+ - tweak: "Adjusted sound volumes for several actions related to windows and airlocks."