void sfx::do_projectile_hit( const Creature &target ) { const int heard_volume = sfx::get_heard_volume( target.pos() ); const int angle = get_heard_angle( target.pos() ); if( target.is_monster() ) { const monster &mon = dynamic_cast<const monster &>( target ); static std::set<material_id> const fleshy = { material_id( "flesh" ), material_id( "hflesh" ), material_id( "iflesh" ), material_id( "veggy" ), material_id( "bone" ), }; const bool is_fleshy = std::any_of( fleshy.begin(), fleshy.end(), [&mon]( const material_id &m ) { return mon.made_of( m ); } ); if( is_fleshy ) { play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); return; } else if( mon.made_of( material_id( "stone" ) ) ) { play_variant_sound( "bullet_hit", "hit_wall", heard_volume, angle, 0.8, 1.2 ); return; } else if( mon.made_of( material_id( "steel" ) ) ) { play_variant_sound( "bullet_hit", "hit_metal", heard_volume, angle, 0.8, 1.2 ); return; } else { play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); return; } } play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); }
void sfx::do_projectile_hit( const Creature &target ) { const int heard_volume = sfx::get_heard_volume( target.pos() ); const int angle = get_heard_angle( target.pos() ); if( target.is_monster() ) { const monster &mon = dynamic_cast<const monster &>( target ); const auto material = mon.get_material(); static std::set<mat_type> const fleshy = { mat_type( "flesh" ), mat_type( "hflesh" ), mat_type( "iflesh" ), mat_type( "veggy" ), mat_type( "bone" ), mat_type( "protoplasmic" ), }; if( fleshy.count( material ) > 0 || mon.has_flag( MF_VERMIN ) ) { play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); return; } else if( material == "stone" ) { play_variant_sound( "bullet_hit", "hit_wall", heard_volume, angle, 0.8, 1.2 ); return; } else if( material == "steel" ) { play_variant_sound( "bullet_hit", "hit_metal", heard_volume, angle, 0.8, 1.2 ); return; } else { play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); return; } } play_variant_sound( "bullet_hit", "hit_flesh", heard_volume, angle, 0.8, 1.2 ); }
void sfx::do_player_death_hurt( const player &target, bool death ) { int heard_volume = get_heard_volume( target.pos() ); const bool male = target.male; if( !male && !death ) { play_variant_sound( "deal_damage", "hurt_f", heard_volume ); } else if( male && !death ) { play_variant_sound( "deal_damage", "hurt_m", heard_volume ); } else if( !male && death ) { play_variant_sound( "clean_up_at_end", "death_f", heard_volume ); } else if( male && death ) { play_variant_sound( "clean_up_at_end", "death_m", heard_volume ); } }
void sfx::do_hearing_loss( int turns ) { if( deafness_turns == 0 ) { deafness_turns = turns; g_sfx_volume_multiplier = .1; fade_audio_group( 1, 50 ); fade_audio_group( 2, 50 ); play_variant_sound( "environment", "deafness_shock", 100 ); play_variant_sound( "environment", "deafness_tone_start", 100 ); if( deafness_turns <= 35 ) { play_ambient_variant_sound( "environment", "deafness_tone_light", 90, 10, 100 ); } else if( deafness_turns <= 90 ) { play_ambient_variant_sound( "environment", "deafness_tone_medium", 90, 10, 100 ); } else if( deafness_turns >= 91 ) { play_ambient_variant_sound( "environment", "deafness_tone_heavy", 90, 10, 100 ); } } else { deafness_turns += turns; } }
void sfx::do_obstacle() { int heard_volume = sfx::get_heard_volume( g->u.pos() ); const auto terrain = g->m.ter( g->u.pos() ).id(); static std::set<ter_str_id> const water = { ter_str_id( "t_water_sh" ), ter_str_id( "t_water_dp" ), ter_str_id( "t_swater_sh" ), ter_str_id( "t_swater_dp" ), ter_str_id( "t_water_pool" ), ter_str_id( "t_sewage" ), }; if( water.count( terrain ) > 0 ) { return; } else { play_variant_sound( "plmove", "clear_obstacle", heard_volume, 0, 0.8, 1.2 ); } }
// Operator overload required for thread API. void sfx::sound_thread::operator()() const { // This is function is run in a separate thread. One must be careful and not access game data // that might change (e.g. g->u.weapon, the character could switch weapons while this thread // runs). std::this_thread::sleep_for( std::chrono::milliseconds( rng( 1, 2 ) ) ); std::string variant_used; static const skill_id skill_bashing( "bashing" ); static const skill_id skill_cutting( "cutting" ); static const skill_id skill_stabbing( "stabbing" ); if( weapon_skill == skill_bashing && weapon_volume <= 8 ) { variant_used = "small_bash"; play_variant_sound( "melee_swing", "small_bash", vol_src, ang_src, 0.8, 1.2 ); } else if( weapon_skill == skill_bashing && weapon_volume >= 9 ) { variant_used = "big_bash"; play_variant_sound( "melee_swing", "big_bash", vol_src, ang_src, 0.8, 1.2 ); } else if( ( weapon_skill == skill_cutting || weapon_skill == skill_stabbing ) && weapon_volume <= 6 ) { variant_used = "small_cutting"; play_variant_sound( "melee_swing", "small_cutting", vol_src, ang_src, 0.8, 1.2 ); } else if( ( weapon_skill == skill_cutting || weapon_skill == skill_stabbing ) && weapon_volume >= 7 ) { variant_used = "big_cutting"; play_variant_sound( "melee_swing", "big_cutting", vol_src, ang_src, 0.8, 1.2 ); } else { variant_used = "default"; play_variant_sound( "melee_swing", "default", vol_src, ang_src, 0.8, 1.2 ); } if( hit ) { if( targ_mon ) { if( material == "steel" ) { std::this_thread::sleep_for( std::chrono::milliseconds( rng( weapon_volume * 12, weapon_volume * 16 ) ) ); play_variant_sound( "melee_hit_metal", variant_used, vol_targ, ang_targ, 0.8, 1.2 ); } else { std::this_thread::sleep_for( std::chrono::milliseconds( rng( weapon_volume * 12, weapon_volume * 16 ) ) ); play_variant_sound( "melee_hit_flesh", variant_used, vol_targ, ang_targ, 0.8, 1.2 ); } } else { std::this_thread::sleep_for( std::chrono::milliseconds( rng( weapon_volume * 9, weapon_volume * 12 ) ) ); play_variant_sound( "melee_hit_flesh", variant_used, vol_targ, ang_targ, 0.8, 1.2 ); } } }
// firing is the item that is fired. It may be the wielded gun, but it can also be an attached // gunmod. p is the character that is firing, this may be a pseudo-character (used by monattack/ // vehicle turrets) or a NPC. void sfx::generate_gun_sound( const player &p, const item &firing ) { end_sfx_timestamp = std::chrono::high_resolution_clock::now(); sfx_time = end_sfx_timestamp - start_sfx_timestamp; if( std::chrono::duration_cast<std::chrono::milliseconds> ( sfx_time ).count() < 80 ) { return; } const tripoint source = p.pos(); int heard_volume = get_heard_volume( source ); if( heard_volume <= 30 ) { heard_volume = 30; } itype_id weapon_id = firing.typeId(); int angle; int distance; std::string selected_sound; // this does not mean p == g->u (it could be a vehicle turret) if( g->u.pos() == source ) { angle = 0; distance = 0; selected_sound = "fire_gun"; const auto mods = firing.gunmods(); if( std::any_of( mods.begin(), mods.end(), []( const item *e ) { return e->type->gunmod->loudness < 0; } ) ) { weapon_id = "weapon_fire_suppressed"; } } else { angle = get_heard_angle( source ); distance = rl_dist( g->u.pos(), source ); if( distance <= 17 ) { selected_sound = "fire_gun"; } else { selected_sound = "fire_gun_distant"; } } play_variant_sound( selected_sound, weapon_id, heard_volume, angle, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); }
void sfx::do_footstep() { end_sfx_timestamp = std::chrono::high_resolution_clock::now(); sfx_time = end_sfx_timestamp - start_sfx_timestamp; if( std::chrono::duration_cast<std::chrono::milliseconds> ( sfx_time ).count() > 400 ) { int heard_volume = sfx::get_heard_volume( g->u.pos() ); const auto terrain = g->m.ter( g->u.pos() ).id(); static std::set<ter_str_id> const grass = { ter_str_id( "t_grass" ), ter_str_id( "t_shrub" ), ter_str_id( "t_underbrush" ), }; static std::set<ter_str_id> const dirt = { ter_str_id( "t_dirt" ), ter_str_id( "t_sand" ), ter_str_id( "t_dirtfloor" ), ter_str_id( "t_palisade_gate_o" ), ter_str_id( "t_sandbox" ), }; static std::set<ter_str_id> const metal = { ter_str_id( "t_ov_smreb_cage" ), ter_str_id( "t_metal_floor" ), ter_str_id( "t_grate" ), ter_str_id( "t_bridge" ), ter_str_id( "t_elevator" ), ter_str_id( "t_guardrail_bg_dp" ), }; static std::set<ter_str_id> const water = { ter_str_id( "t_water_sh" ), ter_str_id( "t_water_dp" ), ter_str_id( "t_swater_sh" ), ter_str_id( "t_swater_dp" ), ter_str_id( "t_water_pool" ), ter_str_id( "t_sewage" ), }; static std::set<ter_str_id> const chain_fence = { ter_str_id( "t_chainfence_h" ), ter_str_id( "t_chainfence_v" ), }; if( !g->u.wearing_something_on( bp_foot_l ) ) { play_variant_sound( "plmove", "walk_barefoot", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else if( grass.count( terrain ) > 0 ) { play_variant_sound( "plmove", "walk_grass", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else if( dirt.count( terrain ) > 0 ) { play_variant_sound( "plmove", "walk_dirt", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else if( metal.count( terrain ) > 0 ) { play_variant_sound( "plmove", "walk_metal", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else if( water.count( terrain ) > 0 ) { play_variant_sound( "plmove", "walk_water", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else if( chain_fence.count( terrain ) > 0 ) { play_variant_sound( "plmove", "clear_obstacle", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } else { play_variant_sound( "plmove", "walk_tarmac", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; } } }