-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspeech.lua
More file actions
424 lines (397 loc) · 12.6 KB
/
speech.lua
File metadata and controls
424 lines (397 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
--------------------------------------------------------------------
-- Speech --
--------------------------------------------------------------------
--[[
Dependencies:
bb_comforts.lua
timer.lua
cinematic.lua
]]--
function SetupSpeech(_voicePath)
npcSpeech = {}
speech_convToAdd = {}
speech_selectedEntities = {}
SPEECH_ROTATION = -45
SPEECH_ZOOM = 1000
SPEECH_ANGLE = 45
SPEECH_VOICE_PATH = _voicePath
XGUIEng.ShowWidget("CinematicMC_Headline", 0)
XGUIEng.ShowWidget("CinematicMC_Text", 0)
GameCallback_Escape_OrigSpeech = GameCallback_Escape
GameCallback_NPCInteraction_OrigBrief = GameCallback_NPCInteraction
GameCallback_NPCInteraction = function(heroId, npcId)
if npcSpeech[npcId] then
if npcSpeech[npcId].onlySpeaksTo then
for i = 1, table.getn(npcSpeech[npcId].onlySpeaksTo) do
if heroId == GetEntityId(npcSpeech[npcId].onlySpeaksTo[i]) then
bb_StartSpeech(npcId)
FaceEachOther(heroId, npcId)
return
end
end
if npcSpeech[npcId].wrongHeroMessage then
Message(npcSpeech[npcId].wrongHeroMessage)
end
else
bb_StartSpeech(npcId)
FaceEachOther(heroId, npcId)
end
else
GameCallback_NPCInteraction_OrigBrief(heroId, npcId)
end
end
BriefingMCButtonSelected = function(_index)
if Speech_Continue() then
return
end
local count = 1
local newConvIndex
for text, subSpeechTable in pairs(speech_Conv[speech_curPage].mc) do
if count == _index then
local tableToChange = subSpeechTable
local page = speech_curPage + 1
while speech_Conv[page] do
table.insert(tableToChange.default, speech_Conv[page])
page = page + 1
end
speech_currentSpeaker["MultipleChoice"] = tableToChange
end
count = count + 1
end
IsWaitingForMCSelection = Speech_IsWaitingForMCSelection
speech_active = false
if speech_currentSpeaker.id then
bb_StartSpeech(speech_currentSpeaker.id, "MultipleChoice")
else
bb_StartDialog(speech_currentSpeaker)
end
XGUIEng.ShowWidget("CinematicMC_Button1", 1)
XGUIEng.ShowWidget("CinematicMC_Button2", 0)
end
InitSpeechIfNear()
end
function Speech_ASP(_title, _text, _pos, _voice, _rot, _angle, _zoom, _action, _mc, _nextPageTime)
return {
title = _title,
text = _text,
pos = _pos,
rot = _rot,
angle = _angle,
zoom = _zoom,
action = _action,
mc = _mc,
nextPageTime = _nextPageTime,
voice = _voice
}
end
function AddConvToSpeaker(_speaker, _conv)
assert(type(_speaker) == "table")
table.insert(_speaker, _conv)
EnableNpcMarker(_speaker.id)
end
function CreateSpeaker(_speaker)
assert(type(_speaker) == "table")
npcSpeech[_speaker.id] = _speaker
EnableNpcMarker(_speaker.id)
end
function RemoveSpeaker(_speaker)
local eId = GetEntityId(_speaker)
npcSpeech[eId] = nil
DisableNpcMarker(eId)
end
function bb_StartDirectSpeech(_speaker)
local id = GetEntityId(_speaker)
bb_StartSpeech(id)
end
function bb_StartDialog(_conv)
assert(type(_conv) == "table", "Speech: invalid dialog")
bb_StartSpeech(_conv)
end
function bb_StartSpeech(_id, _convIndex)
local selectedEnt = { GUI.GetSelectedEntities() }
for i = 1, table.getn(selectedEnt) do
table.insert(speech_selectedEntities, selectedEnt[i])
end
if speech_active then
table.insert(speech_convToAdd, { id = _id, convIndex = _convIndex })
return
else
speech_active = true
end
speech_camPos = {Camera.ScrollGetLookAt()}
speech_currConvIndex = _convIndex or 1
local currentSpeaker = {}
if type(_id) == "table" then
currentSpeaker[speech_currConvIndex] = _id
else
currentSpeaker = npcSpeech[_id]
end
speech_currentSpeaker = currentSpeaker
speech_Remove = true
speech_finished = true
speech_continue = currentSpeaker[speech_currConvIndex].continue
if currentSpeaker[speech_currConvIndex].condition then
if currentSpeaker[speech_currConvIndex].condition() then
speech_Conv = currentSpeaker[speech_currConvIndex].fullfilled
else
speech_Conv = currentSpeaker[speech_currConvIndex].unfullfilled
if not currentSpeaker[speech_currConvIndex].switchOnly then
speech_Remove = false
speech_finished = false
speech_continue = false
end
end
else
speech_Conv = currentSpeaker[speech_currConvIndex].default
end
if not speech_Conv then
return
end
bb_InitSpeech()
end
function bb_InitSpeech()
speech_curPage = 0
EditCinematic()
Speech_NextPage()
GameCallback_Escape = GameCallback_Escape_OrigSpeech
GameCallback_Escape_OrigSpeech = GameCallback_Escape
GameCallback_Escape = Speech_Continue
end
function Speech_Continue()
if (not speech_Conv[speech_curPage].mc) then
if (not speech_Conv[speech_curPage].nextPageTime) and (not speech_Conv[speech_curPage].voice) then
Speech_NextPage()
end
return true
end
end
function EndSpeech()
-- reselect entities
for i = 1, table.getn(speech_selectedEntities) do
if speech_selectedEntities[1] and (not IsDead(speech_selectedEntities[1])) then
GUI.SelectEntity(speech_selectedEntities[1])
end
table.remove(speech_selectedEntities, 1)
end
-- get finished function
if speech_finished then
if speech_currentSpeaker[1].finished then
Speech_FinishedFunction = speech_currentSpeaker[1].finished
end
if speech_currConvIndex == "MultipleChoice" then
if speech_currentSpeaker[speech_currConvIndex].finished then
Speech_FinishedFunction = speech_currentSpeaker[speech_currConvIndex].finished
end
end
end
-- removing and repeating
if speech_currentSpeaker[speech_currConvIndex].repeatConv then
speech_Remove = not speech_currentSpeaker[speech_currConvIndex].repeatConv()
end
if speech_Remove then
if speech_currConvIndex == "MultipleChoice" then
speech_currentSpeaker[speech_currConvIndex] = nil
local removeAll = true
if speech_currentSpeaker[1].repeatConv then
removeAll = not speech_currentSpeaker[1].repeatConv()
end
if removeAll then
table.remove(speech_currentSpeaker, 1)
end
else
table.remove(speech_currentSpeaker, speech_currConvIndex)
end
end
-- disable npc marker if no conv is stacked
if not speech_currentSpeaker[1] and speech_currentSpeaker.id then
DisableNpcMarker(speech_currentSpeaker.id)
end
-- reset
ResetCinematicMCButtons()
speech_Conv = nil
GameCallback_Escape = GameCallback_Escape_OrigSpeech
bb_SetCinematicMode(0)
Camera.ScrollSetLookAt(speech_camPos[1], speech_camPos[2])
speech_active = false
-- check if finished func is existing
if Speech_FinishedFunction then
Speech_FinishedFunction()
Speech_FinishedFunction = nil
end
-- check if should continue
if speech_continue and speech_currentSpeaker.id then
bb_StartSpeech(speech_currentSpeaker.id)
return
end
-- check if convs are stacked
if speech_convToAdd[1] then
bb_StartSpeech(speech_convToAdd[1].id, speech_convToAdd[1].convIndex)
table.remove(speech_convToAdd, 1)
return
end
end
function Speech_SetupPage()
if speech_Conv[speech_curPage].pos then
Camera.FollowEntity(GetEntityId(speech_Conv[speech_curPage].pos))
end
Camera.RotSetAngle(speech_Conv[speech_curPage].rot or SPEECH_ROTATION)
Camera.ZoomSetDistance(speech_Conv[speech_curPage].zoom or SPEECH_ZOOM)
Camera.ZoomSetAngle(speech_Conv[speech_curPage].angle or SPEECH_ANGLE)
XGUIEng.ShowWidget("Cinematic_Text", 1)
bb_SetCinematicMode(1)
if speech_Conv[speech_curPage].action then
speech_Conv[speech_curPage].action()
end
end
function Speech_NextPage()
speech_curPage = speech_curPage + 1
XGUIEng.ShowWidget("CinematicMC_Button1", 1)
XGUIEng.ShowWidget("CinematicMC_Button2", 0)
if not speech_Conv[speech_curPage] then
EndSpeech()
return true
else
XGUIEng.SetText("Cinematic_Headline", Umlaute(speech_Conv[speech_curPage].title))
XGUIEng.SetText("Cinematic_Text", Umlaute(speech_Conv[speech_curPage].text))
XGUIEng.ShowWidget("CinematicMC_Text", 1)
if speech_Conv[speech_curPage].mc then
Speech_IsWaitingForMCSelection = IsWaitingForMCSelection
IsWaitingForMCSelection = function() return true end
Mouse.CursorShow()
briefingState.waitingForMC = true
ResetCinematicMCButtons()
XGUIEng.ShowWidget("CinematicMC_Button1", 1)
XGUIEng.ShowWidget("CinematicMC_Button2", 1)
XGUIEng.ShowWidget("CinematicMC_Text", 0)
local count = 1
for k, v in pairs(speech_Conv[speech_curPage].mc) do
XGUIEng.SetText("CinematicMC_Button"..count, Umlaute(k))
count = count + 1
end
else
XGUIEng.SetWidgetPositionAndSize("CinematicMC_Button1", 0, 0, 2000, 2000)
XGUIEng.SetText("CinematicMC_Button1", "")
for i = 0, 2 do
XGUIEng.SetMaterialColor("CinematicMC_Button1", i, 255, 255, 255, 0)
end
end
Speech_SetupPage()
if speech_Conv[speech_curPage].voice then
Stream.Start(SPEECH_VOICE_PATH .. speech_Conv[speech_curPage].voice, 127)
XGUIEng.ShowWidget("CinematicMC_Text", 0)
RegisterTimer(math.ceil(Stream.GetDuration() + 1), function() Speech_NextPage(); end)
elseif speech_Conv[speech_curPage].nextPageTime then
XGUIEng.ShowWidget("CinematicMC_Text", 0)
RegisterTimer(speech_Conv[speech_curPage].nextPageTime, function() Speech_NextPage(); end)
end
return false
end
end
function bb_SetCinematicMode(_flag)
if _flag == 1 then
ToggleCinematicBars(1)
XGUIEng.ShowWidget("Cinematic", 1)
XGUIEng.ShowWidget("Cinematic_Text", 1)
XGUIEng.ShowWidget("Cinematic_Headline", 1)
XGUIEng.ShowWidget("Cinematic_Headline", 1)
XGUIEng.ShowWidget("Normal", 0)
XGUIEng.ShowWidget("3dOnScreenDisplay", 0)
GUI.SetFeedbackSoundOutputState(0)
GUIAction_GoBackFromHawkViewInNormalView()
gvCamera.DefaultFlag = 0
Camera.SetControlMode(1)
Camera.InitCameraFlight()
Camera.RotSetFlipBack(0)
Display.SetRenderFogOfWar(0)
GUI.ClearSelection()
GUI.CancelState()
GUI.ActivateCutSceneState()
Display.SetRenderSky( 1 )
else
ToggleCinematicBars(0)
Display.SetRenderFogOfWar(1)
Camera.StopCameraFlight()
Camera.SetControlMode(0)
Camera.RotSetAngle(-45)
Camera.RotSetFlipBack(1)
gvCamera.DefaultFlag = 1
Display.SetRenderSky(0)
GUI.ActivateSelectionState()
GUI.SetFeedbackSoundOutputState(1)
XGUIEng.ShowWidget("Normal", 1)
XGUIEng.ShowWidget("Cinematic", 0)
XGUIEng.ShowWidget("3dOnScreenDisplay", 1)
end
end
--------------------------------------------------------------------
-- SpeechAddon_SpeechIfNear --
--------------------------------------------------------------------
function InitSpeechIfNear()
speechIfNear = {}
speechIfNearLastConv = {}
speechIfNearIdCnt = 0
--[[
newSIF = {
conv = conversation, -- table mit einer conversation
pos = "watchman", -- if near pos then conversation and return
ent = {"fooman", "dario", "kyrill"}, -- table of entities who should return if near
distance = 1000 -- distance in scm, which is controlled
}
]]--
end
function AddSpeechIfNear(_t)
speechIfNearIdCnt = speechIfNearIdCnt + 1
local newSIF = {
conv = _t.conv,
ent = _t.ent
}
if type(_t.pos) == "table" then
newSIF.pos = _t.pos
else
newSIF.pos = GetPosition(_t.pos)
end
newSIF.id = speechIfNearIdCnt
newSIF.distance = _t.distance
table.insert(speechIfNear, newSIF)
if JobIsRunning(speechIfNear_JobId) ~= 1 then
speechIfNear_JobId = StartSimpleJob("ControlSpeechIfNear")
end
return speechIfNearIdCnt
end
function RemoveSpeechIfNear(_id)
for i = 1, table.getn(speechIfNear) do
if speechIfNear[i].id == _id then
table.remove(speechIfNear, i)
return true
end
end
return false
end
function ControlSpeechIfNear()
if not speechIfNear[1] then
return true
end
if not speech_active then
for i = 1, table.getn(speechIfNear) do
for o = 1, table.getn(speechIfNear[i].ent) do
local ePos = GetPosition(speechIfNear[i].ent[o])
local conv = speechIfNear[i].conv
if GetDistance(ePos, speechIfNear[i].pos) < speechIfNear[i].distance then
SpeechIfNear_StopAll()
if type(conv) == "table" then
bb_StartDialog(conv)
else
bb_StartDirectSpeech(conv)
end
end
end
end
end
end
function SpeechIfNear_StopAll()
for i = 1, table.getn(speechIfNear) do
for o = 1, table.getn(speechIfNear[i].ent) do
StopFig(speechIfNear[i].ent[o])
end
end
end