summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Data/sounds/BodyHit.oggbin6109 -> 0 bytes
-rw-r--r--Data/sounds/SW.oggbin11795 -> 0 bytes
-rw-r--r--Data/sounds/WallHit.oggbin10136 -> 0 bytes
-rw-r--r--Data/sounds/bodyland.oggbin8736 -> 0 bytes
-rw-r--r--Data/sounds/glock.oggbin13347 -> 0 bytes
-rw-r--r--Data/sounds/gun/empty-clip.wavbin0 -> 67736 bytes
-rw-r--r--Data/sounds/gun/fire/20-gauge-shotgun.wavbin0 -> 149296 bytes
-rw-r--r--Data/sounds/gun/fire/22-magnum-pistol.wavbin0 -> 127076 bytes
-rw-r--r--Data/sounds/gun/fire/9-mm-pistol.wavbin0 -> 137922 bytes
-rw-r--r--Data/sounds/gun/fire/ar-15-pistol.wavbin0 -> 78416 bytes
-rw-r--r--Data/sounds/gun/fire/ar-15-rifle.wavbin0 -> 225080 bytes
-rw-r--r--Data/sounds/impact/body-fall.wavbin0 -> 342498 bytes
-rw-r--r--Data/sounds/impact/body-hit.wavbin0 -> 76858 bytes
-rw-r--r--Data/sounds/impact/knife-stab.wavbin0 -> 49206 bytes
-rw-r--r--Data/sounds/impact/wall-hit.wavbin0 -> 25420 bytes
-rw-r--r--Data/sounds/machinegun.oggbin8256 -> 0 bytes
-rw-r--r--Data/sounds/shotgun.oggbin7872 -> 0 bytes
-rw-r--r--Data/sounds/sniperrifle.oggbin11960 -> 0 bytes
m---------lib/zeal0
-rw-r--r--src/Constants.h2
-rw-r--r--src/GameInitDispose.cpp177
-rw-r--r--src/GameLoop.cpp9
-rw-r--r--src/GameTick.cpp154
-rw-r--r--src/Person.cpp12
-rw-r--r--src/Skeleton.cpp24
-rw-r--r--src/main.zig1
-rw-r--r--src/misc.h11
-rw-r--r--src/misc.zig11
28 files changed, 113 insertions, 288 deletions
diff --git a/Data/sounds/BodyHit.ogg b/Data/sounds/BodyHit.ogg
deleted file mode 100644
index f6b5d77..0000000
--- a/Data/sounds/BodyHit.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/SW.ogg b/Data/sounds/SW.ogg
deleted file mode 100644
index 4445758..0000000
--- a/Data/sounds/SW.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/WallHit.ogg b/Data/sounds/WallHit.ogg
deleted file mode 100644
index dc8ebb8..0000000
--- a/Data/sounds/WallHit.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/bodyland.ogg b/Data/sounds/bodyland.ogg
deleted file mode 100644
index 06d1bbd..0000000
--- a/Data/sounds/bodyland.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/glock.ogg b/Data/sounds/glock.ogg
deleted file mode 100644
index 0913e30..0000000
--- a/Data/sounds/glock.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/gun/empty-clip.wav b/Data/sounds/gun/empty-clip.wav
new file mode 100644
index 0000000..5bdfcd0
--- /dev/null
+++ b/Data/sounds/gun/empty-clip.wav
Binary files differdiff --git a/Data/sounds/gun/fire/20-gauge-shotgun.wav b/Data/sounds/gun/fire/20-gauge-shotgun.wav
new file mode 100644
index 0000000..338c31f
--- /dev/null
+++ b/Data/sounds/gun/fire/20-gauge-shotgun.wav
Binary files differdiff --git a/Data/sounds/gun/fire/22-magnum-pistol.wav b/Data/sounds/gun/fire/22-magnum-pistol.wav
new file mode 100644
index 0000000..37e23ab
--- /dev/null
+++ b/Data/sounds/gun/fire/22-magnum-pistol.wav
Binary files differdiff --git a/Data/sounds/gun/fire/9-mm-pistol.wav b/Data/sounds/gun/fire/9-mm-pistol.wav
new file mode 100644
index 0000000..c328fc9
--- /dev/null
+++ b/Data/sounds/gun/fire/9-mm-pistol.wav
Binary files differdiff --git a/Data/sounds/gun/fire/ar-15-pistol.wav b/Data/sounds/gun/fire/ar-15-pistol.wav
new file mode 100644
index 0000000..7f83595
--- /dev/null
+++ b/Data/sounds/gun/fire/ar-15-pistol.wav
Binary files differdiff --git a/Data/sounds/gun/fire/ar-15-rifle.wav b/Data/sounds/gun/fire/ar-15-rifle.wav
new file mode 100644
index 0000000..425ecbc
--- /dev/null
+++ b/Data/sounds/gun/fire/ar-15-rifle.wav
Binary files differdiff --git a/Data/sounds/impact/body-fall.wav b/Data/sounds/impact/body-fall.wav
new file mode 100644
index 0000000..3e884a6
--- /dev/null
+++ b/Data/sounds/impact/body-fall.wav
Binary files differdiff --git a/Data/sounds/impact/body-hit.wav b/Data/sounds/impact/body-hit.wav
new file mode 100644
index 0000000..a4e61d7
--- /dev/null
+++ b/Data/sounds/impact/body-hit.wav
Binary files differdiff --git a/Data/sounds/impact/knife-stab.wav b/Data/sounds/impact/knife-stab.wav
new file mode 100644
index 0000000..0b636b0
--- /dev/null
+++ b/Data/sounds/impact/knife-stab.wav
Binary files differdiff --git a/Data/sounds/impact/wall-hit.wav b/Data/sounds/impact/wall-hit.wav
new file mode 100644
index 0000000..5d419a4
--- /dev/null
+++ b/Data/sounds/impact/wall-hit.wav
Binary files differdiff --git a/Data/sounds/machinegun.ogg b/Data/sounds/machinegun.ogg
deleted file mode 100644
index 6c8ef30..0000000
--- a/Data/sounds/machinegun.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/shotgun.ogg b/Data/sounds/shotgun.ogg
deleted file mode 100644
index d0c8777..0000000
--- a/Data/sounds/shotgun.ogg
+++ /dev/null
Binary files differdiff --git a/Data/sounds/sniperrifle.ogg b/Data/sounds/sniperrifle.ogg
deleted file mode 100644
index 1d2f526..0000000
--- a/Data/sounds/sniperrifle.ogg
+++ /dev/null
Binary files differdiff --git a/lib/zeal b/lib/zeal
-Subproject bcbf7fbed0392762d35613a995c5ab4fbcfb666
+Subproject 29a1ea1aa2038a3d4bad44741c25e6d34c0e4e9
diff --git a/src/Constants.h b/src/Constants.h
index 71e434d..1998e47 100644
--- a/src/Constants.h
+++ b/src/Constants.h
@@ -130,6 +130,4 @@
 
 #define numcasual 4
 
