Divergent/mods/Bullet Shell Sounds/gamedata/scripts/bullet_shell_sounds.script

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