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 <FileClasses/TextManager.h>
19 
20 #include <globals.h>
21 
22 #include <misc/string_util.h>
23 
24 #include <FileClasses/FileManager.h>
25 #include <FileClasses/POFile.h>
26 
27 #include <misc/FileSystem.h>
28 #include <misc/exceptions.h>
29 
30 #include <config.h>
31 
32 #ifdef _
33 #undef _
34 #endif
35 #define _(msgid) getLocalized(msgid)
36 
TextManager()37 TextManager::TextManager() {
38     std::list<std::string> languagesList = getFileNamesList(getDuneLegacyDataDir() + "/locale", settings.general.language + ".po", true, FileListOrder_Name_Asc);
39 
40     if(languagesList.empty()) {
41         std::string filepath = getDuneLegacyDataDir() + "/locale/English.en.po";
42         SDL_Log("Loading localization from '%s'...", filepath.c_str());
43         localizedString = loadPOFile(SDL_RWFromFile(filepath.c_str(), "r"), true, "English.en.po");
44     } else {
45         std::string filepath = getDuneLegacyDataDir() + "/locale/" + languagesList.front();
46         SDL_Log("Loading localization from '%s'...", filepath.c_str());
47         localizedString = loadPOFile(SDL_RWFromFile(filepath.c_str(), "r"), true, languagesList.front());
48     }
49 }
50 
~TextManager()51 TextManager::~TextManager() {
52 }
53 
loadData()54 void TextManager::loadData() {
55     addOrigDuneText("TEXTH." + _("LanguageFileExtension"), true);
56     addOrigDuneText("TEXTA." + _("LanguageFileExtension"), true);
57     addOrigDuneText("TEXTO." + _("LanguageFileExtension"), true);
58     addOrigDuneText("DUNE." + _("LanguageFileExtension"));
59     addOrigDuneText("MESSAGE." + _("LanguageFileExtension"));
60 
61     // load all mentat texts
62     SDL_RWops* mentat_lng[3];
63     mentat_lng[HOUSE_HARKONNEN] = pFileManager->openFile("MENTATH." + _("LanguageFileExtension"));
64     mentat_lng[HOUSE_ATREIDES] = pFileManager->openFile("MENTATA." + _("LanguageFileExtension"));
65     mentat_lng[HOUSE_ORDOS] = pFileManager->openFile("MENTATO." + _("LanguageFileExtension"));
66 
67     for(int i=0;i<3;i++) {
68         mentatStrings[i] = std::shared_ptr<MentatTextFile>(new MentatTextFile(mentat_lng[i]));
69         SDL_RWclose(mentat_lng[i]);
70     }
71 }
72 
getBriefingText(unsigned int mission,unsigned int texttype,int house) const73 std::string TextManager::getBriefingText(unsigned int mission, unsigned int texttype, int house) const {
74     switch(house) {
75         case HOUSE_HARKONNEN: {
76             switch(texttype) {
77                 case MISSION_DESCRIPTION: {
78                     switch(mission) {
79                         case 0: return _("@TEXTH.ENG|0#Description of House Harkonnen");       break;
80                         case 1: return _("@TEXTH.ENG|4#Description of Harkonnen mission 1");   break;
81                         case 2: return _("@TEXTH.ENG|8#Description of Harkonnen mission 2");   break;
82                         case 3: return _("@TEXTH.ENG|12#Description of Harkonnen mission 3");  break;
83                         case 4: return _("@TEXTH.ENG|16#Description of Harkonnen mission 4");  break;
84                         case 5: return _("@TEXTH.ENG|20#Description of Harkonnen mission 5");  break;
85                         case 6: return _("@TEXTH.ENG|24#Description of Harkonnen mission 6");  break;
86                         case 7: return _("@TEXTH.ENG|28#Description of Harkonnen mission 7");  break;
87                         case 8: return _("@TEXTH.ENG|32#Description of Harkonnen mission 8");  break;
88                         case 9: return _("@TEXTH.ENG|36#Description of Harkonnen mission 9");  break;
89                         default: return "";                                                    break;
90                     }
91                 } break;
92 
93                 case MISSION_WIN: {
94                     switch(mission) {
95                         case 1: return _("@TEXTH.ENG|5#Winning text of Harkonnen mission 1");   break;
96                         case 2: return _("@TEXTH.ENG|9#Winning text of Harkonnen mission 2");   break;
97                         case 3: return _("@TEXTH.ENG|13#Winning text of Harkonnen mission 3");  break;
98                         case 4: return _("@TEXTH.ENG|17#Winning text of Harkonnen mission 4");  break;
99                         case 5: return _("@TEXTH.ENG|21#Winning text of Harkonnen mission 5");  break;
100                         case 6: return _("@TEXTH.ENG|25#Winning text of Harkonnen mission 6");  break;
101                         case 7: return _("@TEXTH.ENG|29#Winning text of Harkonnen mission 7");  break;
102                         case 8: return _("@TEXTH.ENG|33#Winning text of Harkonnen mission 8");  break;
103                         case 9: return _("@TEXTH.ENG|37#Winning text of Harkonnen mission 9");  break;
104                         default: return "";                                                     break;
105                     }
106                 } break;
107 
108                 case MISSION_LOSE: {
109                     switch(mission) {
110                         case 1: return _("@TEXTH.ENG|6#Losing text of Harkonnen mission 1");   break;
111                         case 2: return _("@TEXTH.ENG|10#Losing text of Harkonnen mission 2");  break;
112                         case 3: return _("@TEXTH.ENG|14#Losing text of Harkonnen mission 3");  break;
113                         case 4: return _("@TEXTH.ENG|18#Losing text of Harkonnen mission 4");  break;
114                         case 5: return _("@TEXTH.ENG|22#Losing text of Harkonnen mission 5");  break;
115                         case 6: return _("@TEXTH.ENG|26#Losing text of Harkonnen mission 6");  break;
116                         case 7: return _("@TEXTH.ENG|30#Losing text of Harkonnen mission 7");  break;
117                         case 8: return _("@TEXTH.ENG|34#Losing text of Harkonnen mission 8");  break;
118                         case 9: return _("@TEXTH.ENG|38#Losing text of Harkonnen mission 9");  break;
119                         default: return "";                                                    break;
120                     }
121                 } break;
122 
123                 case MISSION_ADVICE: {
124                     switch(mission) {
125                         case 1: return _("@TEXTH.ENG|7#Advice text for Harkonnen mission 1");   break;
126                         case 2: return _("@TEXTH.ENG|11#Advice text for Harkonnen mission 2");  break;
127                         case 3: return _("@TEXTH.ENG|15#Advice text for Harkonnen mission 3");  break;
128                         case 4: return _("@TEXTH.ENG|19#Advice text for Harkonnen mission 4");  break;
129                         case 5: return _("@TEXTH.ENG|23#Advice text for Harkonnen mission 5");  break;
130                         case 6: return _("@TEXTH.ENG|27#Advice text for Harkonnen mission 6");  break;
131                         case 7: return _("@TEXTH.ENG|31#Advice text for Harkonnen mission 7");  break;
132                         case 8: return _("@TEXTH.ENG|35#Advice text for Harkonnen mission 8");  break;
133                         case 9: return _("@TEXTH.ENG|39#Advice text for Harkonnen mission 9");  break;
134                         default: return "";                                                     break;
135                     }
136                 } break;
137 
138                 default: {
139                     return "";
140                 } break;
141             }
142         } break;
143 
144         case HOUSE_ATREIDES: {
145             switch(texttype) {
146                 case MISSION_DESCRIPTION: {
147                     switch(mission) {
148                         case 0: return _("@TEXTA.ENG|0#Description of House Atreides");       break;
149                         case 1: return _("@TEXTA.ENG|4#Description of Atreides mission 1");   break;
150                         case 2: return _("@TEXTA.ENG|8#Description of Atreides mission 2");   break;
151                         case 3: return _("@TEXTA.ENG|12#Description of Atreides mission 3");  break;
152                         case 4: return _("@TEXTA.ENG|16#Description of Atreides mission 4");  break;
153                         case 5: return _("@TEXTA.ENG|20#Description of Atreides mission 5");  break;
154                         case 6: return _("@TEXTA.ENG|24#Description of Atreides mission 6");  break;
155                         case 7: return _("@TEXTA.ENG|28#Description of Atreides mission 7");  break;
156                         case 8: return _("@TEXTA.ENG|32#Description of Atreides mission 8");  break;
157                         case 9: return _("@TEXTA.ENG|36#Description of Atreides mission 9");  break;
158                         default: return "";                                                   break;
159                     }
160                 } break;
161 
162                 case MISSION_WIN: {
163                     switch(mission) {
164                         case 1: return _("@TEXTA.ENG|5#Winning text of Atreides mission 1");   break;
165                         case 2: return _("@TEXTA.ENG|9#Winning text of Atreides mission 2");   break;
166                         case 3: return _("@TEXTA.ENG|13#Winning text of Atreides mission 3");  break;
167                         case 4: return _("@TEXTA.ENG|17#Winning text of Atreides mission 4");  break;
168                         case 5: return _("@TEXTA.ENG|21#Winning text of Atreides mission 5");  break;
169                         case 6: return _("@TEXTA.ENG|25#Winning text of Atreides mission 6");  break;
170                         case 7: return _("@TEXTA.ENG|29#Winning text of Atreides mission 7");  break;
171                         case 8: return _("@TEXTA.ENG|33#Winning text of Atreides mission 8");  break;
172                         case 9: return _("@TEXTA.ENG|37#Winning text of Atreides mission 9");  break;
173                         default: return "";                                                    break;
174                     }
175                 } break;
176 
177                 case MISSION_LOSE: {
178                     switch(mission) {
179                         case 1: return _("@TEXTA.ENG|6#Losing text of Atreides mission 1");   break;
180                         case 2: return _("@TEXTA.ENG|10#Losing text of Atreides mission 2");  break;
181                         case 3: return _("@TEXTA.ENG|14#Losing text of Atreides mission 3");  break;
182                         case 4: return _("@TEXTA.ENG|18#Losing text of Atreides mission 4");  break;
183                         case 5: return _("@TEXTA.ENG|22#Losing text of Atreides mission 5");  break;
184                         case 6: return _("@TEXTA.ENG|26#Losing text of Atreides mission 6");  break;
185                         case 7: return _("@TEXTA.ENG|30#Losing text of Atreides mission 7");  break;
186                         case 8: return _("@TEXTA.ENG|34#Losing text of Atreides mission 8");  break;
187                         case 9: return _("@TEXTA.ENG|38#Losing text of Atreides mission 9");  break;
188                         default: return "";                                                   break;
189                     }
190                 } break;
191 
192                 case MISSION_ADVICE: {
193                     switch(mission) {
194                         case 1: return _("@TEXTA.ENG|7#Advice text for Atreides mission 1");   break;
195                         case 2: return _("@TEXTA.ENG|11#Advice text for Atreides mission 2");  break;
196                         case 3: return _("@TEXTA.ENG|15#Advice text for Atreides mission 3");  break;
197                         case 4: return _("@TEXTA.ENG|19#Advice text for Atreides mission 4");  break;
198                         case 5: return _("@TEXTA.ENG|23#Advice text for Atreides mission 5");  break;
199                         case 6: return _("@TEXTA.ENG|27#Advice text for Atreides mission 6");  break;
200                         case 7: return _("@TEXTA.ENG|31#Advice text for Atreides mission 7");  break;
201                         case 8: return _("@TEXTA.ENG|35#Advice text for Atreides mission 8");  break;
202                         case 9: return _("@TEXTA.ENG|39#Advice text for Atreides mission 9");  break;
203                         default: return "";                                                    break;
204                     }
205                 } break;
206 
207                 default: {
208                     return "";
209                 } break;
210             }
211         } break;
212 
213         case HOUSE_ORDOS: {
214             switch(texttype) {
215                 case MISSION_DESCRIPTION: {
216                     switch(mission) {
217                         case 0: return _("@TEXTO.ENG|0#Description of House Ordos");       break;
218                         case 1: return _("@TEXTO.ENG|4#Description of Ordos mission 1");   break;
219                         case 2: return _("@TEXTO.ENG|8#Description of Ordos mission 2");   break;
220                         case 3: return _("@TEXTO.ENG|12#Description of Ordos mission 3");  break;
221                         case 4: return _("@TEXTO.ENG|16#Description of Ordos mission 4");  break;
222                         case 5: return _("@TEXTO.ENG|20#Description of Ordos mission 5");  break;
223                         case 6: return _("@TEXTO.ENG|24#Description of Ordos mission 6");  break;
224                         case 7: return _("@TEXTO.ENG|28#Description of Ordos mission 7");  break;
225                         case 8: return _("@TEXTO.ENG|32#Description of Ordos mission 8");  break;
226                         case 9: return _("@TEXTO.ENG|36#Description of Ordos mission 9");  break;
227                         default: return "";                                                break;
228                     }
229                 } break;
230 
231                 case MISSION_WIN: {
232                     switch(mission) {
233                         case 1: return _("@TEXTO.ENG|5#Winning text of Ordos mission 1");   break;
234                         case 2: return _("@TEXTO.ENG|9#Winning text of Ordos mission 2");   break;
235                         case 3: return _("@TEXTO.ENG|13#Winning text of Ordos mission 3");  break;
236                         case 4: return _("@TEXTO.ENG|17#Winning text of Ordos mission 4");  break;
237                         case 5: return _("@TEXTO.ENG|21#Winning text of Ordos mission 5");  break;
238                         case 6: return _("@TEXTO.ENG|25#Winning text of Ordos mission 6");  break;
239                         case 7: return _("@TEXTO.ENG|29#Winning text of Ordos mission 7");  break;
240                         case 8: return _("@TEXTO.ENG|33#Winning text of Ordos mission 8");  break;
241                         case 9: return _("@TEXTO.ENG|37#Winning text of Ordos mission 9");  break;
242                         default: return "";                                                 break;
243                     }
244                 } break;
245 
246                 case MISSION_LOSE: {
247                     switch(mission) {
248                         case 1: return _("@TEXTO.ENG|6#Losing text of Ordos mission 1");   break;
249                         case 2: return _("@TEXTO.ENG|10#Losing text of Ordos mission 2");  break;
250                         case 3: return _("@TEXTO.ENG|14#Losing text of Ordos mission 3");  break;
251                         case 4: return _("@TEXTO.ENG|18#Losing text of Ordos mission 4");  break;
252                         case 5: return _("@TEXTO.ENG|22#Losing text of Ordos mission 5");  break;
253                         case 6: return _("@TEXTO.ENG|26#Losing text of Ordos mission 6");  break;
254                         case 7: return _("@TEXTO.ENG|30#Losing text of Ordos mission 7");  break;
255                         case 8: return _("@TEXTO.ENG|34#Losing text of Ordos mission 8");  break;
256                         case 9: return _("@TEXTO.ENG|38#Losing text of Ordos mission 9");  break;
257                         default: return "";                                                break;
258                     }
259                 } break;
260 
261                 case MISSION_ADVICE: {
262                     switch(mission) {
263                         case 1: return _("@TEXTO.ENG|7#Advice text for Ordos mission 1");   break;
264                         case 2: return _("@TEXTO.ENG|11#Advice text for Ordos mission 2");  break;
265                         case 3: return _("@TEXTO.ENG|15#Advice text for Ordos mission 3");  break;
266                         case 4: return _("@TEXTO.ENG|19#Advice text for Ordos mission 4");  break;
267                         case 5: return _("@TEXTO.ENG|23#Advice text for Ordos mission 5");  break;
268                         case 6: return _("@TEXTO.ENG|27#Advice text for Ordos mission 6");  break;
269                         case 7: return _("@TEXTO.ENG|31#Advice text for Ordos mission 7");  break;
270                         case 8: return _("@TEXTO.ENG|35#Advice text for Ordos mission 8");  break;
271                         case 9: return _("@TEXTO.ENG|39#Advice text for Ordos mission 9");  break;
272                         default: return "";                                                 break;
273                     }
274                 } break;
275 
276                 default: {
277                     return "";
278                 } break;
279             }
280         } break;
281 
282         case HOUSE_FREMEN: {
283             switch(texttype) {
284                 case MISSION_DESCRIPTION: {
285                     switch(mission) {
286                         case 0: return _("House Fremen\nArrakis, the home planet of House Fremen, is one giant sand desert. Perfectly adapted to the warm, dry climate, the Fremen have huge advantage in defending their planet.");       break;
287                         case 1: return _("@TEXTA.ENG|4|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 1");   break;
288                         case 2: return _("@TEXTA.ENG|8|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 2");   break;
289                         case 3: return _("@TEXTA.ENG|12|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 3");  break;
290                         case 4: return _("@TEXTA.ENG|16|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 4");  break;
291                         case 5: return _("@TEXTA.ENG|20|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 5");  break;
292                         case 6: return _("@TEXTA.ENG|24|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 6");  break;
293                         case 7: return _("@TEXTA.ENG|28|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 7");  break;
294                         case 8: return _("@TEXTA.ENG|32|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Description of Fremen mission 8");  break;
295                         case 9: return _("@TEXTA.ENG|36|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary|remaining Ordos and Harkonnen troops->remaining Ordos, Mercenary and Harkonnen troops#Description of Fremen mission 9");  break;
296                         default: return "";                                                   break;
297                     }
298                 } break;
299 
300                 case MISSION_WIN: {
301                     switch(mission) {
302                         case 1: return _("@TEXTA.ENG|5|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 1");   break;
303                         case 2: return _("@TEXTA.ENG|9|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 2");   break;
304                         case 3: return _("@TEXTA.ENG|13|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 3");  break;
305                         case 4: return _("@TEXTA.ENG|17|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 4");  break;
306                         case 5: return _("@TEXTA.ENG|21|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 5");  break;
307                         case 6: return _("@TEXTA.ENG|25|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 6");  break;
308                         case 7: return _("@TEXTA.ENG|29|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 7");  break;
309                         case 8: return _("@TEXTA.ENG|33|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 8");  break;
310                         case 9: return _("@TEXTA.ENG|37|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Winning text of Fremen mission 9");  break;
311                         default: return "";                                                    break;
312                     }
313                 } break;
314 
315                 case MISSION_LOSE: {
316                     switch(mission) {
317                         case 1: return _("@TEXTA.ENG|6|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 1");   break;
318                         case 2: return _("@TEXTA.ENG|10|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 2");  break;
319                         case 3: return _("@TEXTA.ENG|14|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 3");  break;
320                         case 4: return _("@TEXTA.ENG|18|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 4");  break;
321                         case 5: return _("@TEXTA.ENG|22|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 5");  break;
322                         case 6: return _("@TEXTA.ENG|26|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 6");  break;
323                         case 7: return _("@TEXTA.ENG|30|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 7");  break;
324                         case 8: return _("@TEXTA.ENG|34|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 8");  break;
325                         case 9: return _("@TEXTA.ENG|38|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Losing text of Fremen mission 9");  break;
326                         default: return "";                                                   break;
327                     }
328                 } break;
329 
330                 case MISSION_ADVICE: {
331                     switch(mission) {
332                         case 1: return _("@TEXTA.ENG|7|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 1");   break;
333                         case 2: return _("@TEXTA.ENG|11|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 2");  break;
334                         case 3: return _("@TEXTA.ENG|15|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 3");  break;
335                         case 4: return _("@TEXTA.ENG|19|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 4");  break;
336                         case 5: return _("@TEXTA.ENG|23|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 5");  break;
337                         case 6: return _("@TEXTA.ENG|27|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 6");  break;
338                         case 7: return _("@TEXTA.ENG|31|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 7");  break;
339                         case 8: return _("@TEXTA.ENG|35|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 8");  break;
340                         case 9: return _("@TEXTA.ENG|39|Atreides->Fremen|Ordos->Sardaukar|Harkonnen->Mercenary#Advice text for Fremen mission 9");  break;
341                         default: return "";                                                    break;
342                     }
343                 } break;
344 
345                 default: {
346                     return "";
347                 } break;
348             }
349         } break;
350 
351         case HOUSE_SARDAUKAR: {
352             switch(texttype) {
353                 case MISSION_DESCRIPTION: {
354                     switch(mission) {
355                         case 0: return _("House Sardaukar\nOriginating from an forgotten planet, House Sardaukar has moved from planet to planet since then. Conquering foreign planets has specialized their combat skills which got them a reputation of being cruel.");  break;
356                         case 1: return _("@TEXTH.ENG|4|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 1");   break;
357                         case 2: return _("@TEXTH.ENG|8|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 2");   break;
358                         case 3: return _("@TEXTH.ENG|12|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 3");  break;
359                         case 4: return _("@TEXTH.ENG|16|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 4");  break;
360                         case 5: return _("@TEXTH.ENG|20|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar|the Emperor was->the Atreides were#Description of Sardaukar mission 5");  break;
361                         case 6: return _("@TEXTH.ENG|24|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 6");  break;
362                         case 7: return _("@TEXTH.ENG|28|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 7");  break;
363                         case 8: return _("@TEXTH.ENG|32|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Description of Sardaukar mission 8");  break;
364                         case 9: return _("@TEXTH.ENG|36|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar|the Emperor's->their leader's#Description of Sardaukar mission 9");  break;
365                         default: return "";                                                    break;
366                     }
367                 } break;
368 
369                 case MISSION_WIN: {
370                     switch(mission) {
371                         case 1: return _("@TEXTH.ENG|5|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 1");   break;
372                         case 2: return _("@TEXTH.ENG|9|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 2");   break;
373                         case 3: return _("@TEXTH.ENG|13|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 3");  break;
374                         case 4: return _("@TEXTH.ENG|17|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 4");  break;
375                         case 5: return _("@TEXTH.ENG|21|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 5");  break;
376                         case 6: return _("@TEXTH.ENG|25|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 6");  break;
377                         case 7: return _("@TEXTH.ENG|29|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 7");  break;
378                         case 8: return _("@TEXTH.ENG|33|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Winning text of Sardaukar mission 8");  break;
379                         case 9: return _("@TEXTH.ENG|37|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar|the Emperor->the leader#Winning text of Sardaukar mission 9");  break;
380                         default: return "";                                                     break;
381                     }
382                 } break;
383 
384                 case MISSION_LOSE: {
385                     switch(mission) {
386                         case 1: return _("@TEXTH.ENG|6|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 1");   break;
387                         case 2: return _("@TEXTH.ENG|10|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 2");  break;
388                         case 3: return _("@TEXTH.ENG|14|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 3");  break;
389                         case 4: return _("@TEXTH.ENG|18|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 4");  break;
390                         case 5: return _("@TEXTH.ENG|22|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 5");  break;
391                         case 6: return _("@TEXTH.ENG|26|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 6");  break;
392                         case 7: return _("@TEXTH.ENG|30|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 7");  break;
393                         case 8: return _("@TEXTH.ENG|34|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 8");  break;
394                         case 9: return _("@TEXTH.ENG|38|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Losing text of Sardaukar mission 9");  break;
395                         default: return "";                                                    break;
396                     }
397                 } break;
398 
399                 case MISSION_ADVICE: {
400                     switch(mission) {
401                         case 1: return _("@TEXTH.ENG|7|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 1");   break;
402                         case 2: return _("@TEXTH.ENG|11|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 2");  break;
403                         case 3: return _("@TEXTH.ENG|15|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 3");  break;
404                         case 4: return _("@TEXTH.ENG|19|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 4");  break;
405                         case 5: return _("@TEXTH.ENG|23|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 5");  break;
406                         case 6: return _("@TEXTH.ENG|27|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 6");  break;
407                         case 7: return _("@TEXTH.ENG|31|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 7");  break;
408                         case 8: return _("@TEXTH.ENG|35|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 8");  break;
409                         case 9: return _("@TEXTH.ENG|39|Atreides->Mercenary|Ordos->Fremen|Harkonnen->Sardaukar#Advice text for Sardaukar mission 9");  break;
410                         default: return "";                                                     break;
411                     }
412                 } break;
413 
414                 default: {
415                     return "";
416                 } break;
417             }
418         } break;
419 
420         case HOUSE_MERCENARY:
421         default: {
422             switch(texttype) {
423                 case MISSION_DESCRIPTION: {
424                     switch(mission) {
425                         case 0: return _("House Mercenary\nThe home planet of the Mercenary consists of huge oceans and large deserts. House Mercenary is one of the oldest and most influencial intergalactical trading organization. To strengthen their power they don't hesitate to use military force.");       break;
426                         case 1: return _("@TEXTO.ENG|4|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 1");   break;
427                         case 2: return _("@TEXTO.ENG|8|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 2");   break;
428                         case 3: return _("@TEXTO.ENG|12|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 3");  break;
429                         case 4: return _("@TEXTO.ENG|16|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 4");  break;
430                         case 5: return _("@TEXTO.ENG|20|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 5");  break;
431                         case 6: return _("@TEXTO.ENG|24|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 6");  break;
432                         case 7: return _("@TEXTO.ENG|28|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 7");  break;
433                         case 8: return _("@TEXTO.ENG|32|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 8");  break;
434                         case 9: return _("@TEXTO.ENG|36|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Description of Mercenary mission 9");  break;
435                         default: return "";                                                break;
436                     }
437                 } break;
438 
439                 case MISSION_WIN: {
440                     switch(mission) {
441                         case 1: return _("@TEXTO.ENG|5|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 1");   break;
442                         case 2: return _("@TEXTO.ENG|9|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 2");   break;
443                         case 3: return _("@TEXTO.ENG|13|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 3");  break;
444                         case 4: return _("@TEXTO.ENG|17|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 4");  break;
445                         case 5: return _("@TEXTO.ENG|21|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 5");  break;
446                         case 6: return _("@TEXTO.ENG|25|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 6");  break;
447                         case 7: return _("@TEXTO.ENG|29|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 7");  break;
448                         case 8: return _("@TEXTO.ENG|33|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 8");  break;
449                         case 9: return _("@TEXTO.ENG|37|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Winning text of Mercenary mission 9");  break;
450                         default: return "";                                                 break;
451                     }
452                 } break;
453 
454                 case MISSION_LOSE: {
455                     switch(mission) {
456                         case 1: return _("@TEXTO.ENG|6|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 1");   break;
457                         case 2: return _("@TEXTO.ENG|10|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 2");  break;
458                         case 3: return _("@TEXTO.ENG|14|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 3");  break;
459                         case 4: return _("@TEXTO.ENG|18|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 4");  break;
460                         case 5: return _("@TEXTO.ENG|22|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 5");  break;
461                         case 6: return _("@TEXTO.ENG|26|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 6");  break;
462                         case 7: return _("@TEXTO.ENG|30|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 7");  break;
463                         case 8: return _("@TEXTO.ENG|34|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 8");  break;
464                         case 9: return _("@TEXTO.ENG|38|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Losing text of Mercenary mission 9");  break;
465                         default: return "";                                                break;
466                     }
467                 } break;
468 
469                 case MISSION_ADVICE: {
470                     switch(mission) {
471                         case 1: return _("@TEXTO.ENG|7|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 1");   break;
472                         case 2: return _("@TEXTO.ENG|11|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 2");  break;
473                         case 3: return _("@TEXTO.ENG|15|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 3");  break;
474                         case 4: return _("@TEXTO.ENG|19|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 4");  break;
475                         case 5: return _("@TEXTO.ENG|23|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 5");  break;
476                         case 6: return _("@TEXTO.ENG|27|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 6");  break;
477                         case 7: return _("@TEXTO.ENG|31|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 7");  break;
478                         case 8: return _("@TEXTO.ENG|35|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 8");  break;
479                         case 9: return _("@TEXTO.ENG|39|Atreides->Sardaukar|Ordos->Mercenary|Harkonnen->Fremen#Advice text for Mercenary mission 9");  break;
480                         default: return "";                                                 break;
481                     }
482                 } break;
483 
484                 default: {
485                     return "";
486                 } break;
487             }
488 
489         } break;
490 
491     }
492 }
493 
getAllMentatEntries(int house,unsigned int techLevel) const494 std::vector<MentatTextFile::MentatEntry> TextManager::getAllMentatEntries(int house, unsigned int techLevel) const {
495     std::vector<MentatTextFile::MentatEntry> mentatEntries;
496 
497     switch(house) {
498         case HOUSE_HARKONNEN:
499         case HOUSE_SARDAUKAR:
500         default: {
501             for(unsigned int i = 0; i <  mentatStrings[HOUSE_HARKONNEN]->getNumEntries(); i++) {
502                 if(mentatStrings[HOUSE_HARKONNEN]->getMentatEntry(i).techLevel <= techLevel) {
503                     mentatEntries.push_back(mentatStrings[HOUSE_HARKONNEN]->getMentatEntry(i));
504                 }
505             }
506         } break;
507 
508         case HOUSE_ATREIDES:
509         case HOUSE_FREMEN: {
510             for(unsigned int i = 0; i <  mentatStrings[HOUSE_ATREIDES]->getNumEntries(); i++) {
511                 if(mentatStrings[HOUSE_ATREIDES]->getMentatEntry(i).techLevel <= techLevel) {
512                     mentatEntries.push_back(mentatStrings[HOUSE_ATREIDES]->getMentatEntry(i));
513                 }
514             }
515         } break;
516 
517         case HOUSE_ORDOS:
518         case HOUSE_MERCENARY: {
519             for(unsigned int i = 0; i <  mentatStrings[HOUSE_ORDOS]->getNumEntries(); i++) {
520                 if(mentatStrings[HOUSE_ORDOS]->getMentatEntry(i).techLevel <= techLevel) {
521                     mentatEntries.push_back(mentatStrings[HOUSE_ORDOS]->getMentatEntry(i));
522                 }
523             }
524         } break;
525     }
526 
527     return mentatEntries;
528 }
529 
530 
postProcessString(const std::string & unprocessedString) const531 const std::string& TextManager::postProcessString(const std::string& unprocessedString) const {
532     size_t commentStart = unprocessedString.find_first_of('#');
533     if(commentStart == std::string::npos) {
534         commentStart = unprocessedString.size();
535     }
536 
537 
538     std::string commandString = unprocessedString.substr(1, commentStart-1);
539 
540     std::vector<std::string> commands = splitString(commandString, "|", false);
541 
542     int index = -1;
543     if(commands.size() < 2 || !parseString(commands[1], index)) {
544         return unprocessedString;
545     } else {
546         std::map<std::string,std::shared_ptr<IndexedTextFile> >::const_iterator iter = origDuneText.find(commands[0]);
547         if(iter != origDuneText.end()) {
548             std::shared_ptr<IndexedTextFile> pIndexedTextFile = iter->second;
549 
550             if(commands[0].compare(0,5,"DUNE.") && (index >= 281) && pIndexedTextFile->getNumStrings() == 335) {
551                 // Dune II 1.0 has 2 titles less
552                 index = std::max((int) 281, index - 2);
553             }
554 
555 
556             std::map<std::string, std::string> mapping;
557             for(unsigned int i=2;i<commands.size();i++) {
558                 std::vector<std::string> parts = splitString(commands[i], "->");
559                 mapping[parts[0]] = parts[1];
560             }
561 
562             localizedString[unprocessedString] = replaceAll(pIndexedTextFile->getString(index), mapping);
563 
564             return localizedString[unprocessedString];
565         } else {
566             return unprocessedString;
567         }
568 
569         return unprocessedString;
570     }
571 }
572 
addOrigDuneText(const std::string & filename,bool bDecode)573 void TextManager::addOrigDuneText(const std::string& filename, bool bDecode) {
574     SDL_RWops* rwop = pFileManager->openFile(filename);
575 
576     origDuneText[filename] = std::shared_ptr<IndexedTextFile>(new IndexedTextFile(rwop, bDecode));
577 
578     SDL_RWclose(rwop);
579 }
580 
581