-#define soundscalefactordefault 10
-
 #endif
diff --git a/src/GameInitDispose.cpp b/src/GameInitDispose.cpp
index ed767fd..8dadb84 100644
--- a/src/GameInitDispose.cpp
+++ b/src/GameInitDispose.cpp
@@ -109,6 +109,17 @@ Game* makeGame(Config config)
 
 void LoadSounds(bool musictoggle)
 {
+	gSampleSet[clicksound] = loadSound("gun/empty-clip.wav");
+	gSampleSet[pistol1sound] = loadSound("gun/fire/9-mm-pistol.wav");
+	gSampleSet[shotgunsound] = loadSound("gun/fire/20-gauge-shotgun.wav");
+	gSampleSet[pistol2sound] = loadSound("gun/fire/22-magnum-pistol.wav");
+	gSampleSet[machinegunsound] = loadSound("gun/fire/ar-15-pistol.wav");
+	gSampleSet[riflesound] = loadSound("gun/fire/ar-15-rifle.wav");
+	gSampleSet[bodylandsound] = loadSound("impact/body-fall.wav");
+	gSampleSet[bodyhitsound] = loadSound("impact/body-hit.wav");
+	gSampleSet[knifeslashsound] = loadSound("impact/knife-stab.wav");
+	gSampleSet[wallhitsound] = loadSound("impact/wall-hit.ogg");
+
 	gSampleSet[visionsound] = loadSound("underwater.ogg");
 	gSampleSet[soulinsound] = loadSound("soul-in.ogg");
 	gSampleSet[souloutsound] = loadSound("soul-out.ogg");
@@ -117,20 +128,11 @@ void LoadSounds(bool musictoggle)
 	gSampleSet[footstepsound + 2] = loadSound("footstep3.ogg");
 	gSampleSet[footstepsound + 3] = loadSound("footstep4.ogg");
 	gSampleSet[footstepsound + 4] = loadSound("footstep5.ogg");
-	gSampleSet[bodylandsound] = loadSound("bodyland.ogg");
 	gSampleSet[headlandsound] = loadSound("headland.ogg");
-	gSampleSet[riflesound] = loadSound("sniperrifle.ogg");
-	gSampleSet[machinegunsound] = loadSound("machinegun.ogg");
-	gSampleSet[bodyhitsound] = loadSound("BodyHit.ogg");
-	gSampleSet[wallhitsound] = loadSound("WallHit.ogg");
-	gSampleSet[machinegunsound] = loadSound("machinegun.ogg");
 	gSampleSet[nearbulletsound] = loadSound("Nearbullet.ogg");
 	gSampleSet[headwhacksound] = loadSound("riflewhack.ogg");
 	gSampleSet[headshotsound] = loadSound("headshot.ogg");
 	gSampleSet[reloadsound] = loadSound("reload.ogg");
-	gSampleSet[clicksound] = loadSound("click.ogg");
-	gSampleSet[pistol1sound] = loadSound("SW.ogg");
-	gSampleSet[pistol2sound] = loadSound("glock.ogg");
 	gSampleSet[pinpullsound] = loadSound("pinpull.ogg");
 	gSampleSet[pinreplacesound] = loadSound("pinreplace.ogg");
 	gSampleSet[grenadethrowsound] = loadSound("handlerelease.ogg");
@@ -141,8 +143,6 @@ void LoadSounds(bool musictoggle)
 	gSampleSet[rainsound] = loadSound("rain.ogg");
 	gSampleSet[losesound] = loadSound("Lose.ogg");
 	gSampleSet[disguisekillsound] = loadSound("disguise-kill.ogg");
-	gSampleSet[knifeslashsound] = loadSound("knifeslash.ogg");
-	gSampleSet[shotgunsound] = loadSound("shotgun.ogg");
 	if (musictoggle) {
 		gSampleSet[mainmenusong] = loadSound("mainmenusong.ogg");
 		gSampleSet[shootsong] = loadSound("shootsong.ogg");
@@ -184,120 +184,29 @@ void LoadSounds(bool musictoggle)
 	alSourcei(gSourceID[disguisekillsound], AL_BUFFER, gSampleSet[disguisekillsound]);
 	alSourcei(gSourceID[knifeslashsound], AL_BUFFER, gSampleSet[knifeslashsound]);
 	alSourcei(gSourceID[shotgunsound], AL_BUFFER, gSampleSet[shotgunsound]);
-
 	if (musictoggle) {
 		alGenSources(4, gSourceID + 33);
 		alSourcei(gSourceID[mainmenusong], AL_BUFFER, gSampleSet[mainmenusong]);
 		alSourcei(gSourceID[shootsong], AL_BUFFER, gSampleSet[shootsong]);
 		alSourcei(gSourceID[zombiesong], AL_BUFFER, gSampleSet[zombiesong]);
 		alSourcei(gSourceID[knifesong], AL_BUFFER, gSampleSet[knifesong]);
+
+		alSourcei(gSourceID[knifesong], AL_LOOPING, 1);
+		alSourcei(gSourceID[mainmenusong], AL_LOOPING, 1);
+		alSourcei(gSourceID[zombiesong], AL_LOOPING, 1);
+		alSourcei(gSourceID[shootsong], AL_LOOPING, 1);
 	}
 
 	alListenerfv(AL_POSITION, {});
 	alSourcefv(gSourceID[visionsound], AL_POSITION, {});
-	alSourcei(gSourceID[visionsound], AL_LOOPING, 1);
-	alSourcef(gSourceID[visionsound], AL_MIN_GAIN, 1);
 	alSourcefv(gSourceID[soulinsound], AL_POSITION, {});
-	alSourcei(gSourceID[soulinsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[soulinsound], AL_MIN_GAIN, 1);
 	alSourcefv(gSourceID[souloutsound], AL_POSITION, {});
-	alSourcei(gSourceID[souloutsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[souloutsound], AL_MIN_GAIN, 1);
-
-	for(int i=0;i<5;i++){
-		alSourcefv(gSourceID[footstepsound+i], AL_POSITION, {});
-		alSourcei(gSourceID[footstepsound+i], AL_LOOPING, 0);
-		alSourcef(gSourceID[footstepsound+i], AL_MIN_GAIN, 0);
+	if (musictoggle) {
+		alSourcefv(gSourceID[knifesong], AL_POSITION, {});
+		alSourcefv(gSourceID[mainmenusong], AL_POSITION, {});
+		alSourcefv(gSourceID[zombiesong], AL_POSITION, {});
+		alSourcefv(gSourceID[shootsong], AL_POSITION, {});
 	}
-
-	alSourcefv(gSourceID[bodylandsound], AL_POSITION, {});
-	alSourcei(gSourceID[bodylandsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[bodylandsound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[headlandsound], AL_POSITION, {});
-	alSourcei(gSourceID[headlandsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[headlandsound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[riflesound], AL_POSITION, {});
-	alSourcei(gSourceID[riflesound], AL_LOOPING, 0);
-	alSourcef(gSourceID[riflesound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[bodyhitsound], AL_POSITION, {});
-	alSourcei(gSourceID[bodyhitsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[bodyhitsound], AL_MIN_GAIN, 0.1f);
-	alSourcefv(gSourceID[wallhitsound], AL_POSITION, {});
-	alSourcei(gSourceID[wallhitsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[wallhitsound], AL_MIN_GAIN, 0);
-	alSourcef(gSourceID[wallhitsound], AL_MAX_GAIN, 0.6f);
-	alSourcefv(gSourceID[machinegunsound], AL_POSITION, {});
-	alSourcei(gSourceID[machinegunsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[machinegunsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[nearbulletsound], AL_POSITION, {});
-	alSourcei(gSourceID[nearbulletsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[nearbulletsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[headwhacksound], AL_POSITION, {});
-	alSourcei(gSourceID[headwhacksound], AL_LOOPING, 0);
-	alSourcef(gSourceID[headwhacksound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[headshotsound], AL_POSITION, {});
-	alSourcei(gSourceID[headshotsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[headshotsound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[reloadsound], AL_POSITION, {});
-	alSourcei(gSourceID[reloadsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[reloadsound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[clicksound], AL_POSITION, {});
-	alSourcei(gSourceID[clicksound], AL_LOOPING, 0);
-	alSourcef(gSourceID[clicksound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[pistol1sound], AL_POSITION, {});
-	alSourcei(gSourceID[pistol1sound], AL_LOOPING, 0);
-	alSourcef(gSourceID[pistol1sound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[pistol2sound], AL_POSITION, {});
-	alSourcei(gSourceID[pistol2sound], AL_LOOPING, 0);
-	alSourcef(gSourceID[pistol2sound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[pinpullsound], AL_POSITION, {});
-	alSourcei(gSourceID[pinpullsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[pinpullsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[pinreplacesound], AL_POSITION, {});
-	alSourcei(gSourceID[pinreplacesound], AL_LOOPING, 0);
-	alSourcef(gSourceID[pinreplacesound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, {});
-	alSourcei(gSourceID[grenadethrowsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[grenadethrowsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[bouncesound], AL_POSITION, {});
-	alSourcei(gSourceID[bouncesound], AL_LOOPING, 0);
-	alSourcef(gSourceID[bouncesound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[bounce2sound], AL_POSITION, {});
-	alSourcei(gSourceID[bounce2sound], AL_LOOPING, 0);
-	alSourcef(gSourceID[bounce2sound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[explosionsound], AL_POSITION, {});
-	alSourcei(gSourceID[explosionsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[explosionsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[bodywhacksound], AL_POSITION, {});
-	alSourcei(gSourceID[bodywhacksound], AL_LOOPING, 0);
-	alSourcef(gSourceID[bodywhacksound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[rainsound], AL_POSITION, {});
-	alSourcei(gSourceID[rainsound], AL_LOOPING, 1);
-	alSourcef(gSourceID[rainsound], AL_MIN_GAIN, 0.3f);
-	alSourcefv(gSourceID[losesound], AL_POSITION, {});
-	alSourcei(gSourceID[losesound], AL_LOOPING, 0);
-	alSourcef(gSourceID[losesound], AL_MIN_GAIN, 1);
-	alSourcefv(gSourceID[disguisekillsound], AL_POSITION, {});
-	alSourcei(gSourceID[disguisekillsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[disguisekillsound], AL_MIN_GAIN, 1);
-	alSourcefv(gSourceID[knifeslashsound], AL_POSITION, {});
-	alSourcei(gSourceID[knifeslashsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[knifeslashsound], AL_MIN_GAIN,0);
-	alSourcefv(gSourceID[shotgunsound], AL_POSITION, {});
-	alSourcei(gSourceID[shotgunsound], AL_LOOPING, 0);
-	alSourcef(gSourceID[shotgunsound], AL_MIN_GAIN, 0);
-	alSourcefv(gSourceID[knifesong], AL_POSITION, {});
-	alSourcei(gSourceID[knifesong], AL_LOOPING, 1);
-	alSourcef(gSourceID[knifesong], AL_MIN_GAIN, 1);
-	alSourcefv(gSourceID[mainmenusong], AL_POSITION, {});
-	alSourcei(gSourceID[mainmenusong], AL_LOOPING, 1);
-	alSourcef(gSourceID[mainmenusong], AL_MIN_GAIN, 1);
-	alSourcefv(gSourceID[zombiesong], AL_POSITION, {});
-	alSourcei(gSourceID[zombiesong], AL_LOOPING, 1);
-	alSourcef(gSourceID[zombiesong], AL_MIN_GAIN, 1);
-	alSourcefv(gSourceID[shootsong], AL_POSITION, {});
-	alSourcei(gSourceID[shootsong], AL_LOOPING, 1);
-	alSourcef(gSourceID[shootsong], AL_MIN_GAIN, 1);
 }
 
 void initGame(Game* game)
@@ -572,7 +481,7 @@ void initGame(Game* game)
 	game->enemystate = 2;
 
 	if (!game->initialized) {
-		soundscalefactor=soundscalefactordefault; //Setup sound falloff
+		soundscalefactor = 10;
 
 		// Sounds
 		LoadSounds(game->musictoggle);
@@ -756,90 +665,48 @@ void initGame(Game* game)
 		}
 
 	if (!game->initialized) {
-
 		//Load player model
-
 		skeletonmodels[0].load((char*) ":Data:Models:Head.solid");
-
 		skeletonmodels[0].Rotate(90,0,0);
-
 		skeletonmodels[0].Scale(.02,.02,.02);
-
 		skeletonmodels[0].CalculateNormals();
-
 		skeletonmodels[1].load((char*) ":Data:Models:Chest.solid");
-
 		skeletonmodels[1].Rotate(90,0,0);
-
 		skeletonmodels[1].Scale(.02,.02,.02);
-
 		skeletonmodels[1].CalculateNormals();
-
 		skeletonmodels[2].load((char*) ":Data:Models:Abdomen.solid");
-
 		skeletonmodels[2].Rotate(90,0,0);
-
 		skeletonmodels[2].Scale(.02,.02,.02);
-
 		skeletonmodels[2].CalculateNormals();
-
 		skeletonmodels[3].load((char*) ":Data:Models:Upper arm.solid");
-
 		skeletonmodels[3].Rotate(90,0,0);
-
 		skeletonmodels[3].Scale(.02,.02,.02);
-
 		skeletonmodels[3].CalculateNormals();
-
 		skeletonmodels[4].load((char*) ":Data:Models:Lower arm.solid");
-
 		skeletonmodels[4].Rotate(90,0,0);
-
 		skeletonmodels[4].Scale(.02,.02,.02);
-
 		skeletonmodels[4].CalculateNormals();
-
 		skeletonmodels[5].load((char*) ":Data:Models:Hand.solid");
-
 		skeletonmodels[5].Rotate(90,0,0);
-
 		skeletonmodels[5].Scale(.02,.02,.02);
-
 		skeletonmodels[5].CalculateNormals();
-
 		skeletonmodels[6].load((char*) ":Data:Models:Upper leg.solid");
-
 		skeletonmodels[6].Rotate(90,0,0);
-
 		skeletonmodels[6].Scale(.02,.02,.02);
-
 		skeletonmodels[6].CalculateNormals();
-
 		skeletonmodels[7].load((char*) ":Data:Models:Lower leg.solid");
-
 		skeletonmodels[7].Rotate(90,0,0);
-
 		skeletonmodels[7].Scale(.02,.02,.02);
-
 		skeletonmodels[7].CalculateNormals();
-
 		skeletonmodels[8].load((char*) ":Data:Models:Foot.solid");
-
 		skeletonmodels[8].Rotate(90,0,0);
-
 		skeletonmodels[8].Scale(.02,.02,.02);
-
 		skeletonmodels[8].CalculateNormals();
-
 		skeletonmodels[9].load((char*) ":Data:Models:Shades.solid");
-
 		skeletonmodels[9].Rotate(90,0,0);
-
 		skeletonmodels[9].Scale(.02,.02,.02);
-
 		skeletonmodels[9].CalculateNormals();
 
-
 		//Load gun models
 		gunmodels[sniperriflemodel].load((char*) ":Data:Models:sniperrifle.solid");
 
diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp
index b3810c6..e89eb2e 100644
--- a/src/GameLoop.cpp
+++ b/src/GameLoop.cpp
@@ -20,6 +20,7 @@
 // along with Black Shades.  If not, see <https://www.gnu.org/licenses/>.
 
 #include "Game.h"
+#include "misc.h"
 
 extern float multiplier;
 extern int thirdperson;
@@ -95,11 +96,9 @@ void handleKey(Game* game, int key, int action, int mods)
 				                        person.averageloc) > 200)
 					continue;
 
-				auto soundsrc = (player.playercoords
-					- camera.position) / soundscalefactor;
-				float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
-				alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
-				alSourcePlay(gSourceID[clicksound]);
+				auto soundpos = player.playercoords - camera.position;
+				playSound(gSourceID[clicksound],
+					soundpos.x, soundpos.y, soundpos.z);
 
 				auto tmp_gun = player.whichgun;
 				player.whichgun = person.whichgun;
diff --git a/src/GameTick.cpp b/src/GameTick.cpp
index 57b2efe..3088ae5 100644
--- a/src/GameTick.cpp
+++ b/src/GameTick.cpp
@@ -23,6 +23,7 @@
 // along with Black Shades.  If not, see <https://www.gnu.org/licenses/>.
 
 #include "Game.h"
+#include "misc.h"
 
 extern float multiplier;
 extern int thirdperson;
@@ -1499,17 +1500,11 @@ void Game::Tick()
 											person[i].attacktarget=0;
 											person[i].attackframe=0;
 
-											auto stabpos = person[i].playercoords + flatfacing - camera.position;
-											ALfloat gLoc[] {
-												stabpos.x / 2 / soundscalefactor,
-												stabpos.y / 2 / soundscalefactor,
-												stabpos.z / 2 / soundscalefactor,
-											};
-
 											if(person[person[i].killtarget].type!=zombietype)
 											{
-												alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
-												alSourcePlay(gSourceID[knifeslashsound]);
+												auto stabpos = person[i].playercoords + flatfacing - camera.position;
+												playSound(gSourceID[knifeslashsound],
+													stabpos.x, stabpos.y, stabpos.z);
 												person[person[i].killtarget].bjoint1=&person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[neck]];
 												person[person[i].killtarget].bjoint2=&person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[neck]];
 												person[person[i].killtarget].bleeding=1;
@@ -1660,19 +1655,13 @@ void Game::Tick()
 		if(person[person[0].killtarget].skeleton.free<1&&person[0].killtarget!=0&&(person[0].aiming<1||person[0].whichgun==nogun||person[0].whichgun==knife||person[0].targetanimation==joganim)){
 			auto soundpos = person[0].playercoords + flatfacing
 				- camera.position;
-			float gLoc[] {
-				soundpos.x / 2 / soundscalefactor,
-				soundpos.y / 2 / soundscalefactor,
-				soundpos.z / 2 / soundscalefactor,
-			};
-
 			if (person[person[0].killtarget].type != zombietype) {
 				if (person[0].whichgun != knife) {
-					alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
-					alSourcePlay(gSourceID[headwhacksound]);
+					playSound(gSourceID[headwhacksound],
+						soundpos.x, soundpos.y, soundpos.z);
 				} else {
-					alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
-					alSourcePlay(gSourceID[knifeslashsound]);
+					playSound(gSourceID[knifeslashsound],
+						soundpos.x, soundpos.y, soundpos.z);
 
 					person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
 					person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
@@ -1709,55 +1698,53 @@ void Game::Tick()
 					person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=DoRotation(flatfacing,0,40,0)*50;
 					person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=person[0].velocity*2;
 				}
-			} else {
-				if(whacked==0){
-					whacked=1;
-					if (person[0].whichgun!=knife) {
-						alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
-						alSourcePlay(gSourceID[headwhacksound]);
-					} else {
-						alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
-						alSourcePlay(gSourceID[knifeslashsound]);
+			} else if (!whacked) {
+				whacked = true;
+				if (person[0].whichgun != knife) {
+					playSound(gSourceID[headwhacksound],
+						soundpos.x, soundpos.y, soundpos.z);
+				} else {
+					playSound(gSourceID[knifeslashsound],
+						soundpos.x, soundpos.y, soundpos.z);
 
-						person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
-						person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+					person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+					person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
 
-						person[person[0].killtarget].bleeddelay=1;
+					person[person[0].killtarget].bleeddelay=1;
 
-						person[0].bjoint1=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
-						person[0].bjoint2=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+					person[0].bjoint1=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+					person[0].bjoint2=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
 
-						person[0].bleeding=1;
-						person[0].bleeddelay=1;
+					person[0].bleeding=1;
+					person[0].bleeddelay=1;
 
-						velocity=DoRotation(flatfacing,0,70,0)*50+person[0].velocity*2;
-						velocity.y+=30;
+					velocity=DoRotation(flatfacing,0,70,0)*50+person[0].velocity*2;
+					velocity.y+=30;
 
-						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.3, 2);
-						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.2, 3);
-						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4);
-					}
+					sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.3, 2);
+					sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.2, 3);
+					sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4);
+				}
 
-					person[person[0].killtarget].health-=200;
-					person[person[0].killtarget].maxhealth-=20;
-					person[person[0].killtarget].skeleton.free=1;
-					person[person[0].killtarget].longdead=1;
+				person[person[0].killtarget].health-=200;
+				person[person[0].killtarget].maxhealth-=20;
+				person[person[0].killtarget].skeleton.free=1;
+				person[person[0].killtarget].longdead=1;
 
-					for(int j=0;j<person[person[0].killtarget].skeleton.num_joints;j++){
-						person[person[0].killtarget].skeleton.joints[j].position=DoRotation(person[person[0].killtarget].skeleton.joints[j].position,0,person[person[0].killtarget].playerrotation,0);
-						person[person[0].killtarget].skeleton.joints[j].position+=person[person[0].killtarget].playercoords;
-						person[person[0].killtarget].skeleton.joints[j].realoldposition=person[person[0].killtarget].skeleton.joints[j].position;
-						person[person[0].killtarget].skeleton.joints[j].velocity=person[person[0].killtarget].velocity;
+				for(int j=0;j<person[person[0].killtarget].skeleton.num_joints;j++){
+					person[person[0].killtarget].skeleton.joints[j].position=DoRotation(person[person[0].killtarget].skeleton.joints[j].position,0,person[person[0].killtarget].playerrotation,0);
+					person[person[0].killtarget].skeleton.joints[j].position+=person[person[0].killtarget].playercoords;
+					person[person[0].killtarget].skeleton.joints[j].realoldposition=person[person[0].killtarget].skeleton.joints[j].position;
+					person[person[0].killtarget].skeleton.joints[j].velocity=person[person[0].killtarget].velocity;
 
-						person[person[0].killtarget].skeleton.joints[j].velocity.x+=abs(Random()%10)-5;
-						person[person[0].killtarget].skeleton.joints[j].velocity.y+=abs(Random()%10)-5;
-						person[person[0].killtarget].skeleton.joints[j].velocity.z+=abs(Random()%10)-5;
-					}
+					person[person[0].killtarget].skeleton.joints[j].velocity.x+=abs(Random()%10)-5;
+					person[person[0].killtarget].skeleton.joints[j].velocity.y+=abs(Random()%10)-5;
+					person[person[0].killtarget].skeleton.joints[j].velocity.z+=abs(Random()%10)-5;
+				}
 
-					if(person[0].whichgun!=knife){
-						person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=DoRotation(flatfacing,0,40,0)*50;
-						person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=person[0].velocity*2;
-					}
+				if(person[0].whichgun!=knife){
+					person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=DoRotation(flatfacing,0,40,0)*50;
+					person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=person[0].velocity*2;
 				}
 			}
 		}
@@ -1799,13 +1786,9 @@ void Game::Tick()
 
 	// Empty magazine
 	if (person[0].firing && person[0].ammo <= 0) {
-		float gLoc[] {
-			person[0].playercoords.x / soundscalefactor,
-			person[0].playercoords.y / soundscalefactor,
-			person[0].playercoords.z / soundscalefactor,
-		};
-		alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
-		alSourcePlay(gSourceID[clicksound]);
+		auto soundpos = person[0].playercoords - camera.position;
+		playSound(gSourceID[clicksound],
+			soundpos.x, soundpos.y, soundpos.z);
 		person[0].firing = false;
 	}
 
@@ -1941,12 +1924,6 @@ void Game::Tick()
 				camera.rotation -= rot;
 				camera.rotation2 -= rot2;
 
-				auto soundpos = start - camera.position;
-				ALfloat gLoc[] {
-					soundpos.x / 4 / soundscalefactor,
-					soundpos.y / 4 / soundscalefactor,
-					soundpos.z / 4 / soundscalefactor,
-				};
 				ALuint gunsound;
 				switch (person[j].whichgun) {
 				case sniperrifle:
@@ -1964,8 +1941,9 @@ void Game::Tick()
 				default: // assaultrifle
 					gunsound = gSourceID[machinegunsound];
 				}
-				alSourcefv(gunsound, AL_POSITION, gLoc);
-				alSourcePlay(gunsound);
+				auto soundpos = start - camera.position;
+				playSound(gunsound, soundpos.x,
+					soundpos.y, soundpos.z);
 			}
 
 			XYZ end {start + aim * 1000};
@@ -2098,9 +2076,6 @@ void Game::Tick()
 				if(m==0){
 
 					if(j==0&&slomo==2){
-
-						soundscalefactor=soundscalefactordefault;
-
 						alSourceStop(gSourceID[whichsong]);
 
 						alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
@@ -2428,17 +2403,10 @@ void Game::Tick()
 						: gSourceID[bodyhitsound];
 					auto hitpos = hitstruct.hitlocation
 						- camera.position;
-					ALfloat gLoc[] {
-						hitpos.x / soundscalefactor / 4,
-						hitpos.y / soundscalefactor / 4,
-						hitpos.z / soundscalefactor / 4,
-					};
-					ALfloat gain = thirdperson ? 0.1f : 1.0f;
-					alSourcef(hitsound, AL_MIN_GAIN, gain);
-					alSourcefv(hitsound, AL_POSITION, gLoc);
-					alSourcePlay(hitsound);
-				}//with wall
+					playSound(hitsound, hitpos.x, hitpos.y, hitpos.z);
+				}
 
+				// with wall
 				if(oldend==finalwallhit){
 
 					decals.MakeDecal(bullethole, finalwallhit,.7,hitnorm, hitpoly, model, hitmove, hitrotation);
@@ -2489,16 +2457,9 @@ void Game::Tick()
 
 					}
 
-					auto wallhitpos = finalwallhit
-						- camera.position;
-					ALfloat gLoc[] {
-						wallhitpos.x / soundscalefactor,
-						wallhitpos.y / soundscalefactor,
-						wallhitpos.z / soundscalefactor,
-					};
-					alSourcefv(gSourceID[wallhitsound],
-						AL_POSITION, gLoc);
-					alSourcePlay(gSourceID[wallhitsound]);
+					auto soundpos = finalwallhit - camera.position;
+					playSound(gSourceID[wallhitsound],
+						soundpos.x, soundpos.y, soundpos.z);
 				}
 
 				lastshot[0]=start;
@@ -3241,7 +3202,6 @@ void Game::Tick()
 	if(slomo==2){
 		psychicpower-=multiplier*15;
 		if(psychicpower<0){
-			soundscalefactor=soundscalefactordefault;
 			alSourceStop(gSourceID[whichsong]);
 			alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
 			alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
diff --git a/src/Person.cpp b/src/Person.cpp
index ea2280c..7630000 100644
--- a/src/Person.cpp
+++ b/src/Person.cpp
@@ -20,6 +20,7 @@
 #include <GLFW/glfw3.h>
 
 #include "Person.h"
+#include "misc.h"
 
 extern float multiplier;
 extern unsigned int gSourceID[37];
@@ -234,9 +235,8 @@ void Person::DoAnimations(int who)
 			auto soundsrc = (DoRotation(head_joint.position,
 				0, playerrotation, 0) + playercoords
 				- camera.position) / soundscalefactor;
-			ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
-			alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
-			alSourcePlay(gSourceID[bodyhitsound]);
+			playSound(gSourceID[bodyhitsound],
+				soundsrc.x, soundsrc.y, soundsrc.z);
 			bleeding = 1;
 			bleeddelay = 1;
 			bjoint1 = &head_joint;
@@ -614,9 +614,8 @@ void Person::DoAnimationslite(int who)
 			auto soundsrc = (DoRotation(head_joint.position,
 				0, playerrotation, 0) + playercoords
 				- camera.position) / soundscalefactor;
-			ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
-			alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
-			alSourcePlay(gSourceID[bodyhitsound]);
+			playSound(gSourceID[bodyhitsound],
+				soundsrc.x, soundsrc.y, soundsrc.z);
 			bleeding = 1;
 			bleeddelay = 1;
 			bjoint1 = &head_joint;
@@ -629,7 +628,6 @@ void Person::DoAnimationslite(int who)
 			targetframe = 0;
 		else if (targetframe < 0)
 			targetframe = animation[currentanimation].numframes - 1;
-
 		target = 0;
 
 		if ((currentanimation == getupfrontanim
diff --git a/src/Skeleton.cpp b/src/Skeleton.cpp
index 4f2a2a7..7dcdaa1 100644
--- a/src/Skeleton.cpp
+++ b/src/Skeleton.cpp
@@ -1,7 +1,7 @@
 /**> HEADER FILES <**/
 #include "Skeleton.h"
-
 #include "Serialize.h"
+#include "misc.h"
 
 extern float multiplier;
 extern unsigned int gSourceID[37];
@@ -169,25 +169,9 @@ void Skeleton::DoConstraints(Model *collide, XYZ *move, float rotation)
 				if (playing != AL_PLAYING
 				    && (findLengthfast(joints[i].velocity) > 2
 				        || findLengthfast(avgvelocity) > 2)) {
-					ALfloat gain =
-						findLengthfast(avgvelocity
-							+ joints[i].velocity)
-						/ findDistancefast(pos,
-							camera.position)
-						* soundscalefactor * 4;
-					alSourcef(gSourceID[landsound],
-						AL_MIN_GAIN, gain);
-					alSourcef(gSourceID[landsound],
-						AL_MAX_GAIN, gain);
-
-					float gLoc[] {
-						pos.x / soundscalefactor,
-						pos.y / soundscalefactor,
-						pos.z / soundscalefactor,
-					};
-					alSourcefv(gSourceID[landsound],
-						AL_POSITION, gLoc);
-					alSourcePlay(gSourceID[landsound]);
+					auto soundpos = pos - camera.position;
+					playSound(gSourceID[landsound],
+						soundpos.x, soundpos.y, soundpos.z);
 				}
 			}
 		}
diff --git a/src/main.zig b/src/main.zig
index 4b116c8..f80d316 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -29,6 +29,7 @@ comptime {
     // Work around lazy compilation.
     @export(misc.loadSound, .{ .name = "loadSound" });
     @export(misc.loadTexture, .{ .name = "loadTexture" });
+    @export(misc.playSound, .{ .name = "playSound" });
 }
 
 var game: *legacy.Game = undefined;
diff --git a/src/misc.h b/src/misc.h
index e3bef7d..638255c 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -4,7 +4,14 @@
 #include <AL/al.h>
 #include <GL/gl.h>
 
-extern "C" ALuint loadSound(const char*);
-extern "C" GLuint loadTexture(const char*);
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+	ALuint loadSound(const char*);
+	GLuint loadTexture(const char*);
+	void playSound(ALuint source, ALfloat x, ALfloat y, ALfloat z);
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
 
 #endif // BLACKSHADES_MISC_H
diff --git a/src/misc.zig b/src/misc.zig
index 9ad5933..353dcac 100644
--- a/src/misc.zig
+++ b/src/misc.zig
@@ -17,6 +17,7 @@
 // along with Black Shades.  If not, see <https://www.gnu.org/licenses/>.
 
 usingnamespace @cImport({
+    @cInclude("AL/al.h");
     @cInclude("GL/gl.h");
     @cInclude("GL/glu.h");
     @cInclude("lodepng.h");
@@ -33,6 +34,7 @@ const sep = std.fs.path.sep;
 const span = std.mem.span;
 const std = @import("std");
 
+/// Load audio file into an OpenAL buffer and return it.
 pub fn loadSound(filename: [*:0]const u8) callconv(.C) u32 {
     const path = join(allocator, &.{ data_dir ++ "sounds", span(filename) })
         catch unreachable;
@@ -49,6 +51,7 @@ fn check(errorString: fn (c_uint) callconv(.C) [*c]const u8,
         @panic(span(errorString(@intCast(c_uint, status))));
 }
 
+/// Load PNG file into an OpenGL buffer and return it.
 pub fn loadTexture(filename: [*:0]const u8) callconv(.C) GLuint {
     var dir = cwd().openDir(data_dir ++ "textures", .{}) catch unreachable;
     defer dir.close();
@@ -81,3 +84,11 @@ pub fn loadTexture(filename: [*:0]const u8) callconv(.C) GLuint {
                                             GL_RGBA, GL_UNSIGNED_BYTE, data));
     return texture;
 }
+
+/// Move sound source to given position and play it.
+pub fn playSound(source: u32, x: f32, y: f32, z: f32) callconv(.C) void {
+    const src = al.Source{ .reference = source };
+    _ = alGetError(); // TODO: remove when completely migrate to zeal
+    src.setPosition(.{ x / 32, y / 32, z / 32 }) catch unreachable;
+    src.play() catch unreachable;
+}