diff --git a/config/defaults.cfg b/config/defaults.cfg index 408dd7a77..75179aac2 100644 --- a/config/defaults.cfg +++ b/config/defaults.cfg @@ -13,12 +13,10 @@ exec "config/brush.cfg" exec "config/setup.cfg" exec "config/legacy.cfg" -exec "config/sounds/package.cfg" exec "config/vanities.cfg" exec "config/usage.cfg" exec "config/tips.cfg" exec "config/menus/package.cfg" // keep this here, it uses some of the stuff above -exec "config/voice.cfg" exec "config/compass.cfg" diff --git a/config/sounds/announcer.cfg b/config/sounds/announcer.cfg deleted file mode 100644 index b50529822..000000000 --- a/config/sounds/announcer.cfg +++ /dev/null @@ -1,37 +0,0 @@ -registersound "sounds/announcer/secured" 150 // S_V_FLAGSECURED -registersound "sounds/announcer/overthrown" 150 // S_V_FLAGOVERTHROWN -registersound "sounds/announcer/alert" 150 // S_V_FLAGPICKUP -registersound "sounds/announcer/warning" 150 // S_V_FLAGDROP -registersound "sounds/announcer/returned" 150 // S_V_FLAGRETURN -registersound "sounds/announcer/captured" 150 // S_V_FLAGSCORE -registersound "sounds/announcer/reset" 150 // S_V_FLAGRESET -registersound "sounds/announcer/fight" 150 // S_V_BOMBSTART -registersound "sounds/announcer/alert" 150 // S_V_BOMBDUEL -registersound "sounds/announcer/secured" 150 // S_V_BOMBPICKUP -registersound "sounds/announcer/score" 150 // S_V_BOMBSCORE -registersound "sounds/announcer/reset" 150 // S_V_BOMBRESET -registersound "sounds/interface/back" 224 // S_V_NOTIFY -registersound "sounds/announcer/fight" 150 // S_V_FIGHT -registersound "sounds/announcer/fight" 128 // S_V_START -registersound "sounds/announcer/checkpoint" 128 // S_V_CHECKPOINT -registersound "sounds/announcer/score" 192 // S_V_COMPLETE -registersound "sounds/announcer/overtime" 150 // S_V_OVERTIME -registersound "sounds/announcer/oneminute" 150 // S_V_ONEMINUTE -registersound "sounds/announcer/headshot" 150 // S_V_HEADSHOT -registersound "sounds/announcer/spree" 180 // S_V_SPREE1 -registersound "sounds/announcer/spree" 180 // S_V_SPREE2 -registersound "sounds/announcer/spree" 180 // S_V_SPREE3 -registersound "sounds/announcer/spreex" 180 // S_V_SPREE4 -registersound "sounds/announcer/multikill" 180 // S_V_MKILL1 -registersound "sounds/announcer/multikill2" 180 // S_V_MKILL2 -registersound "sounds/announcer/multikill3" 180 // S_V_MKILL3 -registersound "sounds/announcer/revenge" 180 // S_V_REVENGE -registersound "sounds/announcer/dominating" 180 // S_V_DOMINATE -registersound "sounds/announcer/firstblood" 180 // S_V_FIRSTBLOOD -registersound "sounds/announcer/breaker" 180 // S_V_BREAKER -registersound "sounds/announcer/youwin" 150 // S_V_YOUWIN -registersound "sounds/announcer/youlose" 150 // S_V_YOULOSE -registersound "sounds/announcer/draw" 150 // S_V_DRAW -registersound "sounds/announcer/fragged" 80 // S_V_FRAGGED -registersound "sounds/announcer/warning" 150 // S_V_BALWARN -registersound "sounds/announcer/alert" 150 // S_V_BALALERT diff --git a/config/sounds/interface.cfg b/config/sounds/interface.cfg deleted file mode 100644 index fddda146d..000000000 --- a/config/sounds/interface.cfg +++ /dev/null @@ -1,3 +0,0 @@ -registersound "sounds/interface/press" 255 // S_GUIPRESS (gui ui_button pressed) -registersound "sounds/interface/back" 255 // S_GUIBACK (gui back one level) -registersound "sounds/interface/change" 255 // S_GUIACT (gui up one level) diff --git a/config/sounds/package.cfg b/config/sounds/package.cfg deleted file mode 100644 index ca65f09c9..000000000 --- a/config/sounds/package.cfg +++ /dev/null @@ -1,5 +0,0 @@ -exec "config/sounds/interface.cfg" -exec "config/sounds/player.cfg" -exec "config/sounds/sfx.cfg" -exec "config/sounds/announcer.cfg" -exec "config/sounds/weapons.cfg" diff --git a/config/sounds/player.cfg b/config/sounds/player.cfg deleted file mode 100644 index a3e22c5d2..000000000 --- a/config/sounds/player.cfg +++ /dev/null @@ -1,7 +0,0 @@ -registersound "sounds/player/jump" 64 100 0 0 // S_JUMP (player jump) -registersound "sounds/player/impulse" 64 100 0 3 // S_IMPULSE (player impulse) -registersound "sounds/player/land" 128 100 0 3 // S_LAND (player landed with high velocity) -registersound "sounds/player/footstep" 248 300 0 5 // S_FOOTSTEP (default footsteps) -registersound "sounds/player/swimstep" 248 200 0 4 // S_SWIMSTEP (liquid footsteps) -registersound "sounds/player/pain" 130 200 0 6 // S_PAIN (player damage) -registersound "sounds/player/death" 200 270 0 5 // S_DEATH (player die) diff --git a/config/sounds/weapons.cfg b/config/sounds/weapons.cfg deleted file mode 100644 index 8aca9ac17..000000000 --- a/config/sounds/weapons.cfg +++ /dev/null @@ -1,280 +0,0 @@ -registersound "sounds/weapons/sword/primary" 205 150 0 0 // claw primary fire -registersound "sounds/weapons/sword/secondary" 205 150 0 0 // claw secondary fire -registersound "sounds/weapons/sword/power" 160 100 0 0 // claw primary powerup/cook -registersound "sounds/weapons/sword/power" 160 100 0 0 // claw secondary powerup/cook -registersound "sounds/weapons/sword/power" 160 100 0 0 // claw zoom -registersound "sounds/weapons/sword/switch" 185 100 0 0 // claw switch to weapon -registersound "sounds/weapons/reload" 185 100 0 0 // claw reload weapon -registersound "sounds/weapons/notify" 185 100 0 0 // claw notify reload complete -registersound "sounds/weapons/explode" 32 200 0 3 // claw primary projectile destroy (explode) -registersound "sounds/weapons/explode" 32 200 0 3 // claw secondary projectile destroy (explode) -registersound 0 0 0 0 // claw primary projectile destroy (non-explode) -registersound 0 0 0 0 // claw secondary projectile destroy (non-explode) -registersound "sounds/weapons/thwack" 192 120 0 3 // claw primary projectile impact -registersound "sounds/weapons/thwack" 224 160 0 3 // claw secondary projectile impact -registersound 0 0 0 0 // claw primary projectile extinguished -registersound 0 0 0 0 // claw secondary projectile extinguished -registersound 0 0 0 0 // claw primary projectile in transit -registersound 0 0 0 0 // claw secondary projectile in transit -registersound "sounds/weapons/tink" 12 50 0 0 // claw primary projectile bounce/ricochet -registersound "sounds/weapons/tink" 12 50 0 0 // claw secondary projectile bounce/ricochet -registersound "sounds/weapons/pistol/primary" 150 180 0 3 // pistol primary fire -registersound "sounds/weapons/pistol/secondary" 150 180 0 2 // pistol secondary fire -registersound "sounds/weapons/rocket/power" 225 100 0 0 // pistol primary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // pistol secondary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // pistol zoom -registersound "sounds/weapons/pistol/notify" 170 80 0 0 // pistol switch to weapon -registersound "sounds/weapons/pistol/reload" 170 80 0 0 // pistol reload weapon -registersound "sounds/weapons/pistol/notify" 170 80 0 0 // pistol notify reload complete -registersound "sounds/sfx/shell" 100 50 0 6 // pistol primary projectile destroy (explode) -registersound "sounds/sfx/shell" 100 50 0 6 // pistol secondary projectile destroy (explode) -registersound "sounds/sfx/shell" 100 50 0 6 // pistol primary projectile destroy (non-explode) -registersound "sounds/sfx/shell" 100 50 0 6 // pistol secondary projectile destroy (non-explode) -registersound 0 0 0 0 // pistol primary projectile impact -registersound 0 0 0 0 // pistol secondary projectile impact -registersound "sounds/sfx/shell" 100 50 0 6 // pistol primary projectile extinguished -registersound "sounds/sfx/shell" 10 50 0 6 // pistol secondary projectile extinguished -registersound 0 0 0 0 // pistol primary projectile in transit -registersound 0 0 0 0 // pistol secondary projectile in transit -registersound "sounds/weapons/ricochet" 36 80 0 0 // pistol primary projectile bounce/ricochet -registersound "sounds/weapons/ricochet" 36 80 0 0 // pistol secondary projectile bounce/ricochet -registersound "sounds/weapons/sword/primary" 205 150 0 0 // sword primary fire -registersound "sounds/weapons/sword/secondary" 205 150 0 0 // sword secondary fire -registersound "sounds/weapons/sword/power" 160 100 0 0 // sword primary powerup/cook -registersound "sounds/weapons/sword/power" 160 100 0 0 // sword secondary powerup/cook -registersound "sounds/weapons/sword/power" 160 100 0 0 // sword zoom -registersound "sounds/weapons/sword/switch" 185 100 0 0 // sword switch to weapon -registersound "sounds/weapons/reload" 185 100 0 0 // sword reload weapon -registersound "sounds/weapons/notify" 185 100 0 0 // sword notify reload complete -registersound "sounds/weapons/explode" 32 200 0 3 // sword primary projectile destroy (explode) -registersound "sounds/weapons/explode" 32 200 0 3 // sword secondary projectile destroy (explode) -registersound 0 0 0 0 // sword primary projectile destroy (non-explode) -registersound 0 0 0 0 // sword secondary projectile destroy (non-explode) -registersound "sounds/weapons/thwack" 192 120 0 3 // sword primary projectile impact -registersound "sounds/weapons/thwack" 224 160 0 3 // sword secondary projectile impact -registersound 0 0 0 0 // sword primary projectile extinguished -registersound 0 0 0 0 // sword secondary projectile extinguished -registersound 0 0 0 0 // sword primary projectile in transit -registersound 0 0 0 0 // sword secondary projectile in transit -registersound "sounds/weapons/tink" 12 50 0 0 // sword primary projectile bounce/ricochet -registersound "sounds/weapons/tink" 12 50 0 0 // sword secondary projectile bounce/ricochet -registersound "sounds/weapons/sword/switch" 185 100 0 0 // sword item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // sword item spawned -registersound "sounds/weapons/shotgun/primary" 200 300 0 2 // shotgun primary fire -registersound "sounds/weapons/shotgun/secondary" 190 300 0 0 // shotgun secondary fire -registersound "sounds/weapons/rocket/power" 225 100 0 0 // shotgun primary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // shotgun secondary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // shotgun zoom -registersound "sounds/weapons/shotgun/notify" 130 100 0 0 // shotgun switch to weapon -registersound "sounds/weapons/shotgun/reload" 150 100 0 0 // shotgun reload weapon -registersound "sounds/weapons/shotgun/notify" 110 100 0 0 // shotgun notify reload complete -registersound "sounds/sfx/shell" 80 50 0 6 // shotgun primary projectile destroy (explode) -registersound "sounds/weapons/shotgun/explode" 100 100 0 2 // shotgun secondary projectile destroy (explode) -registersound "sounds/sfx/shell" 80 50 0 6 // shotgun primary projectile destroy (non-explode) -registersound "sounds/weapons/shotgun/explode" 100 100 0 2 // shotgun secondary projectile destroy (non-explode) -registersound 0 0 0 0 // shotgun primary projectile impact -registersound 0 0 0 0 // shotgun secondary projectile impact -registersound "sounds/sfx/shell" 40 50 0 6 // shotgun primary projectile extinguished -registersound "sounds/sfx/shell" 80 50 0 6 // shotgun secondary projectile extinguished -registersound "sounds/weapons/whizz" 25 40 0 0 // shotgun primary projectile in transit -registersound 0 0 0 0 // shotgun secondary projectile in transit -registersound "sounds/sfx/shell" 170 50 0 6 // shotgun primary projectile bounce/ricochet -registersound "sounds/sfx/shell" 170 50 0 6 // shotgun secondary projectile bounce/ricochet -registersound "sounds/weapons/shotgun/notify" 130 100 0 0 // shotgun item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // shotgun item spawned -registersound "sounds/weapons/smg/primary" 210 270 0 0 // smg primary fire -registersound "sounds/weapons/smg/secondary" 200 270 0 3 // smg secondary fire -registersound "sounds/weapons/rocket/power" 225 100 0 0 // smg primary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // smg secondary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // smg zoom -registersound "sounds/weapons/smg/notify" 180 100 0 0 // smg switch to weapon -registersound "sounds/weapons/smg/reload" 130 100 0 0 // smg reload weapon -registersound "sounds/weapons/smg/notify" 224 100 0 0 // smg notify reload complete -registersound "sounds/weapons/shotgun/explode" 120 200 0 2 // smg primary projectile destroy (explode) -registersound "sounds/weapons/shotgun/explode" 120 200 0 2 // smg secondary projectile destroy (explode) -registersound "sounds/weapons/bzap" 48 100 0 0 // smg primary projectile destroy (non-explode) -registersound "sounds/weapons/bzap" 48 100 0 0 // smg secondary projectile destroy (non-explode) -registersound 0 0 0 0 // smg primary projectile impact -registersound 0 0 0 0 // smg secondary projectile impact -registersound "sounds/sfx/shell" 170 50 0 6 // smg primary projectile extinguished -registersound "sounds/sfx/shell" 170 50 0 6 // smg secondary projectile extinguished -registersound "sounds/weapons/whizz" 40 50 0 0 // smg primary projectile in transit -registersound "sounds/weapons/whizz" 30 50 0 0 // smg secondary projectile in transit -registersound "sounds/sfx/shell" 170 50 0 6 // smg primary projectile bounce/ricochet -registersound "sounds/sfx/shell" 170 50 0 6 // smg secondary projectile bounce/ricochet -registersound "sounds/weapons/smg/notify" 180 100 0 0 // smg item used -registersound "sounds/sfx/itemspawn" 120 150 0 0 // smg item spawned -registersound "sounds/weapons/flamer/primary" 230 150 0 0 // flamer primary fire -registersound "sounds/weapons/flamer/secondary" 250 170 0 0 // flamer secondary fire -registersound "sounds/weapons/flamer/power" 220 100 0 0 // flamer primary powerup/cook -registersound "sounds/weapons/flamer/power" 220 100 0 0 // flamer secondary powerup/cook -registersound "sounds/weapons/flamer/power" 220 100 0 0 // flamer zoom -registersound "sounds/weapons/flamer/notify" 180 100 0 0 // flamer switch to weapon -registersound "sounds/weapons/flamer/reload" 240 100 0 0 // flamer reload weapon -registersound "sounds/weapons/flamer/notify" 180 100 0 0 // flamer notify reload complete -registersound 0 0 0 0 // flamer primary projectile destroy (explode) -registersound 0 0 0 0 // flamer secondary projectile destroy (explode) -registersound 0 0 0 0 // flamer primary projectile destroy (non-explode) -registersound 0 0 0 0 // flamer secondary projectile destroy (non-explode) -registersound "sounds/weapons/singe" 156 150 0 3 // flamer primary projectile impact -registersound "sounds/weapons/singe" 98 100 0 3 // flamer secondary projectile impact -registersound "sounds/sfx/extinguish" 156 200 0 0 // flamer primary projectile extinguished -registersound "sounds/weapons/bzzt" 128 100 0 0 // flamer secondary projectile extinguished -registersound 0 0 0 0 // flamer primary projectile in transit -registersound 0 0 0 0 // flamer secondary projectile in transit -registersound 0 0 0 0 // flamer primary projectile bounce/ricochet -registersound 0 0 0 0 // flamer secondary projectile bounce/ricochet -registersound "sounds/weapons/flamer/notify" 180 100 0 0 // flamer item used -registersound "sounds/sfx/itemspawn" 192 100 0 0 // flamer item spawned -registersound "sounds/weapons/plasma/primary" 240 280 0 3 // plasma primary fire -registersound "sounds/weapons/plasma/secondary" 200 500 0 0 // plasma secondary fire -registersound "sounds/weapons/plasma/power" 170 100 0 0 // plasma primary powerup/cook -registersound "sounds/weapons/plasma/power" 170 100 0 0 // plasma secondary powerup/cook -registersound "sounds/weapons/plasma/power" 170 100 0 0 // plasma zoom -registersound "sounds/weapons/plasma/notify" 200 100 0 0 // plasma switch to weapon -registersound "sounds/weapons/plasma/reload" 170 100 0 0 // plasma reload weapon -registersound "sounds/weapons/plasma/notify" 200 100 0 0 // plasma notify reload complete -registersound "sounds/weapons/energy" 128 100 0 0 // plasma primary projectile destroy (explode) -registersound "sounds/weapons/energy" 128 100 0 0 // plasma secondary projectile destroy (explode) -registersound "sounds/weapons/energy" 128 100 0 0 // plasma primary projectile destroy (non-explode) -registersound "sounds/weapons/energy" 128 100 0 0 // plasma secondary projectile destroy (non-explode) -registersound "sounds/weapons/singe" 128 100 0 3 // plasma primary projectile impact -registersound 0 0 0 0 // plasma secondary projectile impact -registersound "sounds/sfx/extinguish" 156 200 0 0 // plasma primary projectile extinguished -registersound "sounds/sfx/extinguish" 156 200 0 0 // plasma secondary projectile extinguished -registersound "sounds/weapons/plasma/transit" 50 50 0 0 // plasma primary projectile in transit -registersound "sounds/weapons/plasma/transit" 128 150 0 0 // plasma secondary projectile in transit -registersound "sounds/weapons/bzzt" 128 100 0 0 // plasma primary projectile bounce/ricochet -registersound "sounds/weapons/bzzt" 128 100 0 0 // plasma secondary projectile bounce/ricochet -registersound "sounds/weapons/plasma/notify" 200 100 0 0 // plasma item used -registersound "sounds/sfx/itemspawn" 192 100 0 0 // plasma item spawned -registersound "sounds/weapons/zapper/primary" 200 250 0 4 // zapper primary fire -registersound "sounds/weapons/zapper/secondary" 200 350 0 0 // zapper secondary fire -registersound "sounds/weapons/zapper/power" 170 100 0 0 // zapper primary powerup/cook -registersound "sounds/weapons/zapper/power" 170 100 0 0 // zapper secondary powerup/cook -registersound "sounds/weapons/zapper/power" 170 100 0 0 // zapper zoom -registersound "sounds/weapons/zapper/notify" 200 100 0 0 // zapper switch to weapon -registersound "sounds/weapons/plasma/reload" 170 100 0 0 // zapper reload weapon -registersound "sounds/weapons/zapper/notify" 240 100 0 0 // zapper notify reload complete -registersound "sounds/weapons/energy" 64 100 0 0 // zapper primary projectile destroy (explode) -registersound "sounds/weapons/energy" 64 100 0 0 // zapper secondary projectile destroy (explode) -registersound 0 0 0 0 // zapper primary projectile destroy (non-explode) -registersound 0 0 0 0 // zapper secondary projectile destroy (non-explode) -registersound 0 0 0 0 // zapper primary impact -registersound 0 0 0 0 // zapper secondary impact -registersound "sounds/sfx/extinguish" 64 200 0 0 // zapper primary projectile extinguished -registersound "sounds/sfx/extinguish" 64 200 0 0 // zapper secondary projectile extinguished -registersound 0 0 0 0 // zapper primary projectile in transit -registersound 0 0 0 0 // zapper secondary projectile in transit -registersound "sounds/weapons/bzzt" 128 100 0 0 // zapper primary projectile bounce/ricochet -registersound "sounds/weapons/bzzt" 128 100 0 0 // zapper secondary projectile bounce/ricochet -registersound "sounds/weapons/zapper/notify" 240 100 0 0 // zapper item used -registersound "sounds/sfx/itemspawn" 192 100 0 0 // zapper item spawned -registersound "sounds/weapons/rifle/primary" 245 300 0 3 // rifle primary fire -registersound "sounds/weapons/rifle/secondary" 220 400 0 0 // rifle secondary fire -registersound "sounds/weapons/plasma/power" 224 100 0 0 // rifle primary powerup/cook -registersound "sounds/weapons/plasma/power" 224 100 0 0 // rifle secondary powerup/cook -registersound "sounds/weapons/plasma/power" 224 100 0 0 // rifle zoom -registersound "sounds/weapons/rifle/notify" 220 100 0 0 // rifle switch to weapon -registersound "sounds/weapons/rifle/reload" 125 100 0 0 // rifle reload weapon -registersound "sounds/weapons/rifle/notify" 190 100 0 0 // rifle notify reload complete -registersound "sounds/weapons/rifle/explode" 200 350 0 3 // rifle primary projectile destroy (explode) -registersound "sounds/weapons/rifle/explode" 200 350 0 3 // rifle secondary projectile destroy (explode) -registersound "sounds/weapons/energy" 128 100 0 0 // rifle primary projectile destroy (non-explode) -registersound "sounds/weapons/energy" 128 100 0 0 // rifle secondary projectile destroy (non-explode) -registersound 0 0 0 0 // rifle primary projectile impact -registersound 0 0 0 0 // rifle secondary projectile impact -registersound "sounds/sfx/extinguish" 156 200 0 0 // rifle primary projectile extinguished -registersound "sounds/sfx/extinguish" 156 200 0 0 // rifle secondary projectile extinguished -registersound "sounds/weapons/rifle/transit" 156 500 0 0 // rifle primary projectile in transit -registersound "sounds/weapons/rifle/transit" 156 500 0 0 // rifle secondary projectile in transit -registersound "sounds/weapons/bzzt" 64 100 0 0 // rifle primary projectile bounce/ricochet -registersound "sounds/weapons/bzzt" 64 100 0 0 // rifle secondary projectile bounce/ricochet -registersound "sounds/weapons/rifle/notify" 220 100 0 0 // rifle item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // rifle item spawned -registersound "sounds/weapons/grenade/primary" 128 200 0 0 // grenade primary fire -registersound "sounds/weapons/grenade/primary" 128 200 0 0 // grenade secondary fire -registersound "sounds/weapons/grenade/beep" 192 100 0 0 // grenade primary powerup/cook -registersound "sounds/weapons/grenade/beep" 192 100 0 0 // grenade secondary powerup/cook -registersound "sounds/weapons/grenade/beep" 192 100 0 0 // grenade zoom -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // grenade switch to weapon -registersound "sounds/weapons/reload" 192 100 0 0 // grenade reload weapon -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // grenade notify reload complete -registersound "sounds/weapons/explode" 224 600 0 3 // grenade primary projectile destroy (explode) -registersound "sounds/weapons/explode" 224 600 0 3 // grenade secondary projectile destroy (explode) -registersound "sounds/weapons/explode" 224 600 0 3 // grenade primary projectile destroy (non-explode) -registersound "sounds/weapons/explode" 224 600 0 3 // grenade secondary projectile destroy (non-explode) -registersound 0 0 0 0 // grenade primary projectile impact -registersound 0 0 0 0 // grenade secondary projectile impact -registersound "sounds/sfx/extinguish" 156 200 0 0 // grenade primary projectile extinguished -registersound "sounds/sfx/extinguish" 156 200 0 0 // grenade secondary projectile extinguished -registersound "sounds/weapons/grenade/beep" 192 200 0 0 // grenade primary projectile in transit -registersound "sounds/weapons/grenade/beep" 192 200 0 0 // grenade secondary projectile in transit -registersound "sounds/weapons/tink" 128 200 0 0 // grenade primary projectile bounce/ricochet -registersound "sounds/weapons/tink" 128 200 0 0 // grenade secondary projectile bounce/ricochet -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // grenade item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // grenade item spawned -registersound "sounds/weapons/grenade/primary" 128 200 0 0 // mine primary fire -registersound "sounds/weapons/grenade/primary" 128 200 0 0 // mine secondary fire -registersound "sounds/weapons/mine/beep" 156 100 0 0 // mine primary powerup/cook -registersound "sounds/weapons/mine/beep" 156 100 0 0 // mine secondary powerup/cook -registersound "sounds/weapons/mine/beep" 156 100 0 0 // mine zoom -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // mine switch to weapon -registersound "sounds/weapons/reload" 192 100 0 0 // mine reload weapon -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // mine notify reload complete -registersound "sounds/weapons/mine/explode" 224 600 0 3 // mine primary projectile destroy (explode) -registersound "sounds/weapons/mine/explode" 224 600 0 3 // mine secondary projectile destroy (explode) -registersound "sounds/weapons/mine/explode" 224 600 0 3 // mine primary projectile destroy (non-explode) -registersound "sounds/weapons/mine/explode" 224 600 0 3 // mine secondary projectile destroy (non-explode) -registersound 0 0 0 0 // mine primary projectile impact -registersound 0 0 0 0 // mine secondary projectile impact -registersound "sounds/sfx/extinguish" 156 200 0 0 // mine primary projectile extinguished -registersound "sounds/sfx/extinguish" 156 200 0 0 // mine secondary projectile extinguished -registersound "sounds/weapons/mine/beep" 156 100 0 0 // mine primary projectile in transit -registersound "sounds/weapons/mine/beep" 156 100 0 0 // mine secondary projectile in transit -registersound "sounds/weapons/tink" 128 200 0 0 // mine primary projectile bounce/ricochet -registersound "sounds/weapons/tink" 128 200 0 0 // mine secondary projectile bounce/ricochet -registersound "sounds/weapons/grenade/switch" 105 100 0 0 // mine item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // mine item spawned -registersound "sounds/weapons/rocket/primary" 255 400 0 3 // rocket primary fire -registersound "sounds/weapons/rocket/primary" 255 400 0 3 // rocket secondary fire -registersound "sounds/weapons/rocket/power" 225 100 0 0 // rocket primary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // rocket secondary powerup/cook -registersound "sounds/weapons/rocket/power" 225 100 0 0 // rocket zoom -registersound "sounds/weapons/rocket/reload" 200 100 0 0 // rocket switch to weapon -registersound "sounds/weapons/rocket/reload" 250 100 0 0 // rocket reload weapon -registersound "sounds/weapons/rocket/notify" 255 100 0 0 // rocket notify reload complete -registersound "sounds/weapons/explode" 224 800 0 3 // rocket primary projectile destroy (explode) -registersound "sounds/weapons/explode" 224 800 0 3 // rocket secondary projectile destroy (explode) -registersound "sounds/weapons/explode" 224 800 0 3 // rocket primary projectile destroy (non-explode) -registersound "sounds/weapons/explode" 224 800 0 3 // rocket secondary projectile destroy (non-explode) -registersound 0 0 0 0 // rocket primary projectile impact -registersound 0 0 0 0 // rocket secondary projectile impact -registersound "sounds/sfx/extinguish" 155 200 0 0 // rocket primary projectile extinguished -registersound "sounds/sfx/extinguish" 155 200 0 0 // rocket secondary projectile extinguished -registersound "sounds/weapons/rocket/transit" 255 300 0 0 // rocket primary projectile in transit -registersound "sounds/weapons/rocket/transit" 255 300 0 0 // rocket secondary projectile in transit -registersound "sounds/weapons/tink" 128 200 0 0 // rocket primary projectile bounce/ricochet -registersound "sounds/weapons/tink" 128 200 0 0 // rocket secondary projectile bounce/ricochet -registersound "sounds/weapons/rocket/notify" 250 100 0 0 // rocket item used -registersound "sounds/sfx/itemspawn" 192 150 0 0 // rocket item spawned -registersound 0 0 0 0 // melee primary fire -registersound 0 0 0 0 // melee secondary fire -registersound 0 0 0 0 // melee primary powerup/cook -registersound 0 0 0 0 // melee secondary powerup/cook -registersound 0 0 0 0 // melee zoom -registersound "sounds/weapons/switch" 156 100 0 0 // melee switch to weapon -registersound "sounds/weapons/reload" 192 100 0 0 // melee reload weapon -registersound 0 0 0 0 // melee notify reload complete -registersound 0 0 0 0 // melee primary projectile destroy (explode) -registersound 0 0 0 0 // melee secondary projectile destroy (explode) -registersound 0 0 0 0 // melee primary projectile destroy (non-explode) -registersound 0 0 0 0 // melee secondary projectile destroy (non-explode) -registersound "sounds/weapons/thud" 192 120 0 3 // melee primary projectile impact -registersound "sounds/weapons/thud" 224 160 0 3 // melee secondary projectile impact -registersound 0 0 0 0 // melee primary projectile extinguished -registersound 0 0 0 0 // melee secondary projectile extinguished -registersound 0 0 0 0 // melee primary projectile in transit -registersound 0 0 0 0 // melee secondary projectile in transit -registersound "sounds/weapons/ricochet" 36 80 0 0 // melee primary projectile bounce/ricochet -registersound "sounds/weapons/ricochet" 36 80 0 0 // melee secondary projectile bounce/ricochet diff --git a/config/voice.cfg b/config/voice.cfg deleted file mode 100644 index 0d5fda939..000000000 --- a/config/voice.cfg +++ /dev/null @@ -1,43 +0,0 @@ -// compass/voice actions - -voices = 0 -addvoice = [ - voices = (+ $voices 1) - [voice@[voices]str] = $arg1 - [voice@[voices]snd] = (registersound $arg2 255 512 8 $arg3) -] - -addvoice "argh" "voice/argh" 2 -addvoice "lucky shot" "voice/luckyshot" 2 -addvoice "ls~" "voice/luckyshot" 1 // reuse -addvoice "nice shot" "voice/niceshot" 2 -addvoice "ns~" "voice/niceshot" 1 // reuse -addvoice "boom" "voice/boom" 2 -addvoice "damn" "voice/damnit" 2 -addvoice "haha" "voice/haha" 2 -addvoice "suck" "voice/suckit" 2 -addvoice "pzap" "voice/pzap" 2 -addvoice "yes~" "voice/yes" 2 -addvoice "sorry" "voice/sorry" 2 -addvoice "sry~" "voice/sorry" 1 // reuse -addvoice "no problem" "voice/noproblem" 2 -addvoice "np~" "voice/noproblem" 1 // reuse -addvoice "no prob" "voice/noproblem" 1 // reuse -addvoice "gno prob" "voice/noproblem" 1 // reuse -addvoice "no~" "voice/no" 2 -addvoice "gno~" "voice/no" 1 // reuse -addvoice "go go go" "voice/gogogo" 2 -addvoice "gogogo" "voice/gogogo" 1 // reuse -addvoice "hang on" "voice/hangon" 2 -addvoice "thanks" "voice/thanks" 2 -addvoice "ty~" "voice/thanks" 1 // reuse - -on_text = [ - id = 0 - reg = [@(filter $arg4)~] // the ~ allows absolute matching, like in yes/no/etc - loopwhile i $voices [= $id 0] [ - str = $[voice@(+ $i 1)str] - if (stringncasecmp $str $reg (stringlen $str)) [ id = (+ $i 1) ] - ] - result (getalias [voice@[id]snd]) -] diff --git a/src/cmake/build_client.cmake b/src/cmake/build_client.cmake index ae13cc4fb..a320f5d3d 100644 --- a/src/cmake/build_client.cmake +++ b/src/cmake/build_client.cmake @@ -62,7 +62,13 @@ if(BUILD_CLIENT) engine/skelmodel.h engine/smd.h engine/sound.h + engine/soundsample.h + engine/soundsample.cpp + engine/soundslot.h + engine/soundslot.cpp engine/textedit.h + engine/soundslot_collection.h + engine/soundslot_collection.cpp engine/texture.h engine/version.h engine/vertmodel.h diff --git a/src/cmake/build_genkey.cmake b/src/cmake/build_genkey.cmake index 7ca5b0184..ac02dd83d 100644 --- a/src/cmake/build_genkey.cmake +++ b/src/cmake/build_genkey.cmake @@ -17,6 +17,13 @@ if(BUILD_GENKEY) engine/genkey.cpp shared/crypto.cpp + shared/cube.h + shared/tools.h + shared/command.h + shared/geom.h + shared/ents.h + shared/iengine.h + shared/igame.h ) add_blue_nebula_executable(genkey${BIN_SUFFIX} ${genkey_sources}) diff --git a/src/cmake/build_server.cmake b/src/cmake/build_server.cmake index 4806c7f14..25645ac2a 100644 --- a/src/cmake/build_server.cmake +++ b/src/cmake/build_server.cmake @@ -33,15 +33,29 @@ if(BUILD_SERVER) shared/tools.h shared/crypto.cpp + shared/cube.h + shared/tools.h + shared/command.h + shared/geom.h + shared/ents.h + shared/iengine.h + shared/igame.h shared/geom.cpp shared/stream.cpp shared/tools.cpp shared/zip.cpp + engine/engine.h + engine/version.h engine/command.cpp engine/irc.cpp engine/master.cpp engine/server.cpp game/server.cpp + game/capturemode.h + game/defendmode.h + game/bombermode.h + game/duelmut.h + game/aiman.h ) # dependencies are imported globally in src/CMakeLists.txt diff --git a/src/engine/main.cpp b/src/engine/main.cpp index f59f07213..e1b6e0a30 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -1,6 +1,7 @@ // main.cpp: initialisation & main loop #include "engine.h" #include +#include string caption = ""; @@ -1064,6 +1065,7 @@ int main(int argc, char **argv) conoutf("loading sound.."); initsound(); + game::load_game_sounds(); game::start(); diff --git a/src/engine/sound.cpp b/src/engine/sound.cpp index acf17bf4c..0658e21ae 100644 --- a/src/engine/sound.cpp +++ b/src/engine/sound.cpp @@ -1,24 +1,8 @@ +#include +#include #include "engine.h" #include "SDL_mixer.h" -struct soundsample -{ - Mix_Chunk *sound; - char *name; - - soundsample() : name(NULL) {} - ~soundsample() { DELETEA(name); } - - void cleanup() - { - Mix_FreeChunk(sound); - sound = NULL; - } -}; - -soundslot::soundslot() : vol(255), maxrad(-1), minrad(-1), name(NULL) {} -soundslot::~soundslot() { DELETEA(name); } - sound::sound() : hook(NULL) { reset(); } sound::~sound() {} bool sound::playing() { return chan >= 0 && (Mix_Playing(chan) || Mix_Paused(chan)); } @@ -38,7 +22,11 @@ void sound::reset() } hashnameset soundsamples; -vector gamesounds, mapsounds; + +soundslot_collection gamesounds; +soundslot_collection mapsounds; + +// TODO: "upgrade" to std::vector vector sounds; bool nosound = true, changedvol = false, canmusic = false; @@ -130,7 +118,7 @@ void stopsound() clearsound(); enumerate(soundsamples, soundsample, s, s.cleanup()); soundsamples.clear(); - gamesounds.setsize(0); + gamesounds.clear(); closemumble(); Mix_CloseAudio(); nosound = true; @@ -145,24 +133,47 @@ void removesound(int c) void clearsound() { loopv(sounds) removesound(i); - mapsounds.setsize(0); + mapsounds.clear(); // could introduce problems } -void getsounds(bool mapsnd, int idx, int prop) -{ - vector &soundset = mapsnd ? mapsounds : gamesounds; - if(idx < 0) intret(soundset.length()); - else if(soundset.inrange(idx)) - { - if(prop < 0) intret(4); - else switch(prop) - { - case 0: intret(soundset[idx].vol); break; - case 1: intret(soundset[idx].maxrad); break; - case 2: intret(soundset[idx].minrad); break; - case 3: result(soundset[idx].name); break; - default: break; +template +void getsounds(T soundslots, ssize_t sound_index, int prop) { + if (soundslots.contains(sound_index)) { + if (prop < 0) { + intret(4); + } else { + const auto& slot = soundslots[sound_index]; + + switch (prop) { + case 0: + intret(slot.vol); + break; + case 1: + intret(slot.maxrad); + break; + case 2: + intret(slot.minrad); + break; + case 3: + result(slot.name); + break; + default: + break; + } + } + } +} + +void getsounds(bool is_map_sound, ssize_t sound_index, int prop) { + if (is_map_sound) { + // FIXME: this used to be implemented for gamesounds as well, but it doesn't seem very useful there + if (sound_index < 0) { + intret(mapsounds.size()); + } else { + return getsounds(mapsounds, sound_index, prop); } + } else { + return getsounds(gamesounds, sound_index, prop); } } ICOMMAND(0, getsound, "ibb", (int *n, int *v, int *p), getsounds(*n!=0, *v, *p)); @@ -291,13 +302,7 @@ void smartmusic(bool cond, bool init) } ICOMMAND(0, smartmusic, "i", (int *a), smartmusic(*a)); -int findsound(const char *name, int vol, vector &soundset) -{ - loopv(soundset) if(!strcmp(soundset[i].name, name) && (!vol || soundset[i].vol == vol)) return i; - return -1; -} - -static Mix_Chunk *loadwav(const char *name) +Mix_Chunk* loadwav(const char *name) { Mix_Chunk *c = NULL; stream *z = openzipfile(name, "rb"); @@ -315,85 +320,35 @@ static Mix_Chunk *loadwav(const char *name) return c; } -int addsound(const char *name, int vol, int maxrad, int minrad, int value, vector &soundset) -{ - if(vol <= 0 || vol >= 255) vol = 255; - if(maxrad <= 0) maxrad = -1; - if(minrad < 0) minrad = -1; - if(value == 1) - { - loopv(soundset) - { - soundslot &slot = soundset[i]; - if(slot.vol == vol && slot.maxrad == maxrad && slot.minrad == minrad && !strcmp(slot.name, name)) - return i; - } - } - if(!strcmp(name, "")) - { - soundslot &slot = soundset.add(); - slot.name = newstring(name); - slot.vol = 0; - slot.maxrad = slot.minrad = -1; - return soundset.length()-1; - } - soundsample *sample = NULL; - #define loadsound(req) \ - { \ - if(!(sample = soundsamples.access(req))) \ - { \ - char *n = newstring(req); \ - sample = &soundsamples[n]; \ - sample->name = n; \ - sample->sound = NULL; \ - } \ - if(!sample->sound) \ - { \ - string buf; \ - const char *dirs[] = { "", "sounds/" }, *exts[] = { "", ".wav", ".ogg" }; \ - bool found = false; \ - loopi(sizeof(dirs)/sizeof(dirs[0])) \ - { \ - loopk(sizeof(exts)/sizeof(exts[0])) \ - { \ - formatstring(buf, "%s%s%s", dirs[i], sample->name, exts[k]); \ - if((sample->sound = loadwav(buf)) != NULL) found = true; \ - if(found) break; \ - } \ - if(found) break; \ - } \ - } \ - } - string sam; - loopi(value > 1 ? 2 : 1) - { - if(value > 1 && !i) formatstring(sam, "%s1", name); - else copystring(sam, name); - loadsound(sam); - if(!sample->sound) - { - if(value < 2 || i) conoutf("\frfailed to load sample: %s", name); - } - else break; - } - soundslot &slot = soundset.add(); - slot.name = newstring(name); - slot.vol = vol; - slot.maxrad = maxrad; // use these values if none are supplied when playing - slot.minrad = minrad; - slot.samples.add(sample); - if(value > 1) loopi(value-1) - { - formatstring(sam, "%s%d", name, i+2); - loadsound(sam); - if(!sample->sound) conoutf("\frfailed to load sample: %s", sam); - else slot.samples.add(sample); - } - return soundset.length()-1; +/** + * Register a game sound in the game. Convenience frontend for add_sound. + * @param name path to the sound file (relative to data directory) + * @param volume volume sound is played with (see soundslot) + * @param max_radius maximum radius sound is played in (see soundslot) + * @param min_radius minimum radius sound is played in (see soundslot) + * @param num_slots amount of slots to load for sound "name" + * @param sound_index index of sound in the sounds enum (or -1 for map sounds) + * @return < 0 on failure, index of registered sound on success (also if the sound was not added because it existed already) + */ +size_t add_game_sound(size_t sound_index, const std::string& name, int volume, int max_radius, int min_radius, int num_slots) { + return gamesounds.insert(sound_index, name, volume, max_radius, min_radius, num_slots); } -ICOMMAND(0, registersound, "sissi", (char *n, int *v, char *w, char *x, int *u), intret(addsound(n, *v, *w ? parseint(w) : -1, *x ? parseint(x) : -1, *u, gamesounds))); -ICOMMAND(0, mapsound, "sissi", (char *n, int *v, char *w, char *x, int *u), intret(addsound(n, *v, *w ? parseint(w) : -1, *x ? parseint(x) : -1, *u, mapsounds))); +/** + * Register a game sound in the game. Convenience frontend for add_sound. + * @param name path to the sound file (relative to data directory) + * @param volume volume sound is played with (see soundslot) + * @param max_radius maximum radius sound is played in (see soundslot) + * @param min_radius minimum radius sound is played in (see soundslot) + * @param num_slots amount of slots to load for sound "name" + * @return < 0 on failure, index of registered sound on success (also if the sound was not added because it existed already) + */ +size_t add_map_sound(const std::string& name, int volume, int max_radius, int min_radius, int num_slots) { + return mapsounds.append(name, volume, max_radius, min_radius, num_slots); +} +ICOMMAND(0, mapsound, "sissi", (char* name, const int* volume, char* max_radius, char* min_radius, int* num_slots), + intret(add_map_sound(name, *volume, *max_radius != '\0' ? parseint(max_radius) : -1, *min_radius != '\0' ? parseint(min_radius) : -1, *num_slots)) +) void calcvol(int flags, int vol, int slotvol, int maxrad, int minrad, const vec &pos, int *curvol, int *curpan, bool liquid) { @@ -454,6 +409,65 @@ void updatesound(int chan) } } +template +void updatesounds(T& soundset, sound& s, int i) { + while(!s.buffer.empty() && (soundset.contains(s.buffer[0]) || soundset[s.buffer[0]].samples.empty() || !soundset[s.buffer[0]].vol)) { + s.buffer.remove(0); + } + + if(!s.buffer.empty()) + { + int n = s.buffer[0], chan = -1; + Mix_HaltChannel(i); + s.buffer.remove(0); + bool nocull = s.flags&SND_NOCULL || s.pos.dist(camera1->o) <= 0; + soundslot& slot = soundset[n]; + soundsample *sample = slot.samples[rnd(slot.samples.size())]; + if((chan = Mix_PlayChannel(i, sample->sound, s.flags&SND_LOOP ? -1 : 0)) < 0) + { + int lowest = -1; + loopv(sounds) if(sounds[i].chan >= 0 && (!(sounds[i].flags&SND_MAP) || s.flags&SND_MAP) && sounds[i].curvol < s.curvol && (lowest < 0 || sounds[i].curvol < sounds[lowest].curvol) && (nocull || (!(sounds[i].flags&SND_NOCULL) && sounds[i].pos.dist(camera1->o) > 0))) + lowest = i; + if(sounds.inrange(lowest)) + { + if(verbose >= 4) conoutf("culled channel %d (%d)", lowest, sounds[lowest].curvol); + removesound(lowest); + chan = Mix_PlayChannel(-1, sample->sound, s.flags&SND_LOOP ? -1 : 0); + } + } + if(chan >= 0) + { + while(chan >= sounds.length()) sounds.add(); + sound &t = sounds[chan]; + if(chan == s.chan) + { + i--; // repeat with new sound + return; + } + else + { + t.slot = &slot; + t.vol = s.vol; + t.maxrad = s.maxrad; + t.minrad = s.minrad; + t.material = s.material; + t.flags = s.flags; + t.millis = s.millis; + t.ends = s.ends; + t.slotnum = s.slotnum; + t.owner = s.owner; + t.pos = t.oldpos = s.pos; + t.curvol = s.curvol; + t.curpan = s.curpan; + t.chan = chan; + t.hook = s.hook; + loopvj(s.buffer) t.buffer.add(s.buffer[j]); + updatesound(chan); + } + } + } +} + void updatesounds() { updatemumble(); @@ -471,59 +485,13 @@ void updatesounds() updatesound(i); continue; } - vector &soundset = s.flags&SND_MAP ? mapsounds : gamesounds; - while(!s.buffer.empty() && (!soundset.inrange(s.buffer[0]) || soundset[s.buffer[0]].samples.empty() || !soundset[s.buffer[0]].vol)) s.buffer.remove(0); - if(!s.buffer.empty()) - { - int n = s.buffer[0], chan = -1; - Mix_HaltChannel(i); - s.buffer.remove(0); - bool nocull = s.flags&SND_NOCULL || s.pos.dist(camera1->o) <= 0; - soundslot *slot = &soundset[n]; - soundsample *sample = slot->samples[rnd(slot->samples.length())]; - if((chan = Mix_PlayChannel(i, sample->sound, s.flags&SND_LOOP ? -1 : 0)) < 0) - { - int lowest = -1; - loopv(sounds) if(sounds[i].chan >= 0 && (!(sounds[i].flags&SND_MAP) || s.flags&SND_MAP) && sounds[i].curvol < s.curvol && (lowest < 0 || sounds[i].curvol < sounds[lowest].curvol) && (nocull || (!(sounds[i].flags&SND_NOCULL) && sounds[i].pos.dist(camera1->o) > 0))) - lowest = i; - if(sounds.inrange(lowest)) - { - if(verbose >= 4) conoutf("culled channel %d (%d)", lowest, sounds[lowest].curvol); - removesound(lowest); - chan = Mix_PlayChannel(-1, sample->sound, s.flags&SND_LOOP ? -1 : 0); - } - } - if(chan >= 0) - { - while(chan >= sounds.length()) sounds.add(); - sound &t = sounds[chan]; - if(chan == s.chan) - { - i--; // repeat with new sound - continue; - } - else - { - t.slot = slot; - t.vol = s.vol; - t.maxrad = s.maxrad; - t.minrad = s.minrad; - t.material = s.material; - t.flags = s.flags; - t.millis = s.millis; - t.ends = s.ends; - t.slotnum = s.slotnum; - t.owner = s.owner; - t.pos = t.oldpos = s.pos; - t.curvol = s.curvol; - t.curpan = s.curpan; - t.chan = chan; - t.hook = s.hook; - loopvj(s.buffer) t.buffer.add(s.buffer[j]); - updatesound(chan); - } - } + + if ((s.flags & SND_MAP) != 0) { + updatesounds(mapsounds, s, i); + } else { + updatesounds(gamesounds, s, i); } + removesound(i); } if(music || Mix_PlayingMusic()) @@ -538,12 +506,9 @@ void updatesounds() } } -int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, int minrad, int *hook, int ends, int *oldhook) -{ - if(nosound || !mastervol || !soundvol || ((flags&SND_MAP || n >= S_GAMESPECIFIC) && client::waiting(true)) || (!d && !insideworld(pos))) return -1; - vector &soundset = flags&SND_MAP ? mapsounds : gamesounds; - - if(soundset.inrange(n)) +template +int playsound(T& soundset, int n, const vec& pos, physent* d, int flags, int vol, int maxrad, int minrad, int* hook, int ends, int* oldhook) { + if (soundset.contains(n)) { if(hook && issound(*hook) && flags&SND_BUFFER) { @@ -555,18 +520,22 @@ int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, if(oldhook && issound(*oldhook)) removesound(*oldhook); return -1; } - soundslot *slot = &soundset[n]; - if(!oldhook || !issound(*oldhook) || (n != sounds[*oldhook].slotnum && strcmp(slot->name, gamesounds[sounds[*oldhook].slotnum].name))) + + // TODO: fix following code to be able to use a const reference + auto& slot = soundset[n]; + + if(!oldhook || !issound(*oldhook) || (n != sounds[*oldhook].slotnum && strcmp(slot.name, gamesounds[sounds[*oldhook].slotnum].name) != 0)) oldhook = NULL; vec o = d ? game::camerapos(d) : pos; + int cvol = 0, cpan = 0, v = clamp(vol >= 0 ? vol : 255, flags&SND_CLAMPED ? 64 : 0, 255), - x = maxrad > 0 ? maxrad : (flags&SND_CLAMPED ? getworldsize() : (slot->maxrad > 0 ? slot->maxrad : soundmaxrad)), - y = minrad >= 0 ? minrad : (flags&SND_CLAMPED ? 32 : (slot->minrad >= 0 ? slot->minrad : soundminrad)), + x = maxrad > 0 ? maxrad : (flags&SND_CLAMPED ? getworldsize() : (slot.maxrad > 0 ? slot.maxrad : soundmaxrad)), + y = minrad >= 0 ? minrad : (flags&SND_CLAMPED ? 32 : (slot.minrad >= 0 ? slot.minrad : soundminrad)), mat = lookupmaterial(o); bool liquid = isliquid(lookupmaterial(camera1->o)&MATF_VOLUME); - calcvol(flags, v, slot->vol, x, y, o, &cvol, &cpan, liquid || isliquid(mat&MATF_VOLUME)); + calcvol(flags, v, slot.vol, x, y, o, &cvol, &cpan, liquid || isliquid(mat&MATF_VOLUME)); bool nocull = flags&SND_NOCULL || o.dist(camera1->o) <= 0; if(nocull || !soundcull || cvol > 0) @@ -576,12 +545,12 @@ int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, else { oldhook = NULL; - soundsample *sample = slot->samples[rnd(slot->samples.length())]; + soundsample *sample = slot.samples[rnd(slot.samples.size())]; if((chan = Mix_PlayChannel(-1, sample->sound, flags&SND_LOOP ? -1 : 0)) < 0) { int lowest = -1; loopv(sounds) if(sounds[i].chan >= 0 && (!(sounds[i].flags&SND_MAP) || flags&SND_MAP) && sounds[i].curvol < cvol && (lowest < 0 || sounds[i].curvol < sounds[lowest].curvol) && (nocull || (!(sounds[i].flags&SND_NOCULL) && sounds[i].pos.dist(camera1->o) > 0))) - lowest = i; + lowest = i; if(sounds.inrange(lowest)) { if(verbose >= 4) conoutf("culled channel %d (%d)", lowest, sounds[lowest].curvol); @@ -590,14 +559,16 @@ int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, } } } - if(chan >= 0) - { + + if(chan >= 0) { if(!oldhook && !(flags&SND_NODELAY)) Mix_Pause(chan); while(chan >= sounds.length()) sounds.add(); - sound &s = sounds[chan]; - s.slot = slot; + // TODO: fix following code to be able to use a const reference + sound& s = sounds[chan]; + + s.slot = &slot; s.vol = v; s.maxrad = x; s.minrad = y; @@ -611,27 +582,50 @@ int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, s.curvol = cvol; s.curpan = cpan; s.chan = chan; - if(hook) - { + + if(hook) { if(issound(*hook) && (!oldhook || *hook != *oldhook)) removesound(*hook); *hook = s.chan; s.hook = hook; + } else { + s.hook = NULL; } - else s.hook = NULL; + if(oldhook) *oldhook = -1; updatesound(chan); return chan; + } else if(verbose >= 2) { + conoutf("\frcannot play sound %d (%s): %s", n, slot.name, Mix_GetError()); + } + } + else if(verbose >= 4) + { + // only show this error message if it's a mapsound since we are intentionally + // not loading sounds for some weapons e.g. S_W_BOUNCE2 or S_W_EXTINGUISH + if (flags & SND_MAP) { + conoutf("culled sound %d (%d)", n, cvol); } - else if(verbose >= 2) - conoutf("\frcannot play sound %d (%s): %s", n, slot->name, Mix_GetError()); } - else if(verbose >= 4) conoutf("culled sound %d (%d)", n, cvol); } - else if(n > 0) conoutf("\frunregistered sound: %d", n); + else if(n > 0) + { + conoutf("\frunregistered sound: %d", n); + } if(oldhook && issound(*oldhook)) removesound(*oldhook); return -1; } +int playsound(int n, const vec &pos, physent *d, int flags, int vol, int maxrad, int minrad, int *hook, int ends, int *oldhook) +{ + if(nosound || n < 0 || !mastervol || !soundvol || ((flags&SND_MAP || n >= S_GAMESPECIFIC) && client::waiting(true)) || (!d && !insideworld(pos))) return -1; + + if ((flags & SND_MAP) != 0) { + return playsound(mapsounds, n, pos, d, flags, vol, maxrad, minrad, hook, ends, oldhook); + } else { + return playsound(gamesounds, n, pos, d, flags, vol, maxrad, minrad, hook, ends, oldhook); + } +} + void sound(int *n, int *vol, int *flags) { intret(playsound(*n, camera1->o, camera1, *flags >= 0 ? *flags : SND_FORCED, *vol ? *vol : -1)); @@ -667,9 +661,9 @@ void resetsound() DELETEA(musicfile); DELETEA(musicdonecmd); music = NULL; - gamesounds.setsize(0); - mapsounds.setsize(0); soundsamples.clear(); + gamesounds.clear(); + mapsounds.clear(); return; } rehash(true); diff --git a/src/engine/sound.h b/src/engine/sound.h index fb821e988..6897bb6eb 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -1,3 +1,12 @@ +#pragma once + +#include +#include +#include + +// forward declarations +struct physent; + enum { S_GUIPRESS = 0, S_GUIBACK, S_GUIACT, @@ -25,21 +34,14 @@ enum }; #ifndef STANDALONE +#include "geom.h" +#include "soundslot.h" +#include "soundsample.h" +#include "soundslot_collection.h" + #define SOUNDMINDIST 16.0f #define SOUNDMAXDIST 10000.f -struct soundsample; - -struct soundslot -{ - vector samples; - int vol, maxrad, minrad; - char *name; - - soundslot(); - ~soundslot(); -}; - struct sound { soundslot *slot; @@ -60,7 +62,23 @@ struct sound extern bool nosound; extern int mastervol, soundvol, musicvol; -extern vector gamesounds, mapsounds; + +/* + * For sounds, it makes sense to use a map type to manage the association between the int key (taken from enums) and a + * soundslot value. + * The only problem is that an unordered_map cannot simply be used, as ints are an unhashable type. Sure, this could + * be worked around on, but for now there is no need to optimize to get this sub-1% performance bonus. + * It is planned to put a proper interface in front of the soundslot collections that allows for accessing them easily + * and safely. That will also allow using better (read: more performant) data structures (e.g., an std::vector combined + * with support for the null object pattern, or an actual std::unordered_map with a custom hash function). + */ +extern soundslot_collection gamesounds; + +/* + * Map sounds are added every time a map is loaded. + */ +extern soundslot_collection mapsounds; + extern vector sounds; #define issound(c) (sounds.inrange(c) && sounds[c].valid()) @@ -72,12 +90,11 @@ extern bool playingmusic(bool check = true); extern void smartmusic(bool cond, bool init = false); extern void musicdone(bool docmd); extern void updatesounds(); -extern int addsound(const char *name, int vol, int maxrad, int minrad, int value, vector &soundset); +extern size_t add_game_sound(size_t sound_index, const std::string& name, int volume = 0, int max_radius = 0, int min_radius = 0, int num_slots = 1); extern void removesound(int c); extern void clearsound(); extern int playsound(int n, const vec &pos, physent *d = NULL, int flags = 0, int vol = -1, int maxrad = -1, int minrad = -1, int *hook = NULL, int ends = 0, int *oldhook = NULL); extern void removetrackedsounds(physent *d); - extern void initmumble(); extern void closemumble(); extern void updatemumble(); diff --git a/src/engine/soundsample.cpp b/src/engine/soundsample.cpp new file mode 100644 index 000000000..1dec7d413 --- /dev/null +++ b/src/engine/soundsample.cpp @@ -0,0 +1,18 @@ +// system headers +#include + +// local headers +#include "soundsample.h" +#include "cube.h" + +soundsample::soundsample() : sound(nullptr), name(nullptr) {} + +soundsample::~soundsample() { + DELETEA(name); +} + +void soundsample::cleanup() +{ + Mix_FreeChunk(sound); + sound = nullptr; +} diff --git a/src/engine/soundsample.h b/src/engine/soundsample.h new file mode 100644 index 000000000..04cbc22db --- /dev/null +++ b/src/engine/soundsample.h @@ -0,0 +1,14 @@ +#pragma once + +#include "SDL_mixer.h" + +struct soundsample +{ + Mix_Chunk *sound; + char *name; + + soundsample(); + ~soundsample(); + + void cleanup(); +}; diff --git a/src/engine/soundslot.cpp b/src/engine/soundslot.cpp new file mode 100644 index 000000000..8c0064707 --- /dev/null +++ b/src/engine/soundslot.cpp @@ -0,0 +1,30 @@ +// local headers +#include "soundslot.h" +#include "cube.h" + +soundslot::soundslot() : samples(), vol(255), maxrad(-1), minrad(-1), name(nullptr) {} + +soundslot::~soundslot() { + DELETEA(name); + name = nullptr; +} + +soundslot::soundslot(const soundslot& other) { + samples = other.samples; + vol = other.vol; + maxrad = other.maxrad; + minrad = other.minrad; + name = newstring(other.name); +} + +soundslot& soundslot::operator=(const soundslot& other) { + if (this != &other) { + samples = other.samples; + vol = other.vol; + maxrad = other.maxrad; + minrad = other.minrad; + name = newstring(other.name); + } + + return *this; +} diff --git a/src/engine/soundslot.h b/src/engine/soundslot.h new file mode 100644 index 000000000..5129de1d3 --- /dev/null +++ b/src/engine/soundslot.h @@ -0,0 +1,20 @@ +#pragma once + +// system headers +#include +#include + +// local headers +#include "soundsample.h" + +struct soundslot +{ + std::vector samples; + int vol, maxrad, minrad; + char *name; + + soundslot(); + soundslot(const soundslot& other); + soundslot& operator=(const soundslot& other); + ~soundslot(); +}; diff --git a/src/engine/soundslot_collection.cpp b/src/engine/soundslot_collection.cpp new file mode 100644 index 000000000..bfcdd3b08 --- /dev/null +++ b/src/engine/soundslot_collection.cpp @@ -0,0 +1,79 @@ +/** + * All fully specified implementations of methods declared in soundslot_collection need to go into this file. + */ + +#include "soundslot_collection.h" + +template<> +ssize_t soundslot_collection::find_existing_soundslot_(const soundslot& slot) { + // classic linear search + for (size_t i = 0; i < soundslots_.size(); ++i) { + const auto& existing_slot = soundslots_[i]; + + if (check_soundslots_equal_(slot, existing_slot)) { + return i; + } + } + + return -1; +} + +template<> +ssize_t soundslot_collection::find_existing_soundslot_(const soundslot& slot) { + // classic linear search through the map's values + for (const auto& pair : soundslots_) { + const auto i = pair.first; + const auto& existing_slot = pair.second; + + if (check_soundslots_equal_(slot, existing_slot)) { + return i; + } + } + + return -1; +} + +template<> +size_t soundslot_collection::insert_into_soundslots_(ssize_t index, const soundslot &slot) { + if (index >= 0) { + throw std::logic_error{"Specific indices not supported for vector type collections"}; + } + + soundslots_.emplace_back(slot); + return soundslots_.size() - 1; +} + +template<> +size_t soundslot_collection::insert_into_soundslots_(ssize_t index, const soundslot &slot) { + if (index < 0) { + throw std::logic_error{"Must specify index for map type collections"}; + } + + soundslots_[index] = slot; + return index; +} + +template<> +size_t soundslot_collection::append(const std::string& name, int volume, int max_radius, int min_radius, int num_slots) { + return insert_or_append_(name, volume, max_radius, min_radius, num_slots, -1); +} + +template<> +size_t soundslot_collection::insert(size_t index, const std::string& name, int volume, int max_radius, int min_radius, int num_slots) { + return insert_or_append_(name, volume, max_radius, min_radius, num_slots, index); +} + +template<> +bool soundslot_collection::contains(size_t i) const { + return soundslots_.find(i) != soundslots_.end(); +} + +template<> +bool soundslot_collection::contains(size_t i) const { + return i < soundslots_.size(); +} + +template<> +size_t soundslot_collection::size() const { + return soundslots_.size(); +} diff --git a/src/engine/soundslot_collection.h b/src/engine/soundslot_collection.h new file mode 100644 index 000000000..08a3de9b9 --- /dev/null +++ b/src/engine/soundslot_collection.h @@ -0,0 +1,260 @@ +#pragma once + +// system/STL headers +#include +#include + +// local headers +#include "SDL.h" +#include "soundsample.h" +#include "soundslot.h" +#include "tools.h" + +// forward declarations +extern hashnameset soundsamples; + +// types used as internal containers in soundslot collections +typedef std::map soundslot_collection_map_t; +// TODO: use std::vector +typedef vector soundslot_collection_vector_t; + +// forward declarations +extern Mix_Chunk* loadwav(const char *name); + +/** + * soundslots collection wrapper class. Follows "template method" pattern. + * While game sounds are best managed in a map, map sounds need to be managed in a contiguous collection (no pun intended). + * @tparam T collection type + */ +template +class soundslot_collection { +private: + // internal collection of soundslots + T soundslots_; + + /** + * Compare two soundslots for equality. + */ + static bool check_soundslots_equal_(const soundslot& first, const soundslot& second); + + /** + * Find existing soundslot in collection. Implemented as (linear) search on all values in collection. + * @param slot slot to compare against + * @return -1 if none is found, index otherwise + */ + ssize_t find_existing_soundslot_(const soundslot& slot); + + /** + * Register a sound in the game (map sounds variant). + * @param name path to the sound file (relative to data directory) + * @param volume volume sound is played with (see soundslot) + * @param max_radius maximum radius sound is played in (see soundslot) + * @param min_radius minimum radius sound is played in (see soundslot) + * @param num_slots amount of slots to load for sound "name" + * @param sound_index index of sound in the sounds enum (must be -1 for map sounds, and >= 0 for game sounds) + * @return index of registered sound in internal storage (also if the sound was not added because it existed already) + */ + size_t insert_or_append_(const std::string& name, int volume, int max_radius, int min_radius, int num_slots, ssize_t index); + + /** + * Type-specific insertion method. + * @param index -1 for vector types, actual index for map types + * @param slot soundslot to insert/append + */ + size_t insert_into_soundslots_(ssize_t index, const soundslot& slot); + +public: + /** + * Default constructor. + */ + soundslot_collection(); + + /** + * Register a sound in the game (mapsounds/vector variant). + * @param name path to the sound file (relative to data directory) + * @param volume volume sound is played with (see soundslot) + * @param max_radius maximum radius sound is played in (see soundslot) + * @param min_radius minimum radius sound is played in (see soundslot) + * @param num_slots amount of slots to load for sound "name" + * @param sound_index index of sound in the sounds enum (must be -1 for map sounds, and >= 0 for game sounds) + * @return index of registered sound in internal storage (also if the sound was not added because it existed already) + */ + size_t append(const std::string& name, int volume, int max_radius, int min_radius, int num_slots); + + /** + * Register a sound in the game (gamesounds/ variant). + * @param name path to the sound file (relative to data directory) + * @param volume volume sound is played with (see soundslot) + * @param max_radius maximum radius sound is played in (see soundslot) + * @param min_radius minimum radius sound is played in (see soundslot) + * @param num_slots amount of slots to load for sound "name" + * @param sound_index index of sound in the sounds enum (must be -1 for map sounds, and >= 0 for game sounds) + * @return index of registered sound in internal storage (also if the sound was not added because it existed already) + */ + size_t insert(size_t index, const std::string& name, int volume, int max_radius, int min_radius, int num_slots); + + /** + * Clear internal collection. + */ + void clear(); + + /** + * Query entry for index i. + * @param i index + * @return soundslot entry + */ + const soundslot& operator[](size_t i) const; + + /** + * Query entry for index i. + * @param i index + * @return soundslot entry + */ + soundslot& operator[](size_t i); + + /** + * Checks whether soundslot with index i is contained in internal collection. + * @param i index + * @return whether i is contained in internal collection + */ + bool contains(size_t i) const; + + /** + * Get size of internal collection. Available only for vector implementation. + * @return size of internal collection + */ + size_t size() const; +}; + +template +bool soundslot_collection::check_soundslots_equal_(const soundslot& first, const soundslot& second) { + return first.vol == second.vol && + first.maxrad == second.maxrad && + first.minrad == second.minrad && + strcmp(first.name, second.name) == 0; +} + +template +soundslot_collection::soundslot_collection() : soundslots_() { + static_assert( + std::is_same::value || std::is_same::value, + "unsupported type for soundslot collection" + ); +} + +template +size_t soundslot_collection::insert_or_append_(const std::string& name, int volume, int max_radius, int min_radius, int num_slots, ssize_t index) { + // sanitization: bound value and use max when a negative volume is passed + if (volume <= 0 || volume >= 255) { + volume = 255; + } + + // more sanitization: bound values to -1 on the negative side + min_radius = std::max(-1, min_radius); + max_radius = std::max(-1, max_radius); + + // there should be at least one slot for every sound + num_slots = std::max(1, num_slots); + + // prepare new soundslot to be added + // also used to compare against existing ones (see below) + soundslot new_slot{}; + new_slot.name = newstring(name.c_str()); + new_slot.vol = volume; + new_slot.maxrad = max_radius; + new_slot.minrad = min_radius; + + // TODO: validate whether this check is needed at all; all slots should be filled once the sound has been registered + // check if soundslot has been loaded already to avoid loading samples more than once + if (num_slots == 1) { + const auto existing_slot_index = find_existing_soundslot_(new_slot); + + // if an existing soundslot is found, it is copied into the new location + if (existing_slot_index >= 0) { + return insert_into_soundslots_(index, (*this)[existing_slot_index]); + } + } + + // just used for weapons that don't have certain sound effects, e.g. some weapons don't have a zoom sound + // so we don't create an offset inside the vector, we have to fill those places with some + // placeholders + if (name == "") { + throw std::invalid_argument{"cubescript relict; should not be used any more"}; + } + + // load the actual samples here + int loaded_samples = 0; + + // naming scheme is: shell.ogg, shell2.ogg, shell3.ogg, shell4.ogg + // the values would be name: "shell" and value: 4 + // so the first element has to always be loaded, that's why do...while + // after that just go on counting up 'til we reach the value and load all sounds we find on our way + for (ssize_t i = 1; i <= num_slots; ++i) { + std::string sample_name = name; + + // if the value is 1 (the first entry) just use the normal name since there is no such thing as shell1.ogg, + // but rather shell.ogg and then it continues with shell2.ogg (that's why we start counting from 1) + if (i > 1) { + sample_name += std::to_string(i); + } + + soundsample* sample = nullptr; + + if ((sample = soundsamples.access(sample_name.c_str())) == nullptr) { + char* s_name = newstring(sample_name.c_str()); + + sample = &soundsamples[s_name]; + sample->name = s_name; + sample->sound = nullptr; + } + + // if the sample isn't already loaded, load it + if (!sample->sound) { + for (const auto& dir : {"", "sounds/"}) { + for (const auto& ext : {"", ".wav", ".ogg"}) { + std::string relative_path = dir + sample_name + ext; + sample->sound = loadwav(relative_path.c_str()); + + // if we can load the sample, set found to true and the exit the loop + if (sample->sound != nullptr) { + break; + } + } + + // if we found the entry previously, quit the loop + if (sample->sound != nullptr) { + break; + } + } + } + + // check if the sample is set now + if (sample->sound != nullptr) { + new_slot.samples.emplace_back(sample); + loaded_samples++; + } + } + + if (loaded_samples < num_slots) { + std::string message = "failed to load " + std::to_string(num_slots - loaded_samples) + " samples for sound " + name; + throw std::invalid_argument(message.c_str()); + } + + printf("loaded %d samples for sound %d: %s\n", num_slots, index, new_slot.name); + return insert_into_soundslots_(index, new_slot); +} + +template +void soundslot_collection::clear() { + soundslots_.clear(); +} + +template +const soundslot& soundslot_collection::operator[](size_t i) const { + return this->soundslots_[i]; +} + +template +soundslot& soundslot_collection::operator[](size_t i) { + return this->soundslots_[i]; +} diff --git a/src/engine/worldio.cpp b/src/engine/worldio.cpp index b89a93af9..600e2e1bf 100644 --- a/src/engine/worldio.cpp +++ b/src/engine/worldio.cpp @@ -909,7 +909,7 @@ void save_config(char *mname) loopv(mapsounds) { - progress(i/float(mapsounds.length()), "saving mapsound slots..."); + progress(i/float(mapsounds.size()), "saving mapsound slots..."); h->printf("mapsound %s", escapestring(mapsounds[i].name)); if((mapsounds[i].vol > 0 && mapsounds[i].vol < 255) || mapsounds[i].maxrad > 0 || mapsounds[i].minrad >= 0) h->printf(" %d", mapsounds[i].vol); @@ -917,8 +917,8 @@ void save_config(char *mname) if(mapsounds[i].minrad >= 0) h->printf(" %d", mapsounds[i].minrad); h->printf("\n"); } - if(mapsounds.length()) h->printf("\n"); - if(verbose) conoutf("saved %d mapsound slots", mapsounds.length()); + if(mapsounds.size()) h->printf("\n"); + if(verbose) conoutf("saved %d mapsound slots", mapsounds.size()); delete h; if(verbose) conoutf("saved config %s", fname); diff --git a/src/game/entities.cpp b/src/game/entities.cpp index d08285993..f20cf436d 100644 --- a/src/game/entities.cpp +++ b/src/game/entities.cpp @@ -300,9 +300,9 @@ namespace entities } case MAPSOUND: { - if(mapsounds.inrange(attr[0])) + if(mapsounds.contains(attr[0])) { - int samples = mapsounds[attr[0]].samples.length(); + int samples = mapsounds[attr[0]].samples.size(); defformatstring(ds, "%s (%d %s)", mapsounds[attr[0]].name, samples, samples == 1 ? "sample" : "samples"); addentinfo(ds); } @@ -1164,7 +1164,7 @@ namespace entities f.lastemit = e.lastemit; if(e.type == TRIGGER) f.setspawned(TRIGSTATE(e.spawned(), e.attrs[4])); else if(local) commit = true; - if(mapsounds.inrange(f.attrs[0]) && !issound(f.schan)) + if(mapsounds.contains(f.attrs[0]) && !issound(f.schan)) { int flags = SND_MAP; loopk(SND_LAST) if(f.attrs[4]&(1< #include +#include +#include "enet/enet.h" +#include "zlib.h" #ifdef NULL #undef NULL @@ -580,12 +583,12 @@ static inline bool htcmp(int x, int y) } #ifndef STANDALONE -static inline uint hthash(GLuint key) +static inline uint hthash(uint key) { return key; } -static inline bool htcmp(GLuint x, GLuint y) +static inline bool htcmp(uint x, uint y) { return x==y; }