---------------------------------------------------------------------------------------------------------------------
-- Схема озвучки
-- автор: Диденко Руслан (Stohe)
-- update: Чугай Александр (Chugai)
----------------------------------------------------------------------------------------------------------------------
key_by_id = {}
group_idle = {}
--function printf()
--end
function get_sound(path, tt, npc)
if path == nil then return nil end
if path.exec == nil then
-- чтение настроек темы
tt.into_id = path.into_id
tt.into_max = path.max_ids[npc:id()].into_max
tt.into_last = nil
tt.rnd_id = path.rnd_id
tt.rnd_max = path.max_ids[npc:id()].rnd_max
tt.rnd_last = nil
tt.min_snd = path.min_snd
tt.max_snd = path.max_snd
tt.rnd_snd = path.rnd_snd
else
get_sound(path.types[path.exec(path.types, npc)], tt, npc)
end
end
-- Формирование ключа персонажа
function get_key(npc)
local key
-- формирование ключа
local overrides = xr_logic.generic_scheme_overrides(npc)
if overrides and
overrides.soundgroup
then
key = overrides.soundgroup
else
key = utils.to_str(npc:id())
end
-- апдейт таблиц не менять!
if xr_sound.key_by_id[npc:id()] ~= key then
if xr_sound.group_idle[xr_sound.key_by_id[npc:id()]] ~= nil then
xr_sound.group_idle[xr_sound.key_by_id[npc:id()]].num_in_group = xr_sound.group_idle[xr_sound.key_by_id[npc:id()]].num_in_group - 1
end
xr_sound.key_by_id[npc:id()] = key
if xr_sound.group_idle[key] == nil then
xr_sound.group_idle[key] = {num_in_group = 1}
else
xr_sound.group_idle[key].num_in_group = xr_sound.group_idle[key].num_in_group + 1
end
end
return key
end
------------------------------------------------------------------------------------------------------------------------------- ----
-- Установка и распарсивание тем в файлы.
-----------------------------------------------------------------------------------------------------------------------------------
f unction set_sound(npc, sound, now, into_timeout)
-- printf("*SND* [%s] try to change SND to [%s]", npc:name(), tostring(sound))
local npc_id = npc:id()
if (db.sound[npc_id] == nil or
db.sound[npc_id].theme ~= sound) or
now == true
then
-- if db.sound[npc_id] == nil then
-- printf("*SND* change SND [_] to [%s] for [%s]", tostring(sound), npc:name())
-- else
-- printf("*SND* change SND [%s] to [%s] for [%s]", tostring(db.sound[npc_id].theme), tostring(sound), npc:name())
-- end
-- Туточки надобно распарсить имена тем в их id
if sound == nil then sound = "" end
if db.sound[npc_id] == nil then db.sound[npc_id] = {} end
db.sound[npc_id].theme = sound
db.sound[npc_id].snd = parse_names(sound)
if db.sound[npc_id].last_snd == nil then
db.sound[npc_id].last_snd = {}
else
local snd_table = {}
local t = 0
for k,v in pairs(db.sound[npc_id].snd) do
snd_table[t] = {}
get_sound(sound_theme.theme[v], snd_table[t], npc)
t = t + 1
end
for k,v in pairs(snd_table) do
if v.into_id then db.sound[npc_id].last_snd[v.into_id] = nil end
if v.rnd_id then db.sound[npc_id].last_snd[v.rnd_id] = nil end
end
end
-- Устанавливаем входную паузу
local key = get_key(npc)
xr_sound.group_idle[key].begin = time_global()
if into_timeout then
xr_sound.group_idle[key].idle = into_timeout
else
xr_sound.group_idle[key].idle = 0
end
if now == true then
stop_play_sound(npc)
end
end
end
function play_sound(npc, themes, timeout)
-- нужно составить список тем
local snd_table = {}
local t = 0
for k,v in pairs(themes) do
snd_table[t] = {}
if sound_theme.theme[v] ~= nil then
snd_table[t].theme = v
get_sound(sound_theme.theme[v], snd_table[t], npc)
else
abort("ERROR: ILLEGAL PLAY SOUND!!! %s for %s", v, npc:name())
end
t = t + 1
end
--printf("*")
--print_table(snd_table)
if t == 0 then return end
-- из списка тем выбираем одну.
local snd = snd_table[math.random(0, t-1)]
if snd ~= nil then
--printf("!")
--print_table(snd)
if snd.min_snd == nil then return end
local npc_id = npc:id()
local group_table = xr_sound.group_idle[get_key(npc)]
group_table.idle = math.random(snd.min_snd, snd.max_snd)*1000
if group_table.last_snd == nil then
group_table.last_snd = {}
end
-- необходимо ли нам играть into или rnd звуки
if snd.into_max ~= nil and
snd.into_max > 0
then
if db.sound[npc_id].last_snd[snd.into_id] == snd.into_max - 1 then
if snd.into_cycled == true then
db.sound[npc_id].last_snd[snd.into_id] = nil
else
return
end
end
-- играем входные
if db.sound[npc_id].last_snd[snd.into_id] == nil then db.sound[npc_id].last_snd[snd.into_id] = -1 end
--printf("*SND* play seq [%s] for [%s]", db.sound[npc_id].last_snd[snd.into_id]+1, npc:name())
process_tutor_on_sound(snd.theme)
npc:play_sound(snd.into_id, 1, 0, 1, 0, db.sound[npc_id].last_snd[snd.into_id]+1)
db.sound[npc_id].last_snd[snd.into_id] = db.sound[npc_id].last_snd[snd.into_id] + 1
--printf("*SND* play seq [%s] for [%s]", db.sound[npc_id].last_snd[snd.into_id], npc:name())
return
end
if snd.rnd_max ~= nil and
snd.rnd_max > 0
then
-- играем рандомные
local s = 0
if snd.rnd_max == 1 then
s = 0
else
-- Если прошлый раз проигрывался такой же набор тем
-- то учитывать последний звук для группы.
-- if db.sound[npc_id].last_snd[snd.rnd_id] ~= nil then
if group_table.last_snd[snd.rnd_id] ~= nil then
s = math.random(0, snd.rnd_max-2)
if s >= group_table.last_snd[snd.rnd_id] then s = s + 1 end
else
s = math.random(0, snd.rnd_max-1)
end
end
if timeout == nil then
timeout = 0
end
--printf("*SND* play rnd [%s] for [%s]", s, npc:name())
process_tutor_on_sound(snd.theme)
npc:play_sound(snd.rnd_id, timeout+1, timeout, 1, 0, s)
--db.sound[npc_id].last_snd[snd.rnd_id] = s
group_table.last_snd[snd.rnd_id] = s
end
end
end
function get_last_IDS(npc, theme)
local last_table = db.sound[npc:id()].last_snd
local snd_table = {}
if sound_theme.theme[theme] ~= nil then
get_sound(sound_theme.theme[theme], snd_table, npc)
end
printf("LAST INTO ID for [%s] = [%s], max [%s]", theme, last_table[snd_table.into_id], snd_table.into_max)
return last_table[snd_table.into_id], snd_table.into_max
end
function load_sound(npc)
sound_theme.load_sound(npc)
end
function process_tutor_on_sound(theme)
end
--' Actor sound player
local actor_sound = {}
function set_actor_sound(sound)
printf("*ACTOR SND* try to change SND to [%s]", tostring(sound))
if actor_sound.theme ~= sound then
--' Туточки надобно распарсить имена тем в их id
if sound == nil then sound = "" end
actor_sound.theme = sound
actor_sound.begin = nil
this.set_actor_sound_factor(1)
end
end
function set_actor_sound_factor(factor)
local theme = sound_theme.actor_theme[actor_sound.theme]
if theme ~= nil then
actor_sound.min_snd = theme.min_snd * factor
actor_sound.max_snd = theme.max_snd * factor
end
end
function update_actor()
local theme = sound_theme.actor_theme[actor_sound.theme]
if theme == nil then return end
if table.getn(theme.sounds) == 0 then
return
end
if actor_sound.begin == nil or
time_global() - actor_sound.begin >= actor_sound.idle
then
actor_sound.begin = time_global()
--' Тут надо отыграть звук
local sound = theme.sounds[math.random(table.getn(theme.sounds))]
if sound ~= nil then
sound:play(db.actor, 0, sound_object.s2d)
end
actor_sound.idle = math.random(actor_sound.min_snd, actor_sound.max_snd)
end
end
--' Таблица для хранения созданных саунд обжектов.
sound_object_by_theme = {}
--' type = [random|seq|looped]
function get_sound_object(theme, t_type)
if sound_theme.ph_snd_themes[theme] == nil then
abort("ph_snd_themes for theme %s", tostring(theme))
return
end
if sound_object_by_theme[theme] == nil then
sound_object_by_theme[theme] = {}
end
if t_type == nil then
t_type = "random"
end
--' Выбор следующего айдишника
local play_id = -1
local table_size = table.getn(sound_theme.ph_snd_themes[theme])
if sound_object_by_theme[theme].last_id == nil then
if t_type == "random" then
if table_size >= 2 then
play_id = math.random(1, table_size)
else
play_id = 1
end
else
play_id = 1
end
else
if t_type == "random" then
if table_size >= 2 then
play_id = math.random(1, table_size - 1)
if play_id >= sound_object_by_theme[theme].last_id then play_id = play_id + 1 end
else
play_id = 1
end
else
if sound_object_by_theme[theme].last_id < table_size then
play_id = sound_object_by_theme[theme].last_id + 1
else
if type == "looped" then
play_id = 1
end
end
end
end
printf("SOUND_OBJECT: selected id [%s] for theme [%s], type [%s], size [%s]", tostring(play_id), tostring(theme), tostring(type), table_size)
if play_id == -1 then
return
end
--' Проверяем создан ли у нас соответствующий саунд обжект или его надо создать
if sound_object_by_theme[theme][play_id] == nil then
if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then
sound_object_by_theme[theme][play_id.."_r"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_r")
sound_object_by_theme[theme][play_id.."_l"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_l")
else
sound_object_by_theme[theme][play_id] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id])
end
end
sound_object_by_theme[theme].last_id = play_id
--' Возвращаем саунд обжект
if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then
return sound_object_by_theme[theme][play_id.."_r"], sound_object_by_theme[theme][play_id.."_l"]
else
return sound_object_by_theme[theme][play_id]
end
end
local sound_object_by_path = {}
--' Обертка вокруг функции, возвращающий звуковой объект.
function get_safe_sound_object(path)
if sound_object_by_path[path] == nil then
sound_object_by_path[path] = sound_object(path)
end
return sound_object_by_path[path]
end
function stop_all_sound_object()
for k,v in pairs(sound_object_by_path) do
if v:playing() then
v:stop()
end
end
end
function clear_all_sound_object()
sound_object_by_theme = {}
end