282 lines
No EOL
7.9 KiB
Text
282 lines
No EOL
7.9 KiB
Text
---------------------------------------------------------------------------------------------------------------------
|
|
-- Ñõåìà îòûãðûâàíèÿ ñâÿçíûõ çâóêîâûõ ïîñëåäîâàòåëüíîñòåé.
|
|
-- àâòîð: Äèäåíêî Ðóñëàí (Stohe)
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
--' Òàáëèöà ñîäåðæèò ìåíåäæåðû èñòîðèé
|
|
local sound_managers = {}
|
|
|
|
local story_ltx = ini_file("misc\\sound_stories.ltx")
|
|
|
|
|
|
--' Çâóêîâîé ìåíåäæåð ñîäåðæèò â ñåáå ñïèñîê ïåðñîíàæåé, êîòîðûå ìîãóò ðàññêàçàòü èñòîðèþ ïî ðîëÿì.
|
|
class "sound_manager"
|
|
function sound_manager:__init(id)
|
|
self.id = tostring(id)
|
|
self.npc = {} --'Òàáëèöà ïåðñîíàæåé, çàðåãèñòðèðîâàííûõ â ñàóíäìåíåäæåð
|
|
self.storyteller = nil --'Êòî ÿâëÿåòñÿ ðàññêàç÷èêîì
|
|
self.story = nil --'Êàêóþ èñòîðèþ áóäåò îòûãðûâàòü äàííûé ìåíåäæåð. Îäèí ìåíåäæåð óìååò îòûãðûâàòü òîëüêî îäíó èñòîðèþ.
|
|
self.last_playing_npc = nil
|
|
self.phrase_timeout = nil --' Õðàíèò âðåìÿ íà÷àëà ïàóçû ìåæäó ôðàçàìè.
|
|
self.phrase_idle = 0 --' Õðàíèò äëèíó ïàóçû ìåæäó ôðàçàìè.
|
|
end
|
|
--' Çàðåãèñòðèðîâàòü ÍÏÑ.
|
|
function sound_manager:register_npc(npc_id)
|
|
printf("Register sm npc [%s]:[%s]", self.id, npc_id)
|
|
table.insert(self.npc, {npc_id = npc_id})
|
|
--print_table(self.npc)
|
|
end
|
|
--' Îòðåãèñòðèðîâàòü íïñ
|
|
function sound_manager:unregister_npc(npc_id)
|
|
printf("UnRegister sm npc [%s]:[%s]", self.id, npc_id)
|
|
|
|
if self.last_playing_npc == npc_id and
|
|
xr_sound.sound_table[self.last_playing_npc]
|
|
then
|
|
-- Óäàëÿåòñÿ ÷óâàê, êîòîðûé ùàñ ãîâîðèò ôðàçó. Íóæíî îáðóáèòü èñòîðèþ
|
|
self.story = nil
|
|
xr_sound.sound_table[self.last_playing_npc]:stop(npc_id)
|
|
end
|
|
|
|
if self.storyteller == npc_id then
|
|
self.storyteller = nil
|
|
end
|
|
|
|
local remove_id = nil
|
|
for k,v in pairs(self.npc) do
|
|
if v.npc_id == npc_id then
|
|
remove_id = k
|
|
break
|
|
end
|
|
end
|
|
if remove_id ~= nil then
|
|
table.remove(self.npc, remove_id)
|
|
end
|
|
--print_table(self.npc)
|
|
end
|
|
--' Óñòàíîâèòü íïñ, êàê ðàçêàç÷èêà.
|
|
function sound_manager:set_storyteller(npc_id)
|
|
self.storyteller = npc_id
|
|
--printf("Set storyteller sm [%s] = [%s]", self.id, npc_id)
|
|
end
|
|
|
|
--' Îáíîâëåíèå
|
|
function sound_manager:update()
|
|
--printf("Updating sm [%s]", self.id)
|
|
if self.story == nil then
|
|
--printf("no story")
|
|
return
|
|
end
|
|
|
|
--' Æäåì ïîêà íå çàêîí÷èòñÿ óæå íà÷àòûé çâóê
|
|
if xr_sound.sound_table[self.last_playing_npc] ~= nil then
|
|
--printf("wait sound")
|
|
|
|
-- !!! Åñëè â áîþ - îáðóáèòü çâóê è ñàóíäòåìó
|
|
if db.storage[self.last_playing_npc] and db.storage[self.last_playing_npc].object:best_enemy() ~= nil then
|
|
self.story = nil
|
|
xr_sound.sound_table[self.last_playing_npc]:stop(self.last_playing_npc)
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
--' Óñòàíàâëèâàåì òàéìàóò îæèäàíèÿ ìåæäó ôðàçàìè.
|
|
local t_global = time_global()
|
|
if self.phrase_timeout == nil then
|
|
self.phrase_timeout = t_global
|
|
end
|
|
|
|
if t_global - self.phrase_timeout < self.phrase_idle then
|
|
--printf("wait time")
|
|
return
|
|
end
|
|
|
|
|
|
--' Âûáèðàåì ñëåäóþùóþ ôðàçó.
|
|
local next_phrase = self.story:get_next_phrase()
|
|
|
|
--'  òåìå çàêîí÷èëèñü ôðàçû
|
|
if next_phrase == nil then
|
|
--printf("no phrase")
|
|
return
|
|
end
|
|
|
|
local npc = nil
|
|
local tn = #self.npc
|
|
if tn == 0 then
|
|
--printf("no npc")
|
|
return
|
|
end
|
|
|
|
--' Âûáèðàåì ïåðñîíàæà, êîòîðûé ñêàæåò ôðàçó
|
|
if next_phrase.who == "teller" then
|
|
--' ôðàçà ðàññêàç÷èêà
|
|
if self.storyteller == nil then
|
|
self:choose_random_storyteller()
|
|
end
|
|
npc = self.storyteller
|
|
|
|
elseif next_phrase.who == "reaction" then
|
|
--' Ôðàçà êîãî óãîäíî, êðîìå ðàññêàç÷èêà
|
|
local teller_id = 0
|
|
for k,v in pairs(self.npc) do
|
|
if v.npc_id == self.storyteller then
|
|
teller_id = k
|
|
break
|
|
end
|
|
end
|
|
|
|
if tn >= 2 then
|
|
local id = math.random(1,tn-1)
|
|
if id >= teller_id then
|
|
id = id + 1
|
|
end
|
|
npc = self.npc[id].npc_id
|
|
else
|
|
npc = self.npc[1].npc_id
|
|
end
|
|
elseif next_phrase.who == "reaction_all" then
|
|
local npc_id = nil
|
|
for k,v in pairs(self.npc) do
|
|
if v.npc_id ~= self.storyteller then
|
|
xr_sound.set_sound_play(v.npc_id, next_phrase.theme)
|
|
npc_id = v.npc_id
|
|
end
|
|
end
|
|
|
|
self.last_playing_npc = npc_id
|
|
self.phrase_timeout = nil
|
|
self.phrase_idle = next_phrase.timeout * 1000
|
|
return
|
|
else
|
|
--' Ôðàçà êîãî óãîäíî.
|
|
npc = self.npc[math.random(1,#self.npc)].npc_id
|
|
end
|
|
|
|
if(npc==nil or db.storage[npc]==nil) then
|
|
return
|
|
end
|
|
-- !!! Åñëè â áîþ - îáðóáèòü çâóê è ñàóíäòåìó
|
|
if db.storage[npc].object:best_enemy() ~= nil and xr_sound.sound_table[npc] ~= nil then
|
|
self.story = nil
|
|
xr_sound.sound_table[npc]:stop(npc)
|
|
return
|
|
end
|
|
|
|
|
|
printf("Speaking sm [%s] npc[%s] phrase[%s]", self.id, npc, next_phrase.theme)
|
|
|
|
--' Êåøèðóåì êòî ïðîèçíîñèò ôðàçó, ÷òîáû îòëàâëèâàòü êîãäà îí çàêîí÷èò
|
|
self.last_playing_npc = npc
|
|
|
|
--' Ïðîèçíîñèì ôðàçó
|
|
if next_phrase.theme ~= "nil" then
|
|
if(self.story and self.story.id=="squad_counter_attack") then
|
|
local npc = alife():object(npc)
|
|
local board = sim_board.get_sim_board()
|
|
if(npc) and (board) then
|
|
local our_squad = get_object_squad(npc)
|
|
if(our_squad) then
|
|
local our_smart = our_squad.smart_id
|
|
local task = task_manager.get_task_manager():get_tasks_by_smart(our_smart)
|
|
if(next_phrase.who~="teller") then
|
|
local enemy_faction = task.counter_attack_community
|
|
xr_sound.set_sound_play(npc.id, next_phrase.theme, enemy_faction)
|
|
self.phrase_timeout = nil
|
|
self.phrase_idle = next_phrase.timeout * 1000
|
|
return
|
|
end
|
|
xr_sound.set_sound_play(npc.id, next_phrase.theme, our_squad.player_id, our_smart)
|
|
self.phrase_timeout = nil
|
|
self.phrase_idle = next_phrase.timeout * 1000
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
xr_sound.set_sound_play(npc, next_phrase.theme)
|
|
end
|
|
|
|
self.phrase_timeout = nil
|
|
self.phrase_idle = next_phrase.timeout * 1000
|
|
end
|
|
--' Ðàíäîìíûé âûáîð ðàçêàç÷èêà (âûçûâàåòñÿ åñëè íà ìîìåíò ðàññêàçà ðàññêàç÷èêà íåò)
|
|
function sound_manager:choose_random_storyteller()
|
|
self.storyteller = self.npc[math.random(1,#self.npc)].npc_id
|
|
end
|
|
--' Çàêîí÷èë ëè ñàóíä ìåíåäæåð èãðàòü ñâîþ èñòîðèþ
|
|
function sound_manager:is_finished()
|
|
if self.story == nil then
|
|
return true
|
|
end
|
|
return self.story:is_finished()
|
|
end
|
|
--' Óñòàíîâèòü êàêóþ èñòîðèþ ìåíåäæåð äîëæåí îòûãðàòü
|
|
function sound_manager:set_story(story_id)
|
|
self.story = CStory(story_id)
|
|
--printf("Set story sm [%s] = [%s]", self.id, story_id)
|
|
end
|
|
|
|
|
|
|
|
--' Ñîçäàòü íîâûé ñàóíä-ìåíåäæåð. Íóæíî ïåðåäàòü óíèêàëüíûé àéäèøíèê
|
|
function get_sound_manager(id)
|
|
if sound_managers[id] == nil then
|
|
sound_managers[id] = sound_manager(id)
|
|
end
|
|
return sound_managers[id]
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--' Êëàññ "èñòîðèÿ". Ñîäåðæèò äåðåâî ôðàç. Ó êàæäîé ôðàçû óêàçàíî äîëæåí ëè åå ãîâîðèòü ðàññêàç÷èê èëè ñëóøàòåëè.
|
|
class "CStory"
|
|
function CStory:__init(story_id)
|
|
--printf("Creating story [%s]", tostring(story_id))
|
|
|
|
if not story_ltx:section_exist(story_id) then
|
|
abort("There is no story [%s] in sound_stories.ltx", tostring(story_id))
|
|
end
|
|
|
|
self.replics = {}
|
|
--' Âû÷èòûâàåì øàáëîí èñòîðèè èç ini ôàéëà
|
|
|
|
local n = story_ltx:line_count(story_id)
|
|
local id, value = "",""
|
|
|
|
for i=0,n-1 do
|
|
result, id, value = story_ltx:r_line(story_id,i,"","")
|
|
|
|
local t = parse_names(value)
|
|
|
|
if t[1] ~= "teller" and t[1] ~= "reaction" and t[1] ~= "reaction_all" then
|
|
abort("Wrong fist field [%s] in story [%s]", tostring(t[1]), tostring(story_id))
|
|
end
|
|
|
|
self.replics[i] = {who = t[1], theme = t[2], timeout = t[3]}
|
|
end
|
|
self.id = tostring(story_id)
|
|
self.max_phrase_count = n-1
|
|
self.next_phrase = 0
|
|
--print_table(self.replics)
|
|
end
|
|
--' Çàêîí÷åíà ëè èñòîðèÿ
|
|
function CStory:is_finished()
|
|
return self.next_phrase > self.max_phrase_count
|
|
end
|
|
--' Ðåñåò èñòîðèè
|
|
function CStory:reset_story()
|
|
self.next_phrase = 0
|
|
end
|
|
--' Âîçâðàùàåò ñëåäóþùóþ ôðàçó
|
|
function CStory:get_next_phrase()
|
|
local phrase = self.replics[self.next_phrase]
|
|
self.next_phrase = self.next_phrase + 1
|
|
return phrase
|
|
end |