324 lines
10 KiB
Plaintext
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
|
|
--]] |