1 /*
2  *  This file is part of Dune Legacy.
3  *
4  *  Dune Legacy is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Dune Legacy is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with Dune Legacy.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <globals.h>
19 
20 #include <CutScenes/Intro.h>
21 #include <CutScenes/WSAVideoEvent.h>
22 #include <CutScenes/HoldPictureVideoEvent.h>
23 #include <CutScenes/FadeOutVideoEvent.h>
24 #include <CutScenes/FadeInVideoEvent.h>
25 #include <CutScenes/CrossBlendVideoEvent.h>
26 #include <CutScenes/TextEvent.h>
27 #include <CutScenes/CutSceneSoundTrigger.h>
28 #include <CutScenes/CutSceneMusicTrigger.h>
29 
30 #include <FileClasses/FileManager.h>
31 #include <FileClasses/TextManager.h>
32 #include <FileClasses/Pakfile.h>
33 #include <FileClasses/Wsafile.h>
34 #include <FileClasses/Vocfile.h>
35 #include <FileClasses/IndexedTextFile.h>
36 
37 #include <misc/sound_util.h>
38 
39 #include <string>
40 
41 const char* Intro::VoiceFileNames[Voice_NUM_ENTRIES] =   {  "BLDING.VOC",
42                                                             "DYNASTY.VOC",
43                                                             "PLANET.VOC",
44                                                             "KNOWN.VOC",
45                                                             "SANDLAND.VOC",
46                                                             "HOME.VOC",
47                                                             "SPICE.VOC",
48                                                             "MELANGE.VOC",
49                                                             "SPICE2.VOC",
50                                                             "CONTROLS.VOC",
51                                                             "EMPIRE.VOC",
52                                                             "WHOEVER.VOC",
53                                                             "CONTROL2.VOC",
54                                                             "CONTROL3.VOC",
55                                                             "KING.VOC",
56                                                             "PROPOSED.VOC",
57                                                             "EACHHOME.VOC",
58                                                             "EHOUSE.VOC",
59                                                             "EPRODUCE.VOC",
60                                                             "EMOST.VOC",
61                                                             "ECONTROL.VOC",
62                                                             "ENOSET.VOC",
63                                                             "ETERRIT.VOC",
64                                                             "EANDNO.VOC",
65                                                             "ERULES.VOC",
66                                                             "VAST.VOC",
67                                                             "ARRIVED.VOC",
68                                                             "ANDNOW.VOC",
69                                                             "3HOUSES.VOC",
70                                                             "CONTROL4.VOC",
71                                                             "OFDUNE.VOC",
72                                                             "NOBLE.VOC",
73                                                             "INSID.VOC",
74                                                             "ORD.VOC",
75                                                             "EVIL.VOC",
76                                                             "HARK.VOC",
77                                                             "HOUSE2.VOC",
78                                                             "PREVAIL.VOC",
79                                                             "YOUR.VOC",
80                                                             "BATTLE.VOC",
81                                                             "BEGINS.VOC",
82                                                             "NOW.VOC"
83                                                         };
84 
Intro()85 Intro::Intro() : CutScene() {
86 
87     SDL_RWops* intro1_wsa = pFileManager->openFile("INTRO1.WSA");
88     pDuneText = new Wsafile(intro1_wsa);
89     SDL_RWclose(intro1_wsa);
90 
91     SDL_RWops* intro2_wsa = pFileManager->openFile("INTRO2.WSA");
92     pPlanet = new Wsafile(intro2_wsa);
93     SDL_RWclose(intro2_wsa);
94 
95     SDL_RWops* intro3_wsa = pFileManager->openFile("INTRO3.WSA");
96     pSandstorm = new Wsafile(intro3_wsa);
97     SDL_RWclose(intro3_wsa);
98 
99     SDL_RWops* intro9_wsa = pFileManager->openFile("INTRO9.WSA");
100     pHarvesters = new Wsafile(intro9_wsa);
101     SDL_RWclose(intro9_wsa);
102 
103     SDL_RWops* intro10_wsa = pFileManager->openFile("INTRO10.WSA");
104     pPalace = new Wsafile(intro10_wsa);
105     SDL_RWclose(intro10_wsa);
106 
107     SDL_RWops* intro11_wsa = pFileManager->openFile("INTRO11.WSA");
108     pImperator = new Wsafile(intro11_wsa);
109     SDL_RWclose(intro11_wsa);
110 
111     SDL_RWops* intro4_wsa = pFileManager->openFile("INTRO4.WSA");
112     pStarport = new Wsafile(intro4_wsa);
113     SDL_RWclose(intro4_wsa);
114 
115     SDL_RWops* intro6_wsa = pFileManager->openFile("INTRO6.WSA");
116     pAtreides = new Wsafile(intro6_wsa);
117     SDL_RWclose(intro6_wsa);
118 
119     SDL_RWops* intro7a_wsa = pFileManager->openFile("INTRO7A.WSA");
120     SDL_RWops* intro7b_wsa = pFileManager->openFile("INTRO7B.WSA");
121     pOrdos = new Wsafile(intro7a_wsa, intro7b_wsa);
122     SDL_RWclose(intro7a_wsa);
123     SDL_RWclose(intro7b_wsa);
124 
125     SDL_RWops* intro8a_wsa = pFileManager->openFile("INTRO8A.WSA");
126     SDL_RWops* intro8b_wsa = pFileManager->openFile("INTRO8B.WSA");
127     SDL_RWops* intro8c_wsa = pFileManager->openFile("INTRO8C.WSA");
128     pHarkonnen = new Wsafile(intro8a_wsa, intro8b_wsa, intro8c_wsa);
129     SDL_RWclose(intro8a_wsa);
130     SDL_RWclose(intro8b_wsa);
131     SDL_RWclose(intro8c_wsa);
132 
133     SDL_RWops* intro5_wsa = pFileManager->openFile("INTRO5.WSA");
134     pDestroyedTank = new Wsafile(intro5_wsa);
135     SDL_RWclose(intro5_wsa);
136 
137     SDL_RWops* intro_lng = pFileManager->openFile("INTRO." + _("LanguageFileExtension"));
138     IndexedTextFile* pIntroText = new IndexedTextFile(intro_lng);
139     SDL_RWclose(intro_lng);
140 
141 
142     wind = getChunkFromFile("WIND2BP.VOC");
143     carryallLanding = getChunkFromFile("CLANK.VOC");
144     harvester = getChunkFromFile("BRAKES2P.VOC");
145 
146     Mix_Chunk* singleGunshot = getChunkFromFile("GUNSHOT.VOC");
147     Mix_Chunk* fourGunshots = concat4Chunks(singleGunshot, singleGunshot, singleGunshot, singleGunshot);
148     Mix_Chunk* thirteenGunshots = concat4Chunks(fourGunshots, fourGunshots, fourGunshots, singleGunshot);
149     gunshot = concat3Chunks(thirteenGunshots, singleGunshot, singleGunshot);
150     Mix_FreeChunk(singleGunshot);
151     Mix_FreeChunk(fourGunshots);
152     Mix_FreeChunk(thirteenGunshots);
153 
154     glass = getChunkFromFile("GLASS.VOC");
155     missle = getChunkFromFile("MISSLE8.VOC");
156     blaster = getChunkFromFile("BLASTER.VOC");
157     blowup1 = getChunkFromFile("BLOWUP1.VOC");
158     blowup2 = getChunkFromFile("BLOWUP2.VOC");
159 
160 
161     bool bEnableVoice = (settings.general.language == "en");
162     if(bEnableVoice == true) {
163         // Load english voice
164         for(int i=0;i<Voice_NUM_ENTRIES;i++) {
165             voice[i] = getChunkFromFile(VoiceFileNames[i]);
166         }
167     } else {
168         for(int i=0;i<Voice_NUM_ENTRIES;i++) {
169             voice[i] = nullptr;
170         }
171     }
172 
173     Uint32 color = SDL2RGB(palette[PALCOLOR_HARKONNEN+1]);
174     Uint32 sardaukarColor = SDL2RGB(palette[PALCOLOR_SARDAUKAR+1]);
175 
176     startNewScene();
177 
178     addVideoEvent(new WSAVideoEvent(pDuneText, false));
179     addVideoEvent(new HoldPictureVideoEvent(pDuneText->getPicture(pDuneText->getNumFrames()-1), 30, true, false));
180     addVideoEvent(new FadeOutVideoEvent(pDuneText->getPicture(pDuneText->getNumFrames()-1), 20, true, false));
181     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_Battle_for_Arrakis),color,48,40,true,true,true));
182     addTextEvent(new TextEvent("The remake is called Dune Legacy!",color,48,40,true));
183     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(52,voice[Voice_The_building]));
184     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(64,voice[Voice_of_a_Dynasty]));
185 
186     startNewScene();
187 
188     addVideoEvent(new FadeInVideoEvent(pPlanet->getPicture(0), 20, true));
189     addVideoEvent(new WSAVideoEvent(pPlanet));
190     addVideoEvent(new HoldPictureVideoEvent(pPlanet->getPicture(pPlanet->getNumFrames()-1), 20, true));
191     addVideoEvent(new FadeOutVideoEvent(pPlanet->getPicture(pPlanet->getNumFrames()-1), 20, true));
192     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_planet_Arrakis),color,20,60,true,true,false));
193     addTrigger(new CutSceneMusicTrigger(25,MUSIC_INTRO));
194     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(25,voice[Voice_The_Planet_Arrakis]));
195     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(38,voice[Voice_Known_As_Dune]));
196 
197     startNewScene();
198 
199     addVideoEvent(new FadeInVideoEvent(pSandstorm->getPicture(0), 20, true));
200     addVideoEvent(new WSAVideoEvent(pSandstorm));
201     addVideoEvent(new HoldPictureVideoEvent(pSandstorm->getPicture(pSandstorm->getNumFrames()-1), 50, true));
202     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Land_of_sand),color,20,40,true,true));
203     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Home_of_the_Spice_Melange),color,61,45,true,true,false));
204     addTrigger(new CutSceneSoundTrigger(25,wind));
205     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(15,voice[Voice_Land_of_sand]));
206     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(70,voice[Voice_Home]));
207     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(78,voice[Voice_of_the_spice]));
208     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(92,voice[Voice_Melange]));
209 
210     startNewScene();
211 
212     addVideoEvent(new CrossBlendVideoEvent(pSandstorm->getPicture(pSandstorm->getNumFrames()-1), pHarvesters->getPicture(0), true));
213     addVideoEvent(new WSAVideoEvent(pHarvesters));
214     addVideoEvent(new HoldPictureVideoEvent(pHarvesters->getPicture(pHarvesters->getNumFrames()-1), 22, true));
215     addVideoEvent(new FadeOutVideoEvent(pHarvesters->getPicture(pHarvesters->getNumFrames()-1), 20, true));
216     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Spice_controls_the_Empire),color,25,40,true,true,false));
217     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Whoever_controls_Dune),color,66,55,true,true,false));
218     addTrigger(new CutSceneSoundTrigger(45,carryallLanding));
219     addTrigger(new CutSceneSoundTrigger(79,harvester));
220     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(40,voice[Voice_The_spice]));
221     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(47,voice[Voice_controls]));
222     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(53,voice[Voice_the_Empire]));
223     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(90,voice[Voice_Whoever]));
224     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(96,voice[Voice_controls_dune]));
225     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(108,voice[Voice_controls_the_spice]));
226 
227     startNewScene();
228 
229     addVideoEvent(new FadeInVideoEvent(pPalace->getPicture(0), 20, true));
230     addVideoEvent(new HoldPictureVideoEvent(pPalace->getPicture(0), 50, true));
231     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_Emperor_has_proposed),color,20,48,true,true,false));
232     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(22,voice[Voice_The_Emperor]));
233     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(31,voice[Voice_has_proposed]));
234     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(49,voice[Voice_to_each_of_the_houses]));
235 
236     startNewScene();
237 
238     addVideoEvent(new WSAVideoEvent(pImperator));
239     addVideoEvent(new HoldPictureVideoEvent(pImperator->getPicture(pImperator->getNumFrames()-1), 30, true));
240     addVideoEvent(new WSAVideoEvent(pImperator));
241     addVideoEvent(new HoldPictureVideoEvent(pImperator->getPicture(pImperator->getNumFrames()-1), 15, true));
242     addVideoEvent(new FadeOutVideoEvent(pImperator->getPicture(pImperator->getNumFrames()-1), 20, true));
243     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_House_that_produces),sardaukarColor,0,52,true,true,false));
244     addTextEvent(new TextEvent(pIntroText->getString(IntroText_There_are_no_set_territories),sardaukarColor,68,30,true,true,false));
245     addTextEvent(new TextEvent(pIntroText->getString(IntroText_And_no_rules_of_engagement),sardaukarColor,99,30,true,true,false));
246     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(8,voice[Voice_The_House]));
247     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(14,voice[Voice_that_produces]));
248     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(20,voice[Voice_the_most_spice]));
249     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(30,voice[Voice_will_control_dune]));
250     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(81,voice[Voice_There_are_no_set]));
251     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(89,voice[Voice_territories]));
252     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(98,voice[Voice_and_no]));
253     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(102,voice[Voice_rules_of_engagment]));
254 
255     startNewScene();
256 
257     addVideoEvent(new FadeInVideoEvent(pStarport->getPicture(0), 20, true));
258     addVideoEvent(new WSAVideoEvent(pStarport));
259     addVideoEvent(new HoldPictureVideoEvent(pStarport->getPicture(pStarport->getNumFrames()-1), 20, true));
260     addVideoEvent(new FadeOutVideoEvent(pStarport->getPicture(pStarport->getNumFrames()-1), 20, true));
261     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Vast_armies_have_arrived),color,25,60,true,true,false));
262     addTrigger(new CutSceneSoundTrigger(57,carryallLanding));
263     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(30,voice[Voice_Vast_armies]));
264     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(37,voice[Voice_have_arrived]));
265 
266     startNewScene();
267 
268     addVideoEvent(new HoldPictureVideoEvent(nullptr, 80, true));
269     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Now_three_houses_fight),color,0,80,true,false,true));
270     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(10,voice[Voice_Now]));
271     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(17,voice[Voice_three_Houses_fight]));
272     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(34,voice[Voice_for_control]));
273     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(46,voice[Voice_of_Dune]));
274 
275     startNewScene();
276 
277     addVideoEvent(new WSAVideoEvent(pAtreides));
278     addVideoEvent(new HoldPictureVideoEvent(pAtreides->getPicture(pAtreides->getNumFrames()-1), 8, true));
279     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_noble_Atreides),color,25,58,true,true,false));
280     addTrigger(new CutSceneSoundTrigger(21,gunshot));
281     addTrigger(new CutSceneSoundTrigger(31,glass));
282     addTrigger(new CutSceneSoundTrigger(32,glass));
283     addTrigger(new CutSceneSoundTrigger(33,glass));
284     addTrigger(new CutSceneSoundTrigger(51,gunshot));
285     addTrigger(new CutSceneSoundTrigger(61,glass));
286     addTrigger(new CutSceneSoundTrigger(62,glass));
287     addTrigger(new CutSceneSoundTrigger(63,glass));
288     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(36,voice[Voice_The_noble_Atreides]));
289 
290 
291     startNewScene();
292 
293     addVideoEvent(new WSAVideoEvent(pOrdos));
294     addTextEvent(new TextEvent(pIntroText->getString(IntroText_The_insidious_Ordos),color,-2,47,true,true,false));
295     addTrigger(new CutSceneSoundTrigger(3,missle));
296     addTrigger(new CutSceneSoundTrigger(8,missle));
297     addTrigger(new CutSceneSoundTrigger(28,missle));
298     addTrigger(new CutSceneSoundTrigger(38,missle));
299     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(12,voice[Voice_The_insidious]));
300     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(20,voice[Voice_Ordos]));
301 
302     startNewScene();
303 
304     addVideoEvent(new WSAVideoEvent(pHarkonnen));
305     addVideoEvent(new FadeOutVideoEvent(pHarkonnen->getPicture(pHarkonnen->getNumFrames()-1), 15, true, true ,true));
306     addTextEvent(new TextEvent(pIntroText->getString(IntroText_And_the_evil_Harkonnen),color,-2,45,true,true,false));
307     addTrigger(new CutSceneSoundTrigger(0,gunshot));
308     addTrigger(new CutSceneSoundTrigger(5,blaster));
309     addTrigger(new CutSceneSoundTrigger(7,blaster));
310     addTrigger(new CutSceneSoundTrigger(17,gunshot));
311     addTrigger(new CutSceneSoundTrigger(21,blaster));
312     addTrigger(new CutSceneSoundTrigger(28,gunshot));
313     addTrigger(new CutSceneSoundTrigger(37,gunshot));
314     addTrigger(new CutSceneSoundTrigger(50,blowup1));
315     addTrigger(new CutSceneSoundTrigger(60,blowup2));
316     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(4,voice[Voice_And_the]));
317     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(10,voice[Voice_evil_Harkonnen]));
318 
319     startNewScene();
320 
321     addVideoEvent(new FadeInVideoEvent(pDestroyedTank->getPicture(0), 15, true, true ,true));
322     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
323     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
324     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
325     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
326     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
327     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
328     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
329     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
330     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
331     addVideoEvent(new WSAVideoEvent(pDestroyedTank));
332     addVideoEvent(new FadeOutVideoEvent(pDestroyedTank->getPicture(pDestroyedTank->getNumFrames()-1), 15, true));
333     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Only_one_House_will_prevail),color,18,35,true,true,false));
334     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(21,voice[Voice_Only_one_house]));
335     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(30,voice[Voice_will_prevail]));
336 
337     startNewScene();
338 
339     addVideoEvent(new HoldPictureVideoEvent(nullptr, 184, true));
340     addTextEvent(new TextEvent(pIntroText->getString(IntroText_Your_battle_for_Dune_begins),color,20,45,true,false,true));
341     addTextEvent(new TextEvent(pIntroText->getString(IntroText_NOW),color,68,83,false,true,true));
342 //    addTextEvent(new TextEvent("",COLOR_BLACK,115,10,false,false,true));    // padding to give music time to complete
343     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(30,voice[Voice_Your]));
344     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(36,voice[Voice_battle_for_Dune]));
345     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(48,voice[Voice_begins]));
346     if(bEnableVoice) addTrigger(new CutSceneSoundTrigger(68,voice[Voice_Now_Now]));
347 
348     delete pIntroText;
349 }
350 
~Intro()351 Intro::~Intro() {
352     delete pDuneText;
353     delete pPlanet;
354     delete pSandstorm;
355     delete pHarvesters;
356     delete pPalace;
357     delete pImperator;
358     delete pStarport;
359     delete pOrdos;
360     delete pAtreides;
361     delete pHarkonnen;
362     delete pDestroyedTank;
363 
364     Mix_FreeChunk(wind);
365     Mix_FreeChunk(carryallLanding);
366     Mix_FreeChunk(harvester);
367     Mix_FreeChunk(gunshot);
368     Mix_FreeChunk(glass);
369     Mix_FreeChunk(missle);
370     Mix_FreeChunk(blaster);
371     Mix_FreeChunk(blowup1);
372     Mix_FreeChunk(blowup2);
373 
374     // Free english voice
375     for(int i=0;i<Voice_NUM_ENTRIES;i++) {
376         Mix_FreeChunk(voice[i]);
377     }
378 }
379