Divergent/mods/AI Combat Pack/gamedata/scripts/rx_sound.script

324 lines
10 KiB
Plaintext

--'-------------------------------------------------------------------------------------------------------------------
--' AI Additions
--' îáùàÿ îçâó÷êà ïåðñîíàæåé
--' Rulix aka Bak
--' 10.03.2016
--'--------------------------------------------------------------------------------------------------------------------
local nstl = 64
local theme = {}
local mute_npcs = {}
local function id()
return sound_theme.id()
end
function load_sounds()
stalker_ids.sound_enemy_killed_or_wounded = stalker_ids.sound_enemy_critically_wounded+1 -- fix wrong export id
local snd_ini = ini_file([[misc\ai_additions\rx_script_sound.ltx]])
ASSERTX(snd_ini:section_exist("list"),"There is no section [list] in rx_script_sound.ltx")
local n = snd_ini:line_count("list")
local result,section,value
for i=0,n-1 do
result,section,value = snd_ini:r_line("list",i,"","")
if theme[section] == nil and (value == '' or _G[value] ~= nil) then
theme[section] = npc_sound_generic(snd_ini,section)
end
end
mute_npcs = rx_utils.collect_sections(snd_ini,{"mute_characters"},nil,true)
end
--' Èãðàòü òåìó
function set_sound_play(npc_id,sound,cb_func)
local snd_theme = theme[sound]
if not snd_theme then
rx_ai.printf("set_sound_play. Wrong sound theme [%s], npc[%s]", tostring(sound), npc_id)
return
end
if xr_sound.sound_table[npc_id] == nil then
if snd_theme:play(npc_id) then
snd_theme.npc[npc_id].cb = cb_func
xr_sound.sound_table[npc_id] = snd_theme
return true
end
-- else
-- rx_ai.printf("rx_sound: cannot play sound [%s] because i'm [%s] already play snd [%s]",sound,npc_id,xr_sound.sound_table[npc_id].path)
end
end
class "npc_sound_generic"
function npc_sound_generic:__init(snd_ini,section)
self.section = section
--' Õðàíèò ïàðàìåòðû çâóêà äëÿ êàæäîãî NPC
self.npc = {}
--' Ïàðàìåòðû âû÷èòûâàíèÿ çâóêà
self.internal_type = stalker_ids[rx_utils.read_from_ini(snd_ini,section,"sound","_nil",1)]
if not self.internal_type then
self.prefix = rx_utils.read_from_ini(snd_ini,section,"npc_prefix",true,0)
self.path = rx_utils.read_from_ini(snd_ini,section,"path","",1)
self.shuffle = rx_utils.read_from_ini(snd_ini,section,"shuffle","rnd",1)
-- self.is_combat_sound = rx_utils.read_from_ini(snd_ini,section,"is_combat_sound",false,0) or nil
self.pda_snd = rx_utils.read_from_ini(snd_ini,section,"pda_snd",false,0) or nil
self.type = snd_type[rx_utils.read_from_ini(snd_ini,section,"type","_nil",1)]
end
self.group_snd = rx_utils.read_from_ini(snd_ini,section,"group_snd",false,0) or nil
-- Âðåìÿ çàäåðæêè íà÷àëà îòûãðûâàíèÿ çâóêà
local delay = rx_utils.parse_list(snd_ini,section,"delay_sound",nil,true)
self.min_delay = delay[1] or 0
self.max_delay = delay[2] or self.min_delay
--' Èíòåðâàë ïðîèãðûâàíèÿ çâóêà
local interval = rx_utils.parse_list(snd_ini,section,"idle",nil,true)
self.min_idle = interval[1]
self.max_idle = interval[2]
self.rnd = interval[3]/100
if snd_ini:line_exist(section,"avail_communities") then
self.avail_communities = rx_utils.parse_list(snd_ini,section,"avail_communities",true)
end
if self.group_snd then
self.can_play_group_sound = true
end
end
function npc_sound_generic:init_npc(npc)
if self.internal_type then
self.npc[npc:id()] = {}
return
end
local f = getFS()
local character_prefix
if self.prefix == false then
character_prefix = npc:sound_prefix()
npc:sound_prefix("characters_voice\\")
end
local npc_data = {}
npc_data.id = id()
npc_data.max = npc:add_sound(self.path, nstl, self.type or snd_type.monster_talk, 1, 1, npc_data.id, "bip01_head") - 1 -- priority 2 mask 1?
if npc_data.max < 0 then
npc_data = nil
elseif self.pda_snd then
npc_data.path = {}
if f:exist("$game_sounds$",npc:sound_prefix()..self.path..".ogg") ~= nil then
npc_data.path[1] = npc:sound_prefix()..self.path
else
local num = 1
while f:exist("$game_sounds$",npc:sound_prefix()..self.path..num..".ogg") do
npc_data.path[num] = npc:sound_prefix()..self.path..num
num = num + 1
end
end
end
self.npc[npc:id()] = npc_data
if character_prefix then
npc:sound_prefix(character_prefix)
end
end
function npc_sound_generic:play(npc_id,override)
local npc = db.storage[npc_id] and db.storage[npc_id].object
if npc == nil then
rx_ai.printf("sound[%s]:coudnt find npc!!!",npc_id)
return false
end
if not override and npc:active_sound_count() > 0 then
return false
end
local npc_data = self.npc[npc_id]
if not npc_data then
return false
end
-- êòî-òî óæå ãîâîðèò ãðóïïîâîé çâóê
if self.group_snd and not self.can_play_group_sound then
return false
end
-- íå ïîâåçëî ñêàçàòü
if math.random() > self.rnd then
return false
end
-- âðåìÿ åù¸ íå ïðèøëî
if npc_data.played_time and time_global()-npc_data.played_time < self.idle_time then
return false
end
npc_data.played_time = nil
-- åñëè ñòàíäàðòíûé çâóê - êîìàíäà èãðàòü
if self.internal_type then
if self.group_snd then
self.can_play_group_sound = false
end
local _ = override == 0 and stop_sounds_on_combat(npc) or override and stop_sounds(npc)
npc:play_sound(self.internal_type, self.max_delay, self.min_delay)
return true
end
--' Âûáîð çâóêà, êîòîðûé èãðàòü.
self.played_id = self:select_next_sound(npc_data)
-- çâóêîâ íåò, èëè ïîñëåäîâàòåëüíîñòü óæå îòûãðàíà
if self.played_id == -1 then
return false
end
if self.group_snd then
self.can_play_group_sound = false
end
local _ = override == 0 and stop_sounds_on_combat(npc) or override and stop_sounds(npc)
-- play_sound (u32 internal_type, u32 max_start_time, u32 min_start_time, u32 max_stop_time, u32 min_stop_time, u32 id)
npc:play_sound(npc_data.id, self.max_delay, self.min_delay, 1, 0, self.played_id)
-- ïðîâåðêà íà ñóùåñòâîâàíèå çâóêà äóáëèðóþùåãî îñíîâíîé ïî ÏÄÀ. Åñëè îí åñòü òî èãðàòü è åãî.
if self.pda_snd then
local snd = npc_data.path[self.played_id+1]
if snd and getFS():exist("$game_sounds$",snd.."_pda.ogg") ~= nil and npc:position():distance_to_sqr(db.actor:position()) >= 100 then
if self.pda_snd_obj ~= nil and self.pda_snd_obj:playing() then
self.pda_snd_obj:stop()
end
self.pda_snd_obj = rx_utils.get_sound(snd.."_pda")
self.pda_snd_obj:play_at_pos(db.actor, vector():set(0,0,0), self.max_delay, sound_object.s2d)
self.pda_snd_obj.volume = 0.8
end
end
return true
end
function npc_sound_generic:select_next_sound(npc_data)
if npc_data.max < 0 then
return -1
end
if self.shuffle == "rnd" then
if npc_data.max == 0 then
return 0
end
if self.played_id ~= nil then
if npc_data.max == 1 then
return 1-self.played_id
end
local played_id = math.random(0,npc_data.max-1)
if played_id >= self.played_id then
return played_id + 1
end
return played_id
end
return math.random(0,npc_data.max)
end
if self.shuffle == "seq" then
if self.played_id == nil then
return 0
end
if self.played_id < npc_data.max then
return self.played_id + 1
end
return -1
end
if self.shuffle == "loop" then
if self.played_id == nil then
return 0
end
if self.played_id < npc_data.max then
return self.played_id + 1
end
return 0
end
end
function npc_sound_generic:callback(npc_id)
if self.group_snd then
self.can_play_group_sound = true
end
self.idle_time = math.random(self.min_idle,self.max_idle) * 1000
local npc_data = self.npc[npc_id]
if npc_data then
npc_data.played_time = time_global()
if npc_data.cb then
npc_data.cb[1](npc_data.cb[2],self)
npc_data.cb = nil
end
end
end
function npc_sound_generic:reset(npc_id)
local npc = db.storage[npc_id] and db.storage[npc_id].object
self.npc[npc_id].played_time = nil
self.played_id = nil
if self.group_snd then
self.can_play_group_sound = true
end
stop_sounds(npc)
if self.pda_snd_obj ~= nil then
self.pda_snd_obj:stop()
self.pda_snd_obj = nil
end
end
function npc_sound_generic:is_playing(npc_id)
-- Ïðîâåðêà èãðàåòñÿ ëè ñåé÷àñ çâóê ó íïñ
local obj = db.storage[npc_id] and db.storage[npc_id].object
if obj == nil then
return false
end
return obj:active_sound_count() ~= 0 or (self.pda_snd_obj and self.pda_snd_obj:playing())
end
function npc_sound_generic:stop(obj_id)
local npc = db.storage[obj_id] and db.storage[obj_id].object
stop_sounds(npc)
if self.pda_snd_obj and self.pda_snd_obj:playing() then
self.pda_snd_obj:stop()
self.pda_snd_obj = nil
end
end
--' Çàãðóçêà çâóêîâ ÍÏÑ
function init_npc_sound(npc)
if not (mute_npcs[npc:name()] or mute_npcs[npc:profile_name()] or mute_npcs.all_story and rx_utils.is_story_object(npc)) then
local comm = npc:character_community()
for _,s in pairs(theme) do
if not s.avail_communities or s.avail_communities[comm] then
s:init_npc(npc)
end
end
end
end
--' Äëÿ óáèðàíèÿ çâóêîâ ïðè ïåðåêëþ÷åíèè ñ áîåâûõ ñõåì íà êîìáàò ïëàííåð
function block_alarm_sound(npc)
if npc:best_enemy() and not xr_sound.sound_table[npc:id()] then
npc:set_fastcall(stop_sounds,npc)
end
if not state_mgr.is_idle(npc) then
npc:motivation_action_manager():action(xr_actions_id.state_mgr+1).block_sound = true
end
end
function stop_sounds(obj)
if obj and obj:alive() then
obj:set_sound_mask(-1)
obj:set_sound_mask(0)
end
return true
end
---[[
--'--------------------------------------------------------------------------------------------------------------------
--' êëàññ äëÿ ïðîèãðûâàíèÿ çâóêîâ èç êîíôèãà îáúåêòà
--'--------------------------------------------------------------------------------------------------------------------
class "dihud_sound"
function dihud_sound:__init(section,name,typ,read_delay)
self.st = {}
self.type = typ
local inif = system_ini()
local k,sline = 0,name
while inif:line_exist(section,sline) do
k = k+1
self.st[k] = rx_utils.parse_list(inif,section,sline,nil,true)
if not read_delay then
self.st[k][3] = nil
end
sline = name..k
end
end
function dihud_sound:play(obj,pos,delay,volume)
local s = self.st[math.random(#self.st)]
if s and s[1] and s[1] ~= "" then
local snd = rx_utils.get_sound(s[1])
local dly = (delay or 0)+(s[3] or 0)
if pos then
snd:play_at_pos(obj,pos,dly,self.type or sound_object.s3d)
else
snd:play(obj,dly,self.type or sound_object.s3d)
end
if volume or s[2] then
snd.volume = (volume or 1)*(s[2] or 1)
end
end
end
--]]