310 lines
8.5 KiB
Plaintext
310 lines
8.5 KiB
Plaintext
|
local SHELL_TYPE_PISTOL = "pistol"
|
||
|
local SHELL_TYPE_RIFLE = "rifle"
|
||
|
local SHELL_TYPE_SHOTGUN = "shotgun"
|
||
|
|
||
|
local SHELL_SOUND_TYPE_GENERIC = "generic"
|
||
|
local SHELL_SOUND_TYPE_LEAVES = "leaves"
|
||
|
local SHELL_SOUND_TYPE_WATER = "water"
|
||
|
local SHELL_SOUND_TYPE_METAL = "metal"
|
||
|
local SHELL_SOUND_TYPE_WOOD = "wood"
|
||
|
|
||
|
local SHELL_TYPE = {
|
||
|
["ammo_9x21"] = SHELL_TYPE_PISTOL,
|
||
|
["ammo_9x18"] = SHELL_TYPE_PISTOL,
|
||
|
["ammo_9x19"] = SHELL_TYPE_PISTOL,
|
||
|
["ammo_7.62x25"] = SHELL_TYPE_PISTOL,
|
||
|
["ammo_11.43x23"] = SHELL_TYPE_PISTOL,
|
||
|
["ammo_5.7x28"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_5.45x39"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_5.56x45"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_9x39"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_7.62x39"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_7.92x33"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_7.62x51"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_pkm_100"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_7.62x54"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_12.7x55"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_magnum_300"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_357"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_50"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_338"] = SHELL_TYPE_RIFLE,
|
||
|
["ammo_23x75"] = SHELL_TYPE_SHOTGUN,
|
||
|
["ammo_20x70"] = SHELL_TYPE_SHOTGUN,
|
||
|
["ammo_23"] = SHELL_TYPE_SHOTGUN,
|
||
|
["ammo_12x70"] = SHELL_TYPE_SHOTGUN,
|
||
|
["ammo_12x76"] = SHELL_TYPE_SHOTGUN
|
||
|
}
|
||
|
|
||
|
local SHELL_SOUND_TYPE = {
|
||
|
["water"] = SHELL_SOUND_TYPE_WATER,
|
||
|
["bush"] = SHELL_SOUND_TYPE_LEAVES,
|
||
|
["grass"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["metal"] = SHELL_SOUND_TYPE_METAL,
|
||
|
["metal_plate"] = SHELL_SOUND_TYPE_METAL,
|
||
|
["metal_pipe"] = SHELL_SOUND_TYPE_METAL,
|
||
|
["setka_rabica"] = SHELL_SOUND_TYPE_METAL,
|
||
|
["tin"] = SHELL_SOUND_TYPE_METAL,
|
||
|
["wood"] = SHELL_SOUND_TYPE_WOOD,
|
||
|
["wooden_board"] = SHELL_SOUND_TYPE_WOOD,
|
||
|
["asphalt"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["shifer"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["tile"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["flooring_tile"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["concrete"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["earth"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["dirt"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["gravel"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["sand"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["fake"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["fake_ladders"] = SHELL_SOUND_TYPE_GENERIC,
|
||
|
["actor"] = SHELL_SOUND_TYPE_GENERIC
|
||
|
}
|
||
|
|
||
|
local SHELL_SOUND_TIME = {
|
||
|
["mp412"] = 1400,
|
||
|
["mp133"] = 800,
|
||
|
["ks23"] = 800,
|
||
|
["ks23_kaban"] = 800,
|
||
|
["ks23_kaban_kab_up"] = 800,
|
||
|
["ks23_23_up"] = 800,
|
||
|
["ithacam37"] = 800,
|
||
|
["ithacam37_trench"] = 800,
|
||
|
["ithacam37_mag"] = 800,
|
||
|
["ithacam37_sawnoff"] = 800,
|
||
|
["ithacam37_stakeout"] = 800,
|
||
|
["wincheaster1300"] = 800,
|
||
|
["toz106"] = 1400,
|
||
|
["toz106_m1"] = 1400,
|
||
|
["mossberg590"] = 800,
|
||
|
["remington870"] = 800,
|
||
|
["dvl10"] = 1400,
|
||
|
["dvl10_m1"] = 1400,
|
||
|
["k98"] = 1400,
|
||
|
["k98_mod"] = 1400,
|
||
|
["k98_mod_silen98"] = 1400,
|
||
|
["l96a1"] = 1400,
|
||
|
["l96a1m"] = 1400,
|
||
|
["remington700"] = 1400,
|
||
|
["remington700_archangel"] = 1400,
|
||
|
["remington700_lapua700"] = 1400,
|
||
|
["remington700_magpul_pro"] = 1400,
|
||
|
["remington700_mod_x_gen3"] = 1400,
|
||
|
["sv98"] = 1400,
|
||
|
["sv98_custom"] = 1400,
|
||
|
["vssk"] = 1400,
|
||
|
["mosin"] = 1400
|
||
|
}
|
||
|
|
||
|
local SHELL_SOUND_GAP_TIME = {
|
||
|
["toz34"] = 600,
|
||
|
["toz34_bull"] = 600,
|
||
|
["toz34_custom"] = 600,
|
||
|
["toz34_decor"] = 600,
|
||
|
["toz34_mark4"] = 600,
|
||
|
["toz34_obrez"] = 500,
|
||
|
["toz34_obrez_custom"] = 500,
|
||
|
["toz34_obrez_decor"] = 500,
|
||
|
["bm16"] = 200,
|
||
|
["bm16_alt"] = 200,
|
||
|
["bm16_full"] = 200,
|
||
|
["bm16_full_alt"] = 200
|
||
|
}
|
||
|
|
||
|
local WEAPON_REVOLVER = {
|
||
|
["mp412"] = true
|
||
|
}
|
||
|
|
||
|
local WEAPON_DOUBLE_BARREL = {
|
||
|
["toz34"] = true,
|
||
|
["toz34_bull"] = true,
|
||
|
["toz34_custom"] = true,
|
||
|
["toz34_decor"] = true,
|
||
|
["toz34_mark4"] = true,
|
||
|
["toz34_obrez"] = true,
|
||
|
["toz34_obrez_custom"] = true,
|
||
|
["toz34_obrez_decor"] = true,
|
||
|
["bm16"] = true,
|
||
|
["bm16_alt"] = true,
|
||
|
["bm16_full"] = true,
|
||
|
["bm16_full_alt"] = true
|
||
|
}
|
||
|
|
||
|
local WEAPON_BLACKLIST = {
|
||
|
["gauss"] = true,
|
||
|
["gauss_quest"] = true,
|
||
|
["m79"] = true,
|
||
|
["rg-6"] = true,
|
||
|
["rpg7"] = true
|
||
|
}
|
||
|
|
||
|
local WEAPON_SECTION_POSTFIXES = {
|
||
|
"_1p29",
|
||
|
"_ac10632",
|
||
|
"_ac11090",
|
||
|
"_acog",
|
||
|
"_eot",
|
||
|
"_kobra",
|
||
|
"_ps01",
|
||
|
"_pso1m21",
|
||
|
"_g43",
|
||
|
"_galil",
|
||
|
"_po4x34",
|
||
|
"_pu",
|
||
|
"_23",
|
||
|
"_zf4",
|
||
|
"_silencer",
|
||
|
"_scope",
|
||
|
"_scope_pso1m21",
|
||
|
"_scope_g43",
|
||
|
"_scope_galil",
|
||
|
"_scope_po4x34",
|
||
|
"_scope_pu",
|
||
|
"_scope_zf4",
|
||
|
"_addon_scope_pso1m21",
|
||
|
"_addon_scope_g43",
|
||
|
"_addon_scope_galil",
|
||
|
"_addon_scope_po4x34",
|
||
|
"_addon_scope_pu",
|
||
|
"_addon_scope_zf4",
|
||
|
"_addon_silencer"
|
||
|
}
|
||
|
|
||
|
local AMMO_SECTION_POSTFIXES = {
|
||
|
"_ap",
|
||
|
"_bmg",
|
||
|
"_bull",
|
||
|
"_buck",
|
||
|
"_buck_self",
|
||
|
"_barrikada",
|
||
|
"_dart",
|
||
|
"_ep",
|
||
|
"_eco",
|
||
|
"_fmj",
|
||
|
"_federal",
|
||
|
"_p",
|
||
|
"_ps",
|
||
|
"_pbp",
|
||
|
"_pab9",
|
||
|
"_pmm",
|
||
|
"_sp10",
|
||
|
"_ss190",
|
||
|
"_ss195",
|
||
|
"_shrapnel",
|
||
|
"_7h1",
|
||
|
"_7h14",
|
||
|
"_hydro",
|
||
|
"_hp_mag",
|
||
|
"_zhekan",
|
||
|
"_zhekan_heli",
|
||
|
"_verybad",
|
||
|
"_bad"
|
||
|
}
|
||
|
|
||
|
local shell_sound_list = {}
|
||
|
local current_material_name = "actor"
|
||
|
|
||
|
local volume = 0.8
|
||
|
local is_enabled = true
|
||
|
local is_panned = false
|
||
|
|
||
|
local function gsub_table(source, table)
|
||
|
for i = 1, #table do
|
||
|
local start_index, end_index = string.find(source, table[i])
|
||
|
if start_index ~= nil then
|
||
|
return string.sub(source, 1, start_index - 1)
|
||
|
end
|
||
|
end
|
||
|
return source
|
||
|
end
|
||
|
|
||
|
local function actor_on_footstep(material, power, hud_view, flags)
|
||
|
-- Store material name without path prefix "materials/", it`s 10 charaters in string begin
|
||
|
current_material_name = string.sub(material, 11)
|
||
|
end
|
||
|
|
||
|
local function get_sound_name(ammo_name)
|
||
|
local sound_type = SHELL_SOUND_TYPE[current_material_name] or SHELL_SOUND_TYPE_GENERIC
|
||
|
|
||
|
if sound_type == SHELL_SOUND_TYPE_WATER or sound_type == SHELL_SOUND_TYPE_LEAVES then
|
||
|
return "bullet_shells\\generic_" .. sound_type .. "_" .. math.random(1, 8)
|
||
|
else
|
||
|
return "bullet_shells\\" .. (SHELL_TYPE[ammo_name] or SHELL_TYPE_RIFLE) .. "_" .. sound_type .. "_" .. math.random(1, 8)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function get_sound_time(weapon_name, index)
|
||
|
local sound_gap_time = SHELL_SOUND_GAP_TIME[weapon_name] or 100
|
||
|
local sound_time = (SHELL_SOUND_TIME[weapon_name] or 1000) - sound_gap_time
|
||
|
|
||
|
if sound_time < 0 then
|
||
|
sound_time = 0
|
||
|
end
|
||
|
|
||
|
return time_global() + sound_time + (sound_gap_time * index) + math.random(0, 100)
|
||
|
end
|
||
|
|
||
|
local function get_weapon_info(weapon)
|
||
|
-- Getting pure weapon and ammo names without extra postfixes or prefixes and ammo count in magazine
|
||
|
local weapon_section = weapon:section()
|
||
|
local ammo_list = utils_item.get_ammo(weapon_section, weapon:id())
|
||
|
return gsub_table(string.sub(weapon_section, 5), WEAPON_SECTION_POSTFIXES), gsub_table(ammo_list[weapon:get_ammo_type() + 1] or "ammo_9x39", AMMO_SECTION_POSTFIXES), weapon:get_ammo_in_magazine()
|
||
|
end
|
||
|
|
||
|
local function create_shell_sound(is_reload)
|
||
|
if not is_enabled then return end
|
||
|
|
||
|
local weapon_name, ammo_name, ammo_in_magazine = get_weapon_info(db.actor:active_item())
|
||
|
|
||
|
if WEAPON_BLACKLIST[weapon_name] or (is_reload and not (WEAPON_DOUBLE_BARREL[weapon_name] or WEAPON_REVOLVER[weapon_name])) or (not is_reload and (WEAPON_DOUBLE_BARREL[weapon_name] or WEAPON_REVOLVER[weapon_name])) then return end
|
||
|
|
||
|
local count = 1
|
||
|
if WEAPON_REVOLVER[weapon_name] then
|
||
|
count = 6
|
||
|
elseif WEAPON_DOUBLE_BARREL[weapon_name] then
|
||
|
count = 2 - ammo_in_magazine
|
||
|
end
|
||
|
|
||
|
for i = 1, count do
|
||
|
shell_sound_list[#shell_sound_list + 1] = {
|
||
|
object = nil,
|
||
|
name = get_sound_name(ammo_name),
|
||
|
time = get_sound_time(weapon_name, i)
|
||
|
}
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function actor_on_update()
|
||
|
for i = 1, #shell_sound_list do
|
||
|
local shell_sound = shell_sound_list[i]
|
||
|
if shell_sound and time_global() > shell_sound.time then
|
||
|
if not shell_sound.object then
|
||
|
shell_sound.object = sound_object(shell_sound.name)
|
||
|
shell_sound.object:play(db.actor, 0, sound_object.s2d)
|
||
|
shell_sound.object.volume = volume
|
||
|
end
|
||
|
-- Release object only after sound will played to protect sound object from garbage collection
|
||
|
if not shell_sound.object:playing() then
|
||
|
shell_sound_list[i] = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function load_mcm_options()
|
||
|
if ui_mcm then
|
||
|
is_enabled = ui_mcm.get("bullet_shell_sounds/enabled")
|
||
|
volume = ui_mcm.get("bullet_shell_sounds/volume")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function actor_on_weapon_fired(obj, weapon, ammo_elapsed, grenade_elapsed, ammo_type, grenade_type) create_shell_sound(false) end
|
||
|
local function actor_on_weapon_reload(actor, weapon, ammo_total) create_shell_sound(true) end
|
||
|
|
||
|
function on_game_start()
|
||
|
RegisterScriptCallback("actor_on_footstep", actor_on_footstep)
|
||
|
RegisterScriptCallback("actor_on_update", actor_on_update)
|
||
|
RegisterScriptCallback("actor_on_weapon_fired", actor_on_weapon_fired)
|
||
|
RegisterScriptCallback("actor_on_weapon_reload", actor_on_weapon_reload)
|
||
|
RegisterScriptCallback("on_option_change", load_mcm_options)
|
||
|
load_mcm_options()
|
||
|
end
|