Files
draugnorak/src/creature_audio.nvgt
T

143 lines
5.8 KiB
Plaintext

// Unified creature/enemy audio system
// Ensures consistent panning and distance behavior for all animated entities
//
// *** IMPORTANT: See src/creature_template.nvgt for complete step-by-step guide ***
// The template file has code examples, a checklist, and enforces consistency.
//
// QUICK USAGE GUIDE:
// This system provides standardized audio functions for all creatures (zombies, bandits, animals).
// Using these functions ensures all creatures sound consistent to the player.
//
// When adding new creatures (goblins, sheep, cattle, horses, etc):
// 1. Define creature-specific constants in constants.nvgt:
// const float SHEEP_SOUND_VOLUME_STEP = 3.0;
// const int SHEEP_FOOTSTEP_MAX_DISTANCE = 5;
//
// 2. Use these functions in your creature update code:
// - play_creature_voice() for periodic sounds (bleats, moos, neighs) - returns handle, store it!
// - play_creature_footstep() when creature moves
// - play_creature_attack_sound() when creature attacks player/barricade
// - play_creature_death_sounds() when creature dies (adds optional *_dies.ogg)
// - play_creature_hit_sound() when player damages creature
//
// 3. IMPORTANT: When creature dies, stop its sound before playing death sound:
// if (creature.sound_handle != -1) {
// p.destroy_sound(creature.sound_handle);
// creature.sound_handle = -1;
// }
// play_creature_death_sounds("sounds/enemies/enemy_falls.ogg", creature.voice_sound, x, pos, volume_step);
//
// 4. All sounds automatically use consistent panning/volume falloff
//
// Example for sheep:
// sheep.sound_handle = play_creature_voice("sounds/animals/sheep_bleat.ogg", x, sheep.position, SHEEP_SOUND_VOLUME_STEP);
// play_creature_footstep(x, sheep.position, BASE_END, GRASS_END, SHEEP_FOOTSTEP_MAX_DISTANCE, SHEEP_SOUND_VOLUME_STEP);
//
// Death handling example:
// if (sheep.sound_handle != -1) {
// p.destroy_sound(sheep.sound_handle);
// sheep.sound_handle = -1;
// }
// play_creature_death_sound("sounds/animals/sheep_death.ogg", x, sheep.position, SHEEP_SOUND_VOLUME_STEP);
// Default audio parameters for creatures
const float CREATURE_DEFAULT_VOLUME_STEP = 3.0;
const int CREATURE_DEFAULT_FOOTSTEP_DISTANCE = 6;
// Plays a creature's voice/alert sound with consistent positioning
// Returns the sound handle for tracking
int play_creature_voice(string sound_file, int listener_x, int creature_x,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
return play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
// Plays a creature's footstep sound with consistent positioning
// Only plays if within max_distance to avoid cluttering the soundscape
void play_creature_footstep(int listener_x, int creature_x, int base_end, int grass_end,
int max_distance = CREATURE_DEFAULT_FOOTSTEP_DISTANCE,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
int distance = creature_x - listener_x;
if (distance < 0) {
distance = -distance;
}
if (distance > max_distance) {
return;
}
play_positional_footstep(listener_x, creature_x, base_end, grass_end, max_distance, volume_step);
}
// Plays a creature attack sound (hitting player, hitting barricade, etc.)
void play_creature_attack_sound(string sound_file, int listener_x, int creature_x,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
// Plays a creature death/fall sound
void play_creature_death_sound(string sound_file, int listener_x, int creature_x,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
string get_creature_death_sound_from_alert(string alert_sound) {
if (alert_sound == "") {
return "";
}
string[] parts = alert_sound.split("/");
string filename = alert_sound;
if (parts.length() > 0) {
filename = parts[parts.length() - 1];
}
int dot_index = filename.find(".");
if (dot_index > 0) {
filename = filename.substr(0, dot_index);
}
if (filename == "bandit3" || filename == "bandit4") {
string female_death = "sounds/enemies/bandit_female_dies.ogg";
if (audio_asset_exists(female_death)) {
return female_death;
}
}
// Strip trailing digits (bandit1 -> bandit, goblin2 -> goblin)
while (filename.length() > 0) {
string last_char = filename.substr(filename.length() - 1, 1);
if (last_char >= "0" && last_char <= "9") {
filename = filename.substr(0, filename.length() - 1);
} else {
break;
}
}
if (filename == "") {
return "";
}
string death_sound = "sounds/enemies/" + filename + "_dies.ogg";
if (!audio_asset_exists(death_sound)) {
return "";
}
return death_sound;
}
void play_creature_death_sounds(string default_sound, string alert_sound, int listener_x, int creature_x,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
play_creature_death_sound(default_sound, listener_x, creature_x, volume_step);
string death_sound = get_creature_death_sound_from_alert(alert_sound);
if (death_sound != "" && death_sound != default_sound) {
play_creature_death_sound(death_sound, listener_x, creature_x, volume_step);
}
}
// Plays a creature hit/damage sound (when player damages the creature)
void play_creature_hit_sound(string sound_file, int listener_x, int creature_x,
float volume_step = CREATURE_DEFAULT_VOLUME_STEP) {
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}