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 <sand.h>
19
20 #include <globals.h>
21
22 #include <FileClasses/GFXManager.h>
23 #include <FileClasses/TextManager.h>
24 #include <FileClasses/music/MusicPlayer.h>
25
26 #include <Menu/BriefingMenu.h>
27 #include <Menu/CampaignStatsMenu.h>
28 #include <Menu/CustomGameStatsMenu.h>
29
30 #include <CutScenes/Meanwhile.h>
31 #include <CutScenes/Finale.h>
32
33 #include <Game.h>
34 #include <GameInitSettings.h>
35 #include <data.h>
36
37 #include <misc/exceptions.h>
38
39 #include <algorithm>
40
41 /**
42 This function draws the cursor to the screen. The coordinate is read from
43 the two global variables drawnMouseX and drawnMouseY.
44 */
drawCursor()45 void drawCursor() {
46 if(!(SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)) {
47 return;
48 }
49
50 SDL_Texture* tex = pGFXManager->getUIGraphic(cursorFrame);
51
52 SDL_Rect dest = calcDrawingRect(tex, drawnMouseX, drawnMouseY);
53
54 //reposition image so pointing on right spot
55
56 if (cursorFrame == UI_CursorRight) {
57 dest.x -= dest.w/2;
58 } else if (cursorFrame == UI_CursorDown) {
59 dest.y -= dest.h/2;
60 }
61
62 if ((cursorFrame == UI_CursorAttack_Zoomlevel0) || (cursorFrame == UI_CursorMove_Zoomlevel0)) {
63 dest.x -= dest.w/2;
64 dest.y -= dest.h/2;
65 }
66
67 SDL_RenderCopy(renderer, tex, nullptr, &dest);
68 }
69
70 /**
71 This function resolves the picture corresponding to one item id.
72 \param itemID the id of the item to resolve (e.g. Unit_Quad)
73 \return the surface corresponding. This surface should not be freed or modified. nullptr on error.
74 */
resolveItemPicture(int itemID,HOUSETYPE house)75 SDL_Texture* resolveItemPicture(int itemID, HOUSETYPE house) {
76 int newPicID;
77
78 switch(itemID) {
79 case Structure_Barracks: newPicID = Picture_Barracks; break;
80 case Structure_ConstructionYard: newPicID = Picture_ConstructionYard; break;
81 case Structure_GunTurret: newPicID = Picture_GunTurret; break;
82 case Structure_HeavyFactory: newPicID = Picture_HeavyFactory; break;
83 case Structure_HighTechFactory: newPicID = Picture_HighTechFactory; break;
84 case Structure_IX: newPicID = Picture_IX; break;
85 case Structure_LightFactory: newPicID = Picture_LightFactory; break;
86 case Structure_Palace: newPicID = Picture_Palace; break;
87 case Structure_Radar: newPicID = Picture_Radar; break;
88 case Structure_Refinery: newPicID = Picture_Refinery; break;
89 case Structure_RepairYard: newPicID = Picture_RepairYard; break;
90 case Structure_RocketTurret: newPicID = Picture_RocketTurret; break;
91 case Structure_Silo: newPicID = Picture_Silo; break;
92 case Structure_Slab1: newPicID = Picture_Slab1; break;
93 case Structure_Slab4: newPicID = Picture_Slab4; break;
94 case Structure_StarPort: newPicID = Picture_StarPort; break;
95 case Structure_Wall: newPicID = Picture_Wall; break;
96 case Structure_WindTrap: newPicID = Picture_WindTrap; break;
97 case Structure_WOR: newPicID = Picture_WOR; break;
98
99 case Unit_Carryall: newPicID = Picture_Carryall; break;
100 case Unit_Devastator: newPicID = Picture_Devastator; break;
101 case Unit_Deviator: newPicID = Picture_Deviator; break;
102 case Unit_Frigate: newPicID = Picture_Frigate; break;
103 case Unit_Harvester: newPicID = Picture_Harvester; break;
104 case Unit_Launcher: newPicID = Picture_Launcher; break;
105 case Unit_MCV: newPicID = Picture_MCV; break;
106 case Unit_Ornithopter: newPicID = Picture_Ornithopter; break;
107 case Unit_Quad: newPicID = Picture_Quad; break;
108 case Unit_RaiderTrike: newPicID = Picture_RaiderTrike; break;
109 case Unit_SiegeTank: newPicID = Picture_SiegeTank; break;
110 case Unit_SonicTank: newPicID = Picture_SonicTank; break;
111 case Unit_Tank: newPicID = Picture_Tank; break;
112 case Unit_Trike: newPicID = Picture_Trike; break;
113 case Unit_Saboteur: newPicID = Picture_Saboteur; break;
114 case Unit_Sandworm: newPicID = Picture_Sandworm; break;
115 case Unit_Soldier: newPicID = Picture_Soldier; break;
116 case Unit_Trooper: {
117 switch(house) {
118 case HOUSE_SARDAUKAR: newPicID = Picture_Sardaukar; break;
119 case HOUSE_FREMEN: newPicID = Picture_Fremen; break;
120 default: newPicID = Picture_Trooper; break;
121 }
122 } break;
123 case Unit_Special: newPicID = Picture_Special; break;
124 case Unit_Infantry: newPicID = Picture_Soldier; break;
125 case Unit_Troopers: {
126 switch(house) {
127 case HOUSE_SARDAUKAR: newPicID = Picture_Sardaukar; break;
128 case HOUSE_FREMEN: newPicID = Picture_Fremen; break;
129 default: newPicID = Picture_Trooper; break;
130 }
131 } break;
132
133 default:
134 THROW(std::invalid_argument, "resolveItemPicture(): Invalid item ID " + stringify(itemID) + "!");
135 break;
136 }
137
138 return pGFXManager->getSmallDetailPic(newPicID);
139 }
140
141
142 /**
143 This function returns the anim id based on the passed filename.
144 \param filename the filename (e.g. STARPORT.WSA)
145 \return the id of the animation (e.g. Anim_StarPort)
146 */
getAnimByFilename(const std::string & filename)147 int getAnimByFilename(const std::string& filename) {
148 std::string lowerFilename = strToLower(filename);
149
150 if(lowerFilename == "fartr.wsa") return Anim_AtreidesPlanet;
151 else if(lowerFilename == "fhark.wsa") return Anim_HarkonnenPlanet;
152 else if(lowerFilename == "fordos.wsa") return Anim_OrdosPlanet;
153 else if(lowerFilename == "win1.wsa") return Anim_Win1;
154 else if(lowerFilename == "win2.wsa") return Anim_Win2;
155 else if(lowerFilename == "lostbild.wsa") return Anim_Lose1;
156 else if(lowerFilename == "lostvehc.wsa") return Anim_Lose2;
157 else if(lowerFilename == "barrac.wsa") return Anim_Barracks;
158 else if(lowerFilename == "carryall.wsa") return Anim_Carryall;
159 else if(lowerFilename == "construc.wsa") return Anim_ConstructionYard;
160 else if(lowerFilename == "fremen.wsa") return Anim_Fremen;
161 else if(lowerFilename == "gold-bb.wsa") return Anim_DeathHand;
162 else if(lowerFilename == "harktank.wsa") return Anim_Devastator;
163 else if(lowerFilename == "harvest.wsa") return Anim_Harvester;
164 else if(lowerFilename == "headqrts.wsa") return Anim_Radar;
165 else if(lowerFilename == "hitcftry.wsa") return Anim_HighTechFactory;
166 else if(lowerFilename == "htank.wsa") return Anim_SiegeTank;
167 else if(lowerFilename == "hvyftry.wsa") return Anim_HeavyFactory;
168 else if(lowerFilename == "hyinfy.wsa") return Anim_Trooper;
169 else if(lowerFilename == "infantry.wsa") return Anim_Infantry;
170 else if(lowerFilename == "ix.wsa") return Anim_IX;
171 else if(lowerFilename == "liteftry.wsa") return Anim_LightFactory;
172 else if(lowerFilename == "ltank.wsa") return Anim_Tank;
173 else if(lowerFilename == "mcv.wsa") return Anim_MCV;
174 else if(lowerFilename == "ordrtank.wsa") return Anim_Deviator;
175 else if(lowerFilename == "orni.wsa") return Anim_Ornithopter;
176 else if(lowerFilename == "otrike.wsa") return Anim_Raider;
177 else if(lowerFilename == "palace.wsa") return Anim_Palace;
178 else if(lowerFilename == "quad.wsa") return Anim_Quad;
179 else if(lowerFilename == "refinery.wsa") return Anim_Refinery;
180 else if(lowerFilename == "repair.wsa") return Anim_RepairYard;
181 else if(lowerFilename == "rtank.wsa") return Anim_Launcher;
182 else if(lowerFilename == "rturret.wsa") return Anim_RocketTurret;
183 else if(lowerFilename == "saboture.wsa") return Anim_Saboteur;
184 else if(lowerFilename == "slab.wsa") return Anim_Slab1;
185 else if(lowerFilename == "stank.wsa") return Anim_SonicTank;
186 else if(lowerFilename == "starport.wsa") return Anim_StarPort;
187 else if(lowerFilename == "storage.wsa") return Anim_Silo;
188 else if(lowerFilename == "trike.wsa") return Anim_Trike;
189 else if(lowerFilename == "turret.wsa") return Anim_GunTurret;
190 else if(lowerFilename == "wall.wsa") return Anim_Wall;
191 else if(lowerFilename == "windtrap.wsa") return Anim_WindTrap;
192 else if(lowerFilename == "wor.wsa") return Anim_WOR;
193 else if(lowerFilename == "worm.wsa") return Anim_Sandworm;
194 else if(lowerFilename == "sardukar.wsa") return Anim_Sardaukar;
195 else if(lowerFilename == "frigate.wsa") return Anim_Frigate;
196 else if(lowerFilename == "4slab.wsa") return Anim_Slab4;
197 else return 0;
198 }
199
200 /**
201 This function returns the size of the specified item.
202 \param ItemID the id of the item (e.g. Structure_HeavyFactory)
203 \return a Coord containg the size (e.g. (3,2) ). Returns (0,0) on error.
204 */
getStructureSize(int itemID)205 Coord getStructureSize(int itemID) {
206
207 switch(itemID) {
208 case Structure_Barracks: return Coord(2,2); break;
209 case Structure_ConstructionYard: return Coord(2,2); break;
210 case Structure_GunTurret: return Coord(1,1); break;
211 case Structure_HeavyFactory: return Coord(3,2); break;
212 case Structure_HighTechFactory: return Coord(3,2); break;
213 case Structure_IX: return Coord(2,2); break;
214 case Structure_LightFactory: return Coord(2,2); break;
215 case Structure_Palace: return Coord(3,3); break;
216 case Structure_Radar: return Coord(2,2); break;
217 case Structure_Refinery: return Coord(3,2); break;
218 case Structure_RepairYard: return Coord(3,2); break;
219 case Structure_RocketTurret: return Coord(1,1); break;
220 case Structure_Silo: return Coord(2,2); break;
221 case Structure_StarPort: return Coord(3,3); break;
222 case Structure_Slab1: return Coord(1,1); break;
223 case Structure_Slab4: return Coord(2,2); break;
224 case Structure_Wall: return Coord(1,1); break;
225 case Structure_WindTrap: return Coord(2,2); break;
226 case Structure_WOR: return Coord(2,2); break;
227 default: return Coord(0,0); break;
228 }
229
230 return Coord(0,0);
231 }
232
233 /**
234 This function return the item id of an item specified by name. There may be multiple names for
235 one item. The case of the name is ignored.
236 \param name the name of the item (e.g. "rocket-turret" or "r-turret".
237 \return the id of the item (e.g. Structure_RocketTurret)
238 */
getItemIDByName(const std::string & name)239 Uint32 getItemIDByName(const std::string& name) {
240 std::string lowerName = strToLower(name);
241
242 if(lowerName == "barracks") return Structure_Barracks;
243 else if((lowerName == "const yard") || (lowerName == "construction yard")) return Structure_ConstructionYard;
244 else if((lowerName == "r-turret") || (lowerName == "rocket-turret")) return Structure_RocketTurret;
245 else if((lowerName == "turret") || (lowerName == "gun-turret")) return Structure_GunTurret;
246 else if((lowerName == "heavy fctry") || (lowerName == "heavy factory")) return Structure_HeavyFactory;
247 else if((lowerName == "hi-tech") || (lowerName == "hightech factory")) return Structure_HighTechFactory;
248 else if((lowerName == "ix") || (lowerName == "house ix")) return Structure_IX;
249 else if((lowerName == "light fctry") || (lowerName == "light factory")) return Structure_LightFactory;
250 else if(lowerName == "palace") return Structure_Palace;
251 else if((lowerName == "outpost") || (lowerName == "radar")) return Structure_Radar;
252 else if(lowerName == "refinery") return Structure_Refinery;
253 else if((lowerName == "repair") || (lowerName == "repair yard")) return Structure_RepairYard;
254 else if((lowerName == "spice silo") || (lowerName == "silo")) return Structure_Silo;
255 else if((lowerName == "concrete") || (lowerName == "slab1")) return Structure_Slab1;
256 else if(lowerName == "slab4") return Structure_Slab4;
257 else if((lowerName == "star port") || (lowerName == "starport")) return Structure_StarPort;
258 else if(lowerName == "wall") return Structure_Wall;
259 else if(lowerName == "windtrap") return Structure_WindTrap;
260 else if(lowerName == "wor") return Structure_WOR;
261 else if((lowerName == "carryall") || (lowerName == "carry-all")) return Unit_Carryall;
262 else if((lowerName == "devastator") || (lowerName == "devistator")) return Unit_Devastator;
263 else if(lowerName == "deviator") return Unit_Deviator;
264 else if(lowerName == "frigate") return Unit_Frigate;
265 else if(lowerName == "harvester") return Unit_Harvester;
266 else if(lowerName == "soldier") return Unit_Soldier;
267 else if(lowerName == "launcher") return Unit_Launcher;
268 else if(lowerName == "mcv") return Unit_MCV;
269 else if((lowerName == "thopters") || (lowerName == "'thopters")
270 || (lowerName == "thopter") || (lowerName == "'thopter")
271 || (lowerName == "ornithopter")) return Unit_Ornithopter;
272 else if(lowerName == "quad") return Unit_Quad;
273 else if(lowerName == "saboteur") return Unit_Saboteur;
274 else if(lowerName == "sandworm") return Unit_Sandworm;
275 else if(lowerName == "siege tank") return Unit_SiegeTank;
276 else if((lowerName == "sonic tank") || (lowerName == "sonictank")) return Unit_SonicTank;
277 else if(lowerName == "tank") return Unit_Tank;
278 else if(lowerName == "trike") return Unit_Trike;
279 else if((lowerName == "raider trike") || (lowerName == "raider")) return Unit_RaiderTrike;
280 else if(lowerName == "trooper") return Unit_Trooper;
281 else if(lowerName == "special") return Unit_Special;
282 else if(lowerName == "infantry") return Unit_Infantry;
283 else if(lowerName == "troopers") return Unit_Troopers;
284 else return ItemID_Invalid;
285 }
286
287
288 /**
289 This function returns the name of an item id.
290 \param itemID the id of the item (e.g. Unit_Sandworm)
291 \return the name of the item (e.g. "Sandworm").
292 */
getItemNameByID(Uint32 itemID)293 std::string getItemNameByID(Uint32 itemID) {
294 switch(itemID) {
295 case Structure_Barracks: return "Barracks"; break;
296 case Structure_ConstructionYard: return "Const Yard"; break;
297 case Structure_GunTurret: return "Turret"; break;
298 case Structure_HeavyFactory: return "Heavy Fctry"; break;
299 case Structure_HighTechFactory: return "Hi-Tech"; break;
300 case Structure_IX: return "IX"; break;
301 case Structure_LightFactory: return "Light Fctry"; break;
302 case Structure_Palace: return "Palace"; break;
303 case Structure_Radar: return "Outpost"; break;
304 case Structure_Refinery: return "Refinery"; break;
305 case Structure_RepairYard: return "Repair"; break;
306 case Structure_RocketTurret: return "R-Turret"; break;
307 case Structure_Silo: return "Spice Silo"; break;
308 case Structure_Slab1: return "Concrete"; break;
309 case Structure_Slab4: return "Slab4"; break;
310 case Structure_StarPort: return "Starport"; break;
311 case Structure_Wall: return "Wall"; break;
312 case Structure_WindTrap: return "Windtrap"; break;
313 case Structure_WOR: return "WOR"; break;
314
315 case Unit_Carryall: return "Carryall"; break;
316 case Unit_Devastator: return "Devastator"; break;
317 case Unit_Deviator: return "Deviator"; break;
318 case Unit_Frigate: return "Frigate"; break;
319 case Unit_Harvester: return "Harvester"; break;
320 case Unit_Launcher: return "Launcher"; break;
321 case Unit_MCV: return "MCV"; break;
322 case Unit_Ornithopter: return "'Thopter"; break;
323 case Unit_Quad: return "Quad"; break;
324 case Unit_RaiderTrike: return "Raider Trike"; break;
325 case Unit_SiegeTank: return "Siege Tank"; break;
326 case Unit_SonicTank: return "Sonic Tank"; break;
327 case Unit_Tank: return "Tank"; break;
328 case Unit_Trike: return "Trike"; break;
329 case Unit_Saboteur: return "Saboteur"; break;
330 case Unit_Sandworm: return "Sandworm"; break;
331 case Unit_Soldier: return "Soldier"; break;
332 case Unit_Trooper: return "Trooper"; break;
333 case Unit_Special: return "Special"; break;
334 case Unit_Infantry: return "Infantry"; break;
335 case Unit_Troopers: return "Troopers"; break;
336
337 default:
338 THROW(std::invalid_argument, "getItemNameByID(): Invalid item ID!");
339 break;
340 }
341 }
342
343
344 /**
345 This function resolves the name corresponding to one item id.
346 \param itemID the id of the item to resolve (e.g. Unit_Quad)
347 \return the string corresponding.
348 */
resolveItemName(int itemID)349 std::string resolveItemName(int itemID) {
350 switch(itemID) {
351 case Structure_Barracks: return _("@DUNE.ENG|253#Barracks"); break;
352 case Structure_ConstructionYard: return _("@DUNE.ENG|249#Construction Yard"); break;
353 case Structure_GunTurret: return _("@DUNE.ENG|263#Gun Turret"); break;
354 case Structure_HeavyFactory: return _("@DUNE.ENG|241#Heacy Factory"); break;
355 case Structure_HighTechFactory: return _("@DUNE.ENG|243#Hightech Factory"); break;
356 case Structure_IX: return _("@DUNE.ENG|245#House IX"); break;
357 case Structure_LightFactory: return _("@DUNE.ENG|239#Light Factory"); break;
358 case Structure_Palace: return _("@DUNE.ENG|237#Palace"); break;
359 case Structure_Radar: return _("@DUNE.ENG|269#Radar"); break;
360 case Structure_Refinery: return _("@DUNE.ENG|256#Refinery"); break;
361 case Structure_RepairYard: return _("@DUNE.ENG|259#Repair Yard"); break;
362 case Structure_RocketTurret: return _("@DUNE.ENG|265#Rocket Turret"); break;
363 case Structure_Silo: return _("@DUNE.ENG|267#Silo"); break;
364 case Structure_Slab1: return _("@DUNE.ENG|233#Slab"); break;
365 case Structure_Slab4: return _("@DUNE.ENG|235#Slab (2x2)"); break;
366 case Structure_StarPort: return _("@DUNE.ENG|255#Starport"); break;
367 case Structure_Wall: return _("@DUNE.ENG|261#Wall"); break;
368 case Structure_WindTrap: return _("@DUNE.ENG|251#Windtrap"); break;
369 case Structure_WOR: return _("@DUNE.ENG|247#WOR"); break;
370
371 case Unit_Carryall: return _("@DUNE.ENG|195#Carryall"); break;
372 case Unit_Devastator: return _("@DUNE.ENG|217#Devastator"); break;
373 case Unit_Deviator: return _("@DUNE.ENG|211#Deviator"); break;
374 case Unit_Frigate: return _("Frigate"); break;
375 case Unit_Harvester: return _("@DUNE.ENG|227#Harvester"); break;
376 case Unit_Launcher: return _("@DUNE.ENG|209#Launcher"); break;
377 case Unit_MCV: return _("@DUNE.ENG|229#MCV"); break;
378 case Unit_Ornithopter: return _("@DUNE.ENG|197#Ornithopter"); break;
379 case Unit_Quad: return _("@DUNE.ENG|225#Quad"); break;
380 case Unit_RaiderTrike: return _("@DUNE.ENG|223#Raider Trike"); break;
381 case Unit_SiegeTank: return _("@DUNE.ENG|215#Siege Tank"); break;
382 case Unit_SonicTank: return _("@DUNE.ENG|219#Sonic Tank"); break;
383 case Unit_Tank: return _("@DUNE.ENG|213#Tank"); break;
384 case Unit_Trike: return _("@DUNE.ENG|221#Trike"); break;
385 case Unit_Saboteur: return _("@DUNE.ENG|207#Saboteur"); break;
386 case Unit_Sandworm: return _("@DUNE.ENG|231#Sandworm"); break;
387 case Unit_Soldier: return _("@DUNE.ENG|203#Soldier"); break;
388 case Unit_Trooper: return _("@DUNE.ENG|205#Trooper"); break;
389 case Unit_Special: return _("Sonic/Devast./Devia."); break;
390 case Unit_Infantry: return _("@DUNE.ENG|199#Infantry"); break;
391 case Unit_Troopers: return _("@DUNE.ENG|201#Troopers"); break;
392
393 default:
394 THROW(std::invalid_argument, "resolveItemName(): Invalid item ID!");
395 break;
396 }
397 }
398
399
400 /**
401 This function returns the number of each house providing the house name as a string. The comparison is
402 done case-insensitive.
403 \param name the name of the house (e.g."Atreides")
404 \return the number of the house (e.g. HOUSE_ATREIDES). HOUSE_INVALID is returned on error.
405 */
getHouseByName(const std::string & name)406 HOUSETYPE getHouseByName(const std::string& name) {
407 std::string lowerName = strToLower(name);
408
409 if(lowerName == "harkonnen") return HOUSE_HARKONNEN;
410 else if(lowerName == "atreides") return HOUSE_ATREIDES;
411 else if(lowerName == "ordos") return HOUSE_ORDOS;
412 else if(lowerName == "fremen") return HOUSE_FREMEN;
413 else if(lowerName == "sardaukar") return HOUSE_SARDAUKAR;
414 else if(lowerName == "mercenary") return HOUSE_MERCENARY;
415 else return HOUSE_INVALID;
416 }
417
418 /**
419 This function returns the name of house the house number.
420 \param house the number of the house (e.g. HOUSE_ATREIDES)
421 \return the name of the house (e.g. "Atreides").
422 */
getHouseNameByNumber(HOUSETYPE house)423 std::string getHouseNameByNumber(HOUSETYPE house) {
424 if(house >= 0 && house < NUM_HOUSES) {
425 static const char* houseName[NUM_HOUSES] = { "Harkonnen",
426 "Atreides",
427 "Ordos",
428 "Fremen",
429 "Sardaukar",
430 "Mercenary"
431 };
432 return houseName[house];
433 } else {
434 THROW(std::invalid_argument, "Invalid house number %d!", house);
435 }
436 }
437
getAttackModeByName(const std::string & name)438 ATTACKMODE getAttackModeByName(const std::string& name) {
439 std::string lowerName = strToLower(name);
440
441 if(lowerName == "guard") return GUARD;
442 else if(lowerName == "area guard") return AREAGUARD;
443 else if(lowerName == "ambush") return AMBUSH;
444 else if((lowerName == "hunt") || (lowerName == "attack")) return HUNT;
445 else if(lowerName == "harvest") return HARVEST;
446 else if(lowerName == "sabotage") return SABOTAGE;
447 else if(lowerName == "stop") return STOP;
448 else if(lowerName == "capture") return CAPTURE;
449 else if(lowerName == "retreat") return RETREAT;
450 else return ATTACKMODE_INVALID;
451 }
452
453
getAttackModeNameByMode(ATTACKMODE attackMode)454 std::string getAttackModeNameByMode(ATTACKMODE attackMode) {
455 switch(attackMode) {
456 case GUARD: return "Guard"; break;
457 case AREAGUARD: return "Area Guard"; break;
458 case AMBUSH: return "Ambush"; break;
459 case HUNT: return "Hunt"; break;
460 case HARVEST: return "Harvest"; break;
461 case SABOTAGE: return "Sabotage"; break;
462 case STOP: return "Stop"; break;
463 case CAPTURE: return "Capture"; break;
464 default:
465 THROW(std::invalid_argument, "getAttackModeNameByMode(): Invalid attack mode!");
466 break;
467 }
468 }
469
470
getColorByTerrainType(int terrainType)471 Uint32 getColorByTerrainType(int terrainType) {
472 Uint32 color = COLOR_BLACK;
473 switch (terrainType) {
474 case Terrain_Dunes: color = COLOR_DESERTSAND; break;
475 case Terrain_Mountain: color = COLOR_MOUNTAIN; break;
476 case Terrain_Rock: color = COLOR_ROCK; break;
477 case Terrain_Sand: color = COLOR_DESERTSAND; break;
478 case Terrain_Spice: color = COLOR_SPICE; break;
479 case Terrain_ThickSpice: color = COLOR_THICKSPICE; break;
480 case Terrain_SpiceBloom: color = COLOR_BLOOM; break;
481 case Terrain_SpecialBloom: color = COLOR_BLOOM; break;
482 case Terrain_Slab: color = COLOR_ROCK; break;
483 default: color = COLOR_ROCK; break;
484 }
485
486 return color;
487 }
488
489
490
getDropLocationByName(const std::string & name)491 DropLocation getDropLocationByName(const std::string& name) {
492 std::string lowerName = strToLower(name);
493
494 if(lowerName == "north") {
495 return Drop_North;
496 } else if(lowerName == "east") {
497 return Drop_East;
498 } else if(lowerName == "south") {
499 return Drop_South;
500 } else if(lowerName == "west") {
501 return Drop_West;
502 } else if(lowerName == "air") {
503 return Drop_Air;
504 } else if(lowerName == "visible") {
505 return Drop_Visible;
506 } else if(lowerName == "enemybase") {
507 return Drop_Enemybase;
508 } else if(lowerName == "homebase") {
509 return Drop_Homebase;
510 } else {
511 return Drop_Invalid;
512 }
513 }
514
515
getDropLocationNameByID(DropLocation dropLocation)516 std::string getDropLocationNameByID(DropLocation dropLocation) {
517 switch(dropLocation) {
518 case Drop_North: return "North"; break;
519 case Drop_East: return "East"; break;
520 case Drop_South: return "South"; break;
521 case Drop_West: return "West"; break;
522 case Drop_Air: return "Air"; break;
523 case Drop_Visible: return "Visible"; break;
524 case Drop_Enemybase: return "Enemybase"; break;
525 case Drop_Homebase: return "Homebase"; break;
526 default:
527 THROW(std::invalid_argument, "getDropLocationNameByID(): Invalid drop location!");
528 break;
529 }
530 }
531
resolveDropLocationName(DropLocation dropLocation)532 std::string resolveDropLocationName(DropLocation dropLocation) {
533 switch(dropLocation) {
534 case Drop_North: return _("top edge"); break;
535 case Drop_East: return _("right edge"); break;
536 case Drop_South: return _("bottom edge"); break;
537 case Drop_West: return _("left edge"); break;
538 case Drop_Air: return _("random"); break;
539 case Drop_Visible: return _("middle"); break;
540 case Drop_Enemybase: return _("enemy base"); break;
541 case Drop_Homebase: return _("home base"); break;
542 default:
543 THROW(std::invalid_argument, "resolveDropLocationName(): Invalid drop location!");
544 break;
545 }
546 }
547
getTeamBehaviorByName(const std::string & name)548 TeamBehavior getTeamBehaviorByName(const std::string& name) {
549 std::string lowerName = strToLower(name);
550
551 if(lowerName == "normal") {
552 return TeamBehavior_Normal;
553 } else if(lowerName == "guard") {
554 return TeamBehavior_Guard;
555 } else if(lowerName == "kamikaze") {
556 return TeamBehavior_Kamikaze;
557 } else if(lowerName == "staging") {
558 return TeamBehavior_Staging;
559 } else if(lowerName == "flee") {
560 return TeamBehavior_Flee;
561 } else {
562 return TeamBehavior_Invalid;
563 }
564 }
565
566
getTeamBehaviorNameByID(TeamBehavior teamBehavior)567 std::string getTeamBehaviorNameByID(TeamBehavior teamBehavior) {
568 switch(teamBehavior) {
569 case TeamBehavior_Normal: return "Normal"; break;
570 case TeamBehavior_Guard: return "Guard"; break;
571 case TeamBehavior_Kamikaze: return "Kamikaze"; break;
572 case TeamBehavior_Staging: return "Staging"; break;
573 case TeamBehavior_Flee: return "Flee"; break;
574 default:
575 THROW(std::invalid_argument, "getTeamBehaviorNameByID(): Invalid team behavior!");
576 break;
577 }
578 }
579
580
getTeamTypeByName(const std::string & name)581 TeamType getTeamTypeByName(const std::string& name) {
582 std::string lowerName = strToLower(name);
583
584 if(lowerName == "foot") {
585 return TeamType_Foot;
586 } else if(lowerName == "wheel" || lowerName == "wheeled") {
587 return TeamType_Wheeled;
588 } else if(lowerName == "track" || lowerName == "tracked") {
589 return TeamType_Tracked;
590 } else if(lowerName == "winged") {
591 return TeamType_Winged;
592 } else if(lowerName == "slither") {
593 return TeamType_Slither;
594 } else if(lowerName == "harvester") {
595 return TeamType_Harvester;
596 } else {
597 return TeamType_Invalid;
598 }
599 }
600
601
getTeamTypeNameByID(TeamType teamType)602 std::string getTeamTypeNameByID(TeamType teamType) {
603 switch(teamType) {
604 case TeamType_Foot: return "Foot"; break;
605 case TeamType_Wheeled: return "Wheeled"; break;
606 case TeamType_Tracked: return "Tracked"; break;
607 case TeamType_Winged: return "Winged"; break;
608 case TeamType_Slither: return "Slither"; break;
609 case TeamType_Harvester: return "Harvester"; break;
610 default:
611 THROW(std::invalid_argument, "getTeamTypeNameByID(): Invalid team type!");
612 break;
613 }
614 }
615
616
617 /**
618 This function returns the house-dependent weakness of a unit to get deviated
619 \param house the house of the unit (choose the real owner);
620 */
getDeviateWeakness(HOUSETYPE house)621 FixPoint getDeviateWeakness(HOUSETYPE house) {
622
623 // Deviators are crap enough. If this is a custom game remove the weakness nerf
624 // So that Ordos is playable for Humans
625 //if(currentGame->gameType == GameType::CustomGame){
626 //return FixPt(0,100);
627 return 1;
628 //}
629
630 /*
631 switch(house) {
632 case HOUSE_HARKONNEN: return FixPt(0,78);
633 case HOUSE_ATREIDES: return FixPt(0,30);
634 case HOUSE_ORDOS: return FixPt(0,50);
635 case HOUSE_FREMEN: return FixPt(0,08);
636 case HOUSE_SARDAUKAR: return FixPt(0,04);
637 case HOUSE_MERCENARY: return FixPt(0,50);
638 default: return FixPt(0,00);
639 }*/
640 }
641
642
643
644 /**
645 Starts a game replay
646 \param filename the filename of the replay file
647 */
startReplay(const std::string & filename)648 void startReplay(const std::string& filename) {
649 SDL_Log("Initializing replay...");
650 currentGame = new Game();
651 currentGame->initReplay(filename);
652
653 currentGame->runMainLoop();
654
655 delete currentGame;
656
657 // Change music to menu music
658 musicPlayer->changeMusic(MUSIC_MENU);
659 }
660
661
662 /**
663 Starts a new game. If this game is quit it might start another game. This other game is also started from
664 this function. This is done until there is no more game to be started.
665 \param init contains all the information to start the game
666 */
startSinglePlayerGame(const GameInitSettings & init)667 void startSinglePlayerGame(const GameInitSettings& init)
668 {
669 GameInitSettings currentGameInitInfo = init;
670
671 while(1) {
672
673 SDL_Log("Initializing game...");
674 currentGame = new Game();
675 currentGame->initGame(currentGameInitInfo);
676
677 // get init settings from game as it might have changed (through loading the game)
678 currentGameInitInfo = currentGame->getGameInitSettings();
679
680 currentGame->runMainLoop();
681
682 bool bGetNext = true;
683 while(bGetNext) {
684 switch(currentGame->whatNext()) {
685 case GAME_DEBRIEFING_WIN: {
686 SDL_Log("Debriefing...");
687 BriefingMenu* pBriefing = new BriefingMenu(currentGameInitInfo.getHouseID(), currentGameInitInfo.getMission(), DEBRIEFING_WIN);
688 pBriefing->showMenu();
689 delete pBriefing;
690
691 SDL_Log("Game statistics...");
692 CampaignStatsMenu* pCampaignStats = new CampaignStatsMenu(missionNumberToLevelNumber(currentGameInitInfo.getMission()));
693 pCampaignStats->showMenu();
694 delete pCampaignStats;
695
696 int houseID = currentGameInitInfo.getHouseID();
697
698 if(currentGameInitInfo.getGameType() == GameType::Campaign) {
699 int level = missionNumberToLevelNumber(currentGameInitInfo.getMission());
700
701 if(level == 4 && (houseID == HOUSE_HARKONNEN || houseID == HOUSE_ATREIDES || houseID == HOUSE_ORDOS)) {
702 SDL_Log("Playing meanwhile...");
703 Meanwhile* pMeanwhile = new Meanwhile(houseID,true);
704 pMeanwhile->run();
705 delete pMeanwhile;
706 } else if(level == 8 && (houseID == HOUSE_HARKONNEN || houseID == HOUSE_ATREIDES || houseID == HOUSE_ORDOS)) {
707 SDL_Log("Playing meanwhile...");
708 Meanwhile* pMeanwhile = new Meanwhile(houseID,false);
709 pMeanwhile->run();
710 delete pMeanwhile;
711 } else if(level == 9) {
712 SDL_Log("Playing finale.....");
713 Finale* pFinale = new Finale(houseID);
714 pFinale->run();
715 delete pFinale;
716 }
717 }
718 } break;
719
720 case GAME_DEBRIEFING_LOST: {
721 SDL_Log("Debriefing...");
722 BriefingMenu* pBriefing = new BriefingMenu(currentGameInitInfo.getHouseID(), currentGameInitInfo.getMission(), DEBRIEFING_LOST);
723 pBriefing->showMenu();
724 delete pBriefing;
725 } break;
726
727 case GAME_CUSTOM_GAME_STATS: {
728 SDL_Log("Game statistics...");
729 CustomGameStatsMenu* pCustomGameStats = new CustomGameStatsMenu();
730 pCustomGameStats->showMenu();
731 delete pCustomGameStats;
732 } break;
733
734 case GAME_LOAD:
735 case GAME_NEXTMISSION: {
736 currentGameInitInfo = currentGame->getNextGameInitSettings();
737 delete currentGame;
738 bGetNext = false;
739 } break;
740
741 case GAME_RETURN_TO_MENU:
742 default: {
743 delete currentGame;
744 currentGame = nullptr;
745
746 // Change music to menu music
747 musicPlayer->changeMusic(MUSIC_MENU);
748
749 return;
750 } break;
751 }
752 }
753
754
755 }
756 }
757
758 /**
759 Starts a new multiplayer game.
760 \param init contains all the information to start the game
761 */
startMultiPlayerGame(const GameInitSettings & init)762 void startMultiPlayerGame(const GameInitSettings& init)
763 {
764 GameInitSettings currentGameInitInfo = init;
765
766 SDL_Log("Initializing game...");
767 currentGame = new Game();
768 currentGame->initGame(currentGameInitInfo);
769
770 // get init settings from game as it might have changed (through loading the game)
771 currentGameInitInfo = currentGame->getGameInitSettings();
772
773 currentGame->runMainLoop();
774
775 if(currentGame->whatNext() == GAME_CUSTOM_GAME_STATS) {
776 SDL_Log("Game statistics...");
777 CustomGameStatsMenu* pCustomGameStats = new CustomGameStatsMenu();
778 pCustomGameStats->showMenu();
779 delete pCustomGameStats;
780 }
781
782 delete currentGame;
783 currentGame = nullptr;
784 }
785