1 /************************************************************************************
2 
3 	AstroMenace
4 	Hardcore 3D space scroll-shooter with spaceship upgrade possibilities.
5 	Copyright (c) 2006-2019 Mikhail Kurinnoi, Viewizard
6 
7 
8 	AstroMenace is free software: you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation, either version 3 of the License, or
11 	(at your option) any later version.
12 
13 	AstroMenace is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with AstroMenace. If not, see <https://www.gnu.org/licenses/>.
20 
21 
22 	Website: https://viewizard.com/
23 	Project: https://github.com/viewizard/astromenace
24 	E-mail: viewizard@viewizard.com
25 
26 *************************************************************************************/
27 
28 // TODO split earth fighter and player ship classes
29 
30 // TODO don't call GetPreloadedTextureAsset() all the time, use cached texture instead
31 
32 // TODO switch to enumeration EngineType in CreateRotateSpaceShipEngine(), CreateSpaceShipEngine()
33 
34 #include "space_ship.h"
35 #include "../../assets/texture.h"
36 
37 // NOTE switch to nested namespace definition (namespace A::B::C { ... }) (since C++17)
38 namespace viewizard {
39 namespace astromenace {
40 
41 namespace {
42 
43 struct sEarthSpaceFighterData {
44 	float Armor;
45 	unsigned int EngineQuantity;
46 	std::string Name;
47 };
48 
49 const std::vector<sEarthSpaceFighterData> PresetEarthSpaceFighterData{
50 	{30,	2,	"models/earthfighter/sf-01.vw3d"},
51 	{40,	4,	"models/earthfighter/sf-02.vw3d"},
52 	{60,	4,	"models/earthfighter/sf-03.vw3d"},
53 	{35,	2,	"models/earthfighter/sf-04.vw3d"},
54 	{45,	4,	"models/earthfighter/sf-05.vw3d"},
55 	{50,	2,	"models/earthfighter/sf-06.vw3d"},
56 	{60,	3,	"models/earthfighter/sf-07.vw3d"},
57 	{25,	4,	"models/earthfighter/sf-08.vw3d"},
58 	{55,	2,	"models/earthfighter/sf-09.vw3d"},
59 	{55,	2,	"models/earthfighter/sf-10.vw3d"},
60 	{60,	2,	"models/earthfighter/sf-11.vw3d"},
61 	{70,	2,	"models/earthfighter/sf-12.vw3d"},
62 	{80,	4,	"models/earthfighter/sf-13.vw3d"},
63 	{65,	2,	"models/earthfighter/sf-14.vw3d"},
64 	{70,	2,	"models/earthfighter/sf-15.vw3d"},
65 	{90,	4,	"models/earthfighter/sf-16.vw3d"},
66 	{75,	2,	"models/earthfighter/sf-17.vw3d"},
67 	{110,	4,	"models/earthfighter/sf-18.vw3d"},
68 	{55,	4,	"models/earthfighter/sf-19.vw3d"},
69 	{80,	4,	"models/earthfighter/sf-20.vw3d"},
70 	{80,	2,	"models/earthfighter/sf-21.vw3d"},
71 	{100,	1,	"models/earthfighter/sf-22.vw3d"}
72 };
73 
74 } // unnamed namespace
75 
76 
77 /*
78  * Get engine power.
79  */
GetEnginePower(const int EngineType)80 float GetEnginePower(const int EngineType)
81 {
82 	switch (EngineType) {
83 	case 1:
84 		return 20.0f;
85 	case 2:
86 		return 25.0f;
87 	case 3:
88 		return 30.0f;
89 	case 4:
90 		return 35.0f;
91 	default:
92 		std::cerr << __func__ << "(): " << "wrong EngineType.\n";
93 		break;
94 	}
95 
96 	return 0.0f;
97 }
98 
99 /*
100  * Get max engine acceleration.
101  */
GetEngineAcceleration(const int EngineType)102 float GetEngineAcceleration(const int EngineType)
103 {
104 	switch (EngineType) {
105 	case 1:
106 		return 15.0f;
107 	case 2:
108 		return 19.0f;
109 	case 3:
110 		return 24.0f;
111 	case 4:
112 		return 28.0f;
113 	default:
114 		std::cerr << __func__ << "(): " << "wrong EngineType.\n";
115 		break;
116 	}
117 
118 	return 0.0f;
119 }
120 
121 /*
122  * Get rotate engine power.
123  */
GetEngineRotatePower(const int EngineType)124 float GetEngineRotatePower(const int EngineType)
125 {
126 	switch (EngineType) {
127 	case 1:
128 		return 15.0f;
129 	case 2:
130 		return 18.0f;
131 	case 3:
132 		return 20.0f;
133 	case 4:
134 		return 23.0f;
135 	default:
136 		std::cerr << __func__ << "(): " << "wrong EngineType.\n";
137 		break;
138 	}
139 
140 	return 0.0f;
141 }
142 
143 /*
144  * Setup weapon.
145  */
SetEarthSpaceFighterWeapon(std::weak_ptr<cSpaceShip> & SpaceShip,const int WeaponSlot,const int WeaponNum)146 bool SetEarthSpaceFighterWeapon(std::weak_ptr<cSpaceShip> &SpaceShip, const int WeaponSlot, const int WeaponNum)
147 {
148 	auto sharedSpaceShip = SpaceShip.lock();
149 	if (!sharedSpaceShip)
150 		return false;
151 
152 	if (static_cast<int>(sharedSpaceShip->WeaponSlots.size()) < WeaponSlot)
153 		return false;
154 
155 	if (!sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Weapon.expired())
156 		ReleaseWeapon(sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Weapon);
157 
158 	sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Weapon = CreateWeapon(WeaponNum);
159 
160 	auto sharedWeapon = sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Weapon.lock();
161 	if (!sharedWeapon)
162 		return false;
163 
164 	if (sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Type < sharedWeapon->WeaponLevel) {
165 		ReleaseWeapon(sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Weapon);
166 		return false;
167 	}
168 
169 	sharedWeapon->SetLocation(sharedSpaceShip->WeaponSlots[WeaponSlot - 1].Location);
170 	sharedWeapon->ObjectStatus = sharedSpaceShip->ObjectStatus;
171 
172 	return true;
173 }
174 
175 /*
176  * Setup engine gfx.
177  */
CreateSpaceShipEngine(std::shared_ptr<cParticleSystem> & ParticleSystem,const int EngineType)178 static void CreateSpaceShipEngine(std::shared_ptr<cParticleSystem> &ParticleSystem, const int EngineType)
179 {
180 	ParticleSystem->Texture = GetPreloadedTextureAsset("gfx/flare1.tga");
181 
182 	static const sRGBCOLOR LightYellow{1.0f, 0.7f, 0.3f};
183 	static const sRGBCOLOR Red{1.0f, 0.0f, 0.0f};
184 
185 	static const sRGBCOLOR MuddyYellow{0.6f, 0.6f, 0.3f};
186 	static const sRGBCOLOR LightGreen{0.3f, 1.0f, 0.3f};
187 
188 	static const sRGBCOLOR Violet{0.5f, 0.5f, 1.0f};
189 	static const sRGBCOLOR LightViolet{0.0f, 0.4f, 1.0f};
190 
191 	static const sRGBCOLOR Turquoise{0.0f, 0.7f, 1.0f};
192 	static const sRGBCOLOR LightSkyey{0.7f, 1.0f, 1.0f};
193 
194 	switch (EngineType) {
195 	case 1:
196 		ParticleSystem->ColorStart = LightYellow;
197 		ParticleSystem->ColorEnd = Red;
198 		ParticleSystem->AlphaStart = 1.00f;
199 		ParticleSystem->AlphaEnd = 0.10f;
200 		ParticleSystem->SizeStart = 0.50f;
201 		ParticleSystem->SizeVar = 0.50f;
202 		ParticleSystem->SizeEnd = 0.20f;
203 		ParticleSystem->Speed = 7.00f;
204 		ParticleSystem->SpeedOnCreation = 7.00f;
205 		ParticleSystem->SpeedVar = 2.00f;
206 		ParticleSystem->Theta = 30.00f;
207 		ParticleSystem->Life = 0.50f;
208 		ParticleSystem->ParticlesPerSec = 100;
209 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.35f, 0.15f, 0.0f, 0.07f);
210 		ParticleSystem->LightNeedDeviation = true;
211 		break;
212 	case 2:
213 		ParticleSystem->ColorStart = MuddyYellow;
214 		ParticleSystem->ColorEnd = LightGreen;
215 		ParticleSystem->AlphaStart = 1.00f;
216 		ParticleSystem->AlphaEnd = 0.00f;
217 		ParticleSystem->SizeStart = 0.50f;
218 		ParticleSystem->SizeVar = 0.70f;
219 		ParticleSystem->SizeEnd = 0.10f;
220 		ParticleSystem->Speed = 7.00f;
221 		ParticleSystem->SpeedOnCreation = 7.00f;
222 		ParticleSystem->SpeedVar = 2.00f;
223 		ParticleSystem->Theta = 12.00f;
224 		ParticleSystem->Life = 0.50f;
225 		ParticleSystem->ParticlesPerSec = 100;
226 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.4f, 0.75f, 0.15f, 0.0f, 0.07f);
227 		ParticleSystem->LightNeedDeviation = true;
228 		break;
229 	case 3:
230 		ParticleSystem->ColorStart = Violet;
231 		ParticleSystem->ColorEnd = LightViolet;
232 		ParticleSystem->AlphaStart = 1.00f;
233 		ParticleSystem->AlphaEnd = 0.00f;
234 		ParticleSystem->SizeStart = 0.50f;
235 		ParticleSystem->SizeVar = 0.50f;
236 		ParticleSystem->SizeEnd = 0.10f;
237 		ParticleSystem->Speed = 7.00f;
238 		ParticleSystem->SpeedOnCreation = 7.00f;
239 		ParticleSystem->SpeedVar = 2.00f;
240 		ParticleSystem->Theta = 3.00f;
241 		ParticleSystem->Life = 0.50f;
242 		ParticleSystem->ParticlesPerSec = 80;
243 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.25f, 0.25f, 1.0f, 0.0f, 0.07f);
244 		ParticleSystem->LightNeedDeviation = true;
245 		break;
246 	case 4:
247 		ParticleSystem->ColorStart = Turquoise;
248 		ParticleSystem->ColorEnd = LightSkyey;
249 		ParticleSystem->AlphaStart = 1.00f;
250 		ParticleSystem->AlphaEnd = 0.00f;
251 		ParticleSystem->SizeStart = 0.30f;
252 		ParticleSystem->SizeVar = 0.00f;
253 		ParticleSystem->SizeEnd = 0.10f;
254 		ParticleSystem->Speed = 12.00f;
255 		ParticleSystem->SpeedOnCreation = 12.00f;
256 		ParticleSystem->Theta = 30.00f;
257 		ParticleSystem->Life = 0.30f;
258 		ParticleSystem->ParticlesPerSec = 100;
259 		ParticleSystem->CreationType = eParticleCreationType::Sphere;
260 		ParticleSystem->CreationSize(0.6f, 0.6f, 0.1f);
261 		ParticleSystem->IsMagnet = true;
262 		ParticleSystem->MagnetFactor = 50.0f;
263 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.0f, 0.7f, 1.0f, 0.0f, 0.07f);
264 		ParticleSystem->LightNeedDeviation = true;
265 		break;
266 
267 	default:
268 		std::cerr << __func__ << "(): " << "wrong EngineType.\n";
269 		break;
270 	}
271 }
272 
273 /*
274  * Setup rotate engine gfx.
275  */
CreateRotateSpaceShipEngine(std::shared_ptr<cParticleSystem> & ParticleSystem,const int EngineType)276 static void CreateRotateSpaceShipEngine(std::shared_ptr<cParticleSystem> &ParticleSystem, const int EngineType)
277 {
278 	ParticleSystem->Texture = GetPreloadedTextureAsset("gfx/flare1.tga");
279 
280 	static const sRGBCOLOR LightYellow{1.0f, 0.7f, 0.3f};
281 	static const sRGBCOLOR Red{1.0f, 0.0f, 0.0f};
282 
283 	static const sRGBCOLOR MuddyYellow{0.6f, 0.6f, 0.3f};
284 	static const sRGBCOLOR LightGreen{0.3f, 1.0f, 0.3f};
285 
286 	static const sRGBCOLOR Violet{0.5f, 0.5f, 1.0f};
287 	static const sRGBCOLOR LightViolet{0.0f, 0.4f, 1.0f};
288 
289 	static const sRGBCOLOR Turquoise{0.0f, 0.7f, 1.0f};
290 	static const sRGBCOLOR LightSkyey{0.7f, 1.0f, 1.0f};
291 
292 	switch (EngineType) {
293 	case 1:
294 		ParticleSystem->ColorStart = LightYellow;
295 		ParticleSystem->ColorEnd = Red;
296 		ParticleSystem->AlphaStart = 0.60f;
297 		ParticleSystem->AlphaEnd = 0.10f;
298 		ParticleSystem->SizeStart = 0.50f;
299 		ParticleSystem->SizeVar = 0.05f;
300 		ParticleSystem->SizeEnd = 0.10f;
301 		ParticleSystem->Speed = 5.00f;
302 		ParticleSystem->SpeedVar = 5.00f;
303 		ParticleSystem->Theta = 40.00f;
304 		ParticleSystem->Life = 0.50f;
305 		ParticleSystem->IsSuppressed = true;
306 		ParticleSystem->ParticlesPerSec = 50;
307 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.35f, 0.15f, 0.0f, 0.2f);
308 		ParticleSystem->LightNeedDeviation = true;
309 		break;
310 	case 2:
311 		ParticleSystem->ColorStart = MuddyYellow;
312 		ParticleSystem->ColorEnd = LightGreen;
313 		ParticleSystem->AlphaStart = 0.60f;
314 		ParticleSystem->AlphaEnd = 0.10f;
315 		ParticleSystem->SizeStart = 0.5f;
316 		ParticleSystem->SizeVar = 0.05f;
317 		ParticleSystem->SizeEnd = 0.10f;
318 		ParticleSystem->Speed = 5.00f;
319 		ParticleSystem->SpeedVar = 5.00f;
320 		ParticleSystem->Theta = 30.00f;
321 		ParticleSystem->Life = 0.50f;
322 		ParticleSystem->IsSuppressed = true;
323 		ParticleSystem->ParticlesPerSec = 50;
324 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.4f, 0.75f, 0.15f, 0.0f, 0.2f);
325 		ParticleSystem->LightNeedDeviation = true;
326 		break;
327 	case 3:
328 		ParticleSystem->ColorStart = Violet;
329 		ParticleSystem->ColorEnd = LightViolet;
330 		ParticleSystem->AlphaStart = 0.60f;
331 		ParticleSystem->AlphaEnd = 0.10f;
332 		ParticleSystem->SizeStart = 0.5f;
333 		ParticleSystem->SizeVar = 0.05f;
334 		ParticleSystem->SizeEnd = 0.10f;
335 		ParticleSystem->Speed = 5.00f;
336 		ParticleSystem->SpeedVar = 5.00f;
337 		ParticleSystem->Theta = 30.00f;
338 		ParticleSystem->Life = 0.50f;
339 		ParticleSystem->IsSuppressed = true;
340 		ParticleSystem->ParticlesPerSec = 50;
341 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.25f, 0.25f, 1.0f, 0.0f, 0.2f);
342 		ParticleSystem->LightNeedDeviation = true;
343 		break;
344 	case 4:
345 		ParticleSystem->ColorStart = Turquoise;
346 		ParticleSystem->ColorEnd = LightSkyey;
347 		ParticleSystem->AlphaStart = 0.60f;
348 		ParticleSystem->AlphaEnd = 0.10f;
349 		ParticleSystem->SizeStart = 0.5f;
350 		ParticleSystem->SizeVar = 0.05f;
351 		ParticleSystem->SizeEnd = 0.10f;
352 		ParticleSystem->Speed = 5.00f;
353 		ParticleSystem->SpeedVar = 5.00f;
354 		ParticleSystem->Theta = 30.00f;
355 		ParticleSystem->Life = 0.50f;
356 		ParticleSystem->IsSuppressed = true;
357 		ParticleSystem->ParticlesPerSec = 50;
358 		ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.85f, 1.0f, 0.0f, 0.2f);
359 		ParticleSystem->LightNeedDeviation = true;
360 		break;
361 
362 	default:
363 		std::cerr << __func__ << "(): " << "wrong EngineType.\n";
364 		break;
365 	}
366 }
367 
368 /*
369  * Setup engines.
370  */
SetEarthSpaceFighterEngine(std::weak_ptr<cSpaceShip> & SpaceShip,const int EngineType)371 void SetEarthSpaceFighterEngine(std::weak_ptr<cSpaceShip> &SpaceShip, const int EngineType)
372 {
373 	auto sharedSpaceShip = SpaceShip.lock();
374 	if (!sharedSpaceShip)
375 		return;
376 
377 	if (EngineType == 0) {
378 		for (auto &tmpEngine : sharedSpaceShip->Engines) {
379 			vw_ReleaseParticleSystem(tmpEngine);
380 		}
381 
382 		if (!sharedSpaceShip->EnginesLeft.empty()) {
383 			for (auto &tmpEngineLeft : sharedSpaceShip->EnginesLeft) {
384 				vw_ReleaseParticleSystem(tmpEngineLeft);
385 			}
386 		}
387 
388 		if (!sharedSpaceShip->EnginesRight.empty()) {
389 			for (auto &tmpEngineRight : sharedSpaceShip->EnginesRight) {
390 				vw_ReleaseParticleSystem(tmpEngineRight);
391 			}
392 		}
393 
394 		sharedSpaceShip->MaxSpeed = 0.0f;
395 		sharedSpaceShip->MaxAcceler = 0.0f;
396 		sharedSpaceShip->MaxSpeedRotate = 0.0f;
397 		return;
398 	}
399 
400 	for (unsigned int i = 0; i < sharedSpaceShip->Engines.size(); i++) {
401 		vw_ReleaseParticleSystem(sharedSpaceShip->Engines[i]);
402 		sharedSpaceShip->Engines[i] = vw_CreateParticleSystem();
403 		if (auto sharedEngine = sharedSpaceShip->Engines[i].lock()) {
404 			CreateSpaceShipEngine(sharedEngine, EngineType);
405 			sharedEngine->SetStartLocation(sharedSpaceShip->EnginesLocation[i]);
406 			sharedEngine->Direction = sVECTOR3D{0.0f, 0.0f, -1.0f};
407 		}
408 	}
409 
410 	if (!sharedSpaceShip->EnginesLeft.empty()) {
411 		for (unsigned int i = 0; i < sharedSpaceShip->EnginesLeft.size(); i++) {
412 			vw_ReleaseParticleSystem(sharedSpaceShip->EnginesLeft[i]);
413 			sharedSpaceShip->EnginesLeft[i] = vw_CreateParticleSystem();
414 			if (auto sharedEngineLeft = sharedSpaceShip->EnginesLeft[i].lock()) {
415 				CreateRotateSpaceShipEngine(sharedEngineLeft, EngineType);
416 				sharedEngineLeft->SetStartLocation(sharedSpaceShip->EnginesLeftLocation[i]);
417 				sharedEngineLeft->Direction = sVECTOR3D{1.0f, 0.0f, 0.6f};
418 				sharedEngineLeft->IsSuppressed = true;
419 			}
420 		}
421 	}
422 
423 	if (!sharedSpaceShip->EnginesRight.empty()) {
424 		for (unsigned int i = 0; i < sharedSpaceShip->EnginesRight.size(); i++) {
425 			vw_ReleaseParticleSystem(sharedSpaceShip->EnginesRight[i]);
426 			sharedSpaceShip->EnginesRight[i] = vw_CreateParticleSystem();
427 			if (auto sharedEngineRight = sharedSpaceShip->EnginesRight[i].lock()) {
428 				CreateRotateSpaceShipEngine(sharedEngineRight, EngineType);
429 				sharedEngineRight->SetStartLocation(sharedSpaceShip->EnginesRightLocation[i]);
430 				sharedEngineRight->Direction = sVECTOR3D{-1.0f, 0.0f, 0.6f};
431 				sharedEngineRight->IsSuppressed = true;
432 			}
433 		}
434 	}
435 
436 	sharedSpaceShip->MaxSpeed = GetEnginePower(EngineType) * sharedSpaceShip->Engines.size();
437 	sharedSpaceShip->MaxAcceler = GetEngineAcceleration(EngineType) * sharedSpaceShip->Engines.size();
438 	sharedSpaceShip->MaxSpeedRotate = GetEngineRotatePower(EngineType) * sharedSpaceShip->Engines.size();
439 }
440 
441 /*
442  * Get texture for particular armor.
443  * Note, we use only 4 for player ship, but all 8 could be used by script.
444  */
GetArmorTexture(const int ArmorType)445 static GLtexture GetArmorTexture(const int ArmorType)
446 {
447 	switch (ArmorType) {
448 	case 0:
449 		return GetPreloadedTextureAsset("models/earthfighter/sf-text00.vw2d");
450 
451 	case 1:
452 		return GetPreloadedTextureAsset("models/earthfighter/sf-text04.vw2d");
453 
454 	case 2:
455 		return GetPreloadedTextureAsset("models/earthfighter/sf-text05.vw2d");
456 
457 	case 3:
458 		return GetPreloadedTextureAsset("models/earthfighter/sf-text07.vw2d");
459 
460 	case 4:
461 		return GetPreloadedTextureAsset("models/earthfighter/sf-text08.vw2d");
462 
463 	case 5:
464 		return GetPreloadedTextureAsset("models/earthfighter/sf-text09.vw2d");
465 
466 	case 6:
467 		return GetPreloadedTextureAsset("models/earthfighter/sf-text10.vw2d");
468 
469 	case 7:
470 		return GetPreloadedTextureAsset("models/earthfighter/sf-text06.vw2d");
471 
472 	default:
473 		std::cerr << __func__ << "(): " << "wrong ArmorType.\n";
474 		break;
475 	}
476 
477 	return 0;
478 }
479 
480 /*
481  * Get illumination texture for particular armor.
482  * Note, we use only 4 for player ship, but all 8 could be used by script.
483  */
GetArmorIllumTexture(const int ArmorType)484 static GLtexture GetArmorIllumTexture(const int ArmorType)
485 {
486 	switch (ArmorType) {
487 	case 0:
488 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum01.vw2d");
489 
490 	case 1:
491 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum02.vw2d");
492 
493 	case 2:
494 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum03.vw2d");
495 
496 	case 3:
497 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum03.vw2d");
498 
499 	case 4:
500 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum03.vw2d");
501 
502 	case 5:
503 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum02.vw2d");
504 
505 	case 6:
506 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum04.vw2d");
507 
508 	case 7:
509 		return GetPreloadedTextureAsset("models/earthfighter/sf-illum03.vw2d");
510 
511 	default:
512 		std::cerr << __func__ << "(): " << "wrong ArmorType.\n";
513 		break;
514 	}
515 
516 	return 0;
517 }
518 
519 /*
520  * Setup armor.
521  */
SetEarthSpaceFighterArmor(std::weak_ptr<cSpaceShip> & SpaceShip,const int ArmorType)522 void SetEarthSpaceFighterArmor(std::weak_ptr<cSpaceShip> &SpaceShip, const int ArmorType)
523 {
524 	auto sharedSpaceShip = SpaceShip.lock();
525 	if (!sharedSpaceShip)
526 		return;
527 
528 	for (unsigned int i = 0; i < sharedSpaceShip->Chunks.size(); i++) {
529 		sharedSpaceShip->Texture[i] = GetArmorTexture(ArmorType);
530 		sharedSpaceShip->TextureIllum[i] = GetArmorIllumTexture(ArmorType);
531 	}
532 }
533 
534 /*
535  * Get max and min weapon slot angle for particular ship.
536  */
GetShipWeaponSlotAngle(const int ShipNum,const int SlotNum,float & Min,float & Max)537 void GetShipWeaponSlotAngle(const int ShipNum, const int SlotNum, float &Min, float &Max)
538 {
539 	Min = 0.0f;
540 	Max = 0.0f;
541 
542 	switch (ShipNum) {
543 	case 1:
544 		switch (SlotNum) {
545 		case 0:
546 			Min = -45.0f;
547 			Max = 5.0f;
548 			break;
549 		case 1:
550 			Min = -5.0f;
551 			Max = 45.0f;
552 			break;
553 		case 2:
554 			Min = -45.0f;
555 			Max = 10.0f;
556 			break;
557 		case 3:
558 			Min = -10.0f;
559 			Max = 45.0f;
560 			break;
561 		case 4:
562 			Min = -30.0f;
563 			Max = 30.0f;
564 			break;
565 		}
566 		break;
567 	case 2:
568 		switch (SlotNum) {
569 		case 0:
570 			Min = -45.0f;
571 			Max = 5.0f;
572 			break;
573 		case 1:
574 			Min = -5.0f;
575 			Max = 45.0f;
576 			break;
577 		case 2:
578 			Min = -45.0f;
579 			Max = 10.0f;
580 			break;
581 		case 3:
582 			Min = -10.0f;
583 			Max = 45.0f;
584 			break;
585 		}
586 		break;
587 	case 3:
588 		switch (SlotNum) {
589 		case 0:
590 			Min = -45.0f;
591 			Max = 45.0f;
592 			break;
593 		case 1:
594 			Min = -20.0f;
595 			Max = 20.0f;
596 			break;
597 		case 2:
598 			Min = -20.0f;
599 			Max = 20.0f;
600 			break;
601 		}
602 		break;
603 	case 4:
604 		switch (SlotNum) {
605 		case 0:
606 			Min = -45.0f;
607 			Max = 10.0f;
608 			break;
609 		case 1:
610 			Min = -10.0f;
611 			Max = 45.0f;
612 			break;
613 		case 2:
614 			Min = -45.0f;
615 			Max = 10.0f;
616 			break;
617 		case 3:
618 			Min = -10.0f;
619 			Max = 45.0f;
620 			break;
621 		case 4:
622 			Min = -30.0f;
623 			Max = 30.0f;
624 			break;
625 		}
626 		break;
627 	case 5:
628 		switch (SlotNum) {
629 		case 0:
630 			Min = -45.0f;
631 			Max = 5.0f;
632 			break;
633 		case 1:
634 			Min = -5.0f;
635 			Max = 45.0f;
636 			break;
637 		}
638 		break;
639 	case 6:
640 		switch (SlotNum) {
641 		case 0:
642 			Min = -45.0f;
643 			Max = 5.0f;
644 			break;
645 		case 1:
646 			Min = -5.0f;
647 			Max = 45.0f;
648 			break;
649 		case 2:
650 			Min = -45.0f;
651 			Max = 10.0f;
652 			break;
653 		case 3:
654 			Min = -10.0f;
655 			Max = 45.0f;
656 			break;
657 		case 4:
658 			Min = -30.0f;
659 			Max = 30.0f;
660 			break;
661 		}
662 		break;
663 	case 7:
664 		switch (SlotNum) {
665 		case 0:
666 			Min = -10.0f;
667 			Max = 10.0f;
668 			break;
669 		case 1:
670 			Min = -45.0f;
671 			Max = 25.0f;
672 			break;
673 		case 2:
674 			Min = -25.0f;
675 			Max = 45.0f;
676 			break;
677 		case 3:
678 			Min = -45.0f;
679 			Max = 15.0f;
680 			break;
681 		case 4:
682 			Min = -15.0f;
683 			Max = 45.0f;
684 			break;
685 		}
686 		break;
687 	case 8:
688 		switch (SlotNum) {
689 		case 0:
690 			Min = -10.0f;
691 			Max = 10.0f;
692 			break;
693 		case 1:
694 			Min = -10.0f;
695 			Max = 10.0f;
696 			break;
697 		}
698 		break;
699 	case 9:
700 		switch (SlotNum) {
701 		case 0:
702 			Min = -10.0f;
703 			Max = 10.0f;
704 			break;
705 		case 1:
706 			Min = -10.0f;
707 			Max = 10.0f;
708 			break;
709 		}
710 		break;
711 	case 10:
712 		switch (SlotNum) {
713 		case 0:
714 			Min = -45.0f;
715 			Max = 10.0f;
716 			break;
717 		case 1:
718 			Min = -10.0f;
719 			Max = 45.0f;
720 			break;
721 		case 2:
722 			Min = -20.0f;
723 			Max = 5.0f;
724 			break;
725 		case 3:
726 			Min = -5.0f;
727 			Max = 20.0f;
728 			break;
729 		case 4:
730 			Min = -30.0f;
731 			Max = 30.0f;
732 			break;
733 		}
734 		break;
735 	case 11:
736 		switch (SlotNum) {
737 		case 0:
738 			Min = -30.0f;
739 			Max = 0.0f;
740 			break;
741 		case 1:
742 			Min = -0.0f;
743 			Max = 30.0f;
744 			break;
745 		case 2:
746 			Min = -30.0f;
747 			Max = 30.0f;
748 			break;
749 		}
750 		break;
751 	case 12:
752 		switch (SlotNum) {
753 		case 0:
754 			Min = -45.0f;
755 			Max = 25.0f;
756 			break;
757 		case 1:
758 			Min = -25.0f;
759 			Max = 45.0f;
760 			break;
761 		case 2:
762 			Min = -30.0f;
763 			Max = 30.0f;
764 			break;
765 		}
766 		break;
767 	case 13:
768 		switch (SlotNum) {
769 		case 0:
770 			Min = -10.0f;
771 			Max = 10.0f;
772 			break;
773 		case 1:
774 			Min = -45.0f;
775 			Max = 20.0f;
776 			break;
777 		case 2:
778 			Min = -20.0f;
779 			Max = 45.0f;
780 			break;
781 		case 3:
782 			Min = -45.0f;
783 			Max = 10.0f;
784 			break;
785 		case 4:
786 			Min = -10.0f;
787 			Max = 45.0f;
788 			break;
789 		}
790 		break;
791 	case 14:
792 		switch (SlotNum) {
793 		case 0:
794 			Min = -30.0f;
795 			Max = 5.0f;
796 			break;
797 		case 1:
798 			Min = -5.0f;
799 			Max = 30.0f;
800 			break;
801 		case 2:
802 			Min = -35.0f;
803 			Max = 5.0f;
804 			break;
805 		case 3:
806 			Min = -5.0f;
807 			Max = 35.0f;
808 			break;
809 		case 4:
810 			Min = -15.0f;
811 			Max = 15.0f;
812 			break;
813 		}
814 		break;
815 	case 15:
816 		switch (SlotNum) {
817 		case 0:
818 			Min = -45.0f;
819 			Max = 45.0f;
820 			break;
821 		case 1:
822 			Min = -45.0f;
823 			Max = 20.0f;
824 			break;
825 		case 2:
826 			Min = -20.0f;
827 			Max = 45.0f;
828 			break;
829 		}
830 		break;
831 	case 16:
832 		switch (SlotNum) {
833 		case 0:
834 			Min = -20.0f;
835 			Max = 20.0f;
836 			break;
837 		case 1:
838 			Min = -30.0f;
839 			Max = 0.0f;
840 			break;
841 		case 2:
842 			Min = -0.0f;
843 			Max = 30.0f;
844 			break;
845 		}
846 		break;
847 	case 17:
848 		switch (SlotNum) {
849 		case 0:
850 			Min = -30.0f;
851 			Max = 5.0f;
852 			break;
853 		case 1:
854 			Min = -5.0f;
855 			Max = 30.0f;
856 			break;
857 		case 2:
858 			Min = -45.0f;
859 			Max = 10.0f;
860 			break;
861 		case 3:
862 			Min = -10.0f;
863 			Max = 45.0f;
864 			break;
865 		case 4:
866 			Min = -20.0f;
867 			Max = 20.0f;
868 			break;
869 		}
870 		break;
871 	case 18:
872 		switch (SlotNum) {
873 		case 0:
874 			Min = -20.0f;
875 			Max = 20.0f;
876 			break;
877 		case 1:
878 			Min = -20.0f;
879 			Max = 20.0f;
880 			break;
881 		case 2:
882 			Min = -25.0f;
883 			Max = 5.0f;
884 			break;
885 		case 3:
886 			Min = -5.0f;
887 			Max = 25.0f;
888 			break;
889 		}
890 		break;
891 	case 19:
892 		switch (SlotNum) {
893 		case 0:
894 			Min = -45.0f;
895 			Max = 45.0f;
896 			break;
897 		case 1:
898 			Min = -45.0f;
899 			Max = 10.0f;
900 			break;
901 		case 2:
902 			Min = -10.0f;
903 			Max = 45.0f;
904 			break;
905 		}
906 		break;
907 	case 20:
908 		switch (SlotNum) {
909 		case 0:
910 			Min = -10.0f;
911 			Max = 10.0f;
912 			break;
913 		case 1:
914 			Min = -10.0f;
915 			Max = 10.0f;
916 			break;
917 		case 2:
918 			Min = -45.0f;
919 			Max = 20.0f;
920 			break;
921 		case 3:
922 			Min = -20.0f;
923 			Max = 45.0f;
924 			break;
925 		}
926 		break;
927 	case 21:
928 		switch (SlotNum) {
929 		case 0:
930 			Min = -25.0f;
931 			Max = 0.0f;
932 			break;
933 		case 1:
934 			Min = -0.0f;
935 			Max = 25.0f;
936 			break;
937 		case 2:
938 			Min = -20.0f;
939 			Max = 20.0f;
940 			break;
941 		}
942 		break;
943 	case 22:
944 		switch (SlotNum) {
945 		case 0:
946 			Min = -25.0f;
947 			Max = 25.0f;
948 			break;
949 		}
950 		break;
951 
952 	default:
953 		std::cerr << __func__ << "(): " << "wrong ShipNum.\n";
954 		break;
955 	}
956 }
957 
958 /*
959  * Get armor for particular ship.
960  */
GetShipArmor(const int SpaceShipNum)961 float GetShipArmor(const int SpaceShipNum)
962 {
963 	return PresetEarthSpaceFighterData[SpaceShipNum - 1].Armor;
964 }
965 
966 /*
967  * Constructor.
968  */
cEarthSpaceFighter(const int SpaceShipNum)969 cEarthSpaceFighter::cEarthSpaceFighter(const int SpaceShipNum)
970 {
971 	if ((SpaceShipNum <= 0) ||
972 	    (static_cast<unsigned>(SpaceShipNum) > PresetEarthSpaceFighterData.size())) {
973 		std::cerr << __func__ << "(): "
974 			  << "Could not init cEarthSpaceFighter object with Number "
975 			  << SpaceShipNum << "\n";
976 		return;
977 	}
978 
979 	ObjectStatus = eObjectStatus::Ally;
980 	ObjectType = eObjectType::EarthFighter;
981 	InternalType = SpaceShipNum;
982 	PromptDrawDist2 = 100.0f;
983 
984 	ArmorCurrentStatus = ArmorInitialStatus =
985 			PresetEarthSpaceFighterData[SpaceShipNum - 1].Armor; // GameEnemyArmorPenalty for enemies only
986 	LoadObjectData(PresetEarthSpaceFighterData[SpaceShipNum - 1].Name, *this);
987 
988 	Engines.resize(PresetEarthSpaceFighterData[SpaceShipNum - 1].EngineQuantity);
989 	EnginesLocation.resize(Engines.size());
990 
991 	EnginesLeftLocation.resize(1);
992 	EnginesLeft.resize(1);
993 
994 	EnginesRightLocation.resize(1);
995 	EnginesRight.resize(1);
996 
997 	switch (SpaceShipNum) {
998 	case 1:
999 		WeaponSlots.reserve(5);
1000 		WeaponSlots.emplace_back(1, sVECTOR3D{4.4f, -0.1f, -6.0f});
1001 		WeaponSlots.emplace_back(1, sVECTOR3D{-4.4f, -0.1f, -6.0f});
1002 		WeaponSlots.emplace_back(1, sVECTOR3D{1.9f, -1.25f, 6.5f});
1003 		WeaponSlots.emplace_back(1, sVECTOR3D{-1.9f, -1.25f, 6.5f});
1004 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -1.20f, 1.0f});
1005 		EnginesLocation[0] = sVECTOR3D{3.0f, -1.2f, -4.7f};
1006 		EnginesLocation[1] = sVECTOR3D{-3.0f, -1.2f, -4.7f};
1007 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, -0.7f, 3.7f};
1008 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, -0.7f, 3.7f};
1009 		break;
1010 
1011 	case 2:
1012 		WeaponSlots.reserve(4);
1013 		WeaponSlots.emplace_back(1, sVECTOR3D{3.45f, 1.03f, -8.5f});
1014 		WeaponSlots.emplace_back(1, sVECTOR3D{-3.45f, 1.03f, -8.5f});
1015 		WeaponSlots.emplace_back(1, sVECTOR3D{1.7f, -1.03f, 3.9f});
1016 		WeaponSlots.emplace_back(1, sVECTOR3D{-1.7f, -1.03f, 3.9f});
1017 		EnginesLocation[0] = sVECTOR3D{4.9f, -1.1f, -8.9f};
1018 		EnginesLocation[1] = sVECTOR3D{-4.9f, -1.1f, -8.9f};
1019 		EnginesLocation[2] = sVECTOR3D{0.75f, 0.7f, -9.6f};
1020 		EnginesLocation[3] = sVECTOR3D{-0.75f, 0.7f, -9.6f};
1021 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, -0.7f, 5.7f};
1022 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, -0.7f, 5.7f};
1023 		break;
1024 
1025 	case 3:
1026 		WeaponSlots.reserve(3);
1027 		WeaponSlots.emplace_back(5, sVECTOR3D{0.0f, -1.75f, 3.5f});
1028 		WeaponSlots.emplace_back(1, sVECTOR3D{7.15f, -0.38f, -4.4f});
1029 		WeaponSlots.emplace_back(1, sVECTOR3D{-7.15f, -0.38f, -4.4f});
1030 		EnginesLocation[0] = sVECTOR3D{4.4f, -3.0f, -9.7f};
1031 		EnginesLocation[1] = sVECTOR3D{-4.4f, -3.0f, -9.7f};
1032 		EnginesLocation[2] = sVECTOR3D{4.4f, 3.0f, -9.7f};
1033 		EnginesLocation[3] = sVECTOR3D{-4.4f, 3.0f, -9.7f};
1034 		EnginesLeftLocation[0] = sVECTOR3D{0.8f, -1.6f, 8.7f};
1035 		EnginesRightLocation[0] = sVECTOR3D{-0.8f, -1.6f, 8.7f};
1036 		break;
1037 
1038 	case 4:
1039 		WeaponSlots.reserve(5);
1040 		WeaponSlots.emplace_back(1, sVECTOR3D{4.10f, 1.4f, -2.5f});
1041 		WeaponSlots.emplace_back(1, sVECTOR3D{-4.10f, 1.4f, -2.5f});
1042 		WeaponSlots.emplace_back(1, sVECTOR3D{5.10f, -1.2f, -2.5f});
1043 		WeaponSlots.emplace_back(1, sVECTOR3D{-5.10f, -1.2f, -2.5f});
1044 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -1.5f, 5.3f});
1045 		EnginesLocation[0] = sVECTOR3D{0.8f, 0.1f, -9.6f};
1046 		EnginesLocation[1] = sVECTOR3D{-0.8f, 0.1f, -9.6f};
1047 		EnginesLeftLocation[0] = sVECTOR3D{1.6f, -0.9f, 5.7f};
1048 		EnginesRightLocation[0] = sVECTOR3D{-1.6f, -0.9f, 5.7f};
1049 		break;
1050 
1051 	case 5:
1052 		WeaponSlots.reserve(2);
1053 		WeaponSlots.emplace_back(2, sVECTOR3D{4.0f, -0.5f, 1.0f});
1054 		WeaponSlots.emplace_back(2, sVECTOR3D{-4.0f, -0.5f, 1.0f});
1055 		EnginesLocation[0] = sVECTOR3D{6.72f, -0.28f, -7.98f};
1056 		EnginesLocation[1] = sVECTOR3D{-6.72f, -0.28f, -7.98f};
1057 		EnginesLocation[2] = sVECTOR3D{6.72f, -1.96f, -7.28f};
1058 		EnginesLocation[3] = sVECTOR3D{-6.72f, -1.96f, -7.28f};
1059 		EnginesLeftLocation[0] = sVECTOR3D{1.4f, 0.0f, 3.92f};
1060 		EnginesRightLocation[0] = sVECTOR3D{-1.4f, 0.0f, 3.92f};
1061 		break;
1062 
1063 	case 6:
1064 		WeaponSlots.reserve(5);
1065 		WeaponSlots.emplace_back(2, sVECTOR3D{2.80f, 0.25f, -7.0f});
1066 		WeaponSlots.emplace_back(2, sVECTOR3D{-2.80f, 0.25f, -7.0f});
1067 		WeaponSlots.emplace_back(1, sVECTOR3D{5.20f, 0.6f, -6.0f});
1068 		WeaponSlots.emplace_back(1, sVECTOR3D{-5.20f, 0.6f, -6.0f});
1069 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -1.3f, 2.6f});
1070 		EnginesLocation[0] = sVECTOR3D{0.6f, 0.45f, -9.9f};
1071 		EnginesLocation[1] = sVECTOR3D{-0.6f, 0.45f, -9.9f};
1072 		EnginesLeftLocation[0] = sVECTOR3D{1.6f, -0.9f, 4.7f};
1073 		EnginesRightLocation[0] = sVECTOR3D{-1.6f, -0.9f, 4.7f};
1074 		break;
1075 
1076 	case 7:
1077 		WeaponSlots.reserve(5);
1078 		WeaponSlots.emplace_back(5, sVECTOR3D{0.0f, -0.2f, 0.0f});
1079 		WeaponSlots.emplace_back(1, sVECTOR3D{4.3f, -1.25f, -1.4f});
1080 		WeaponSlots.emplace_back(1, sVECTOR3D{-4.3f, -1.25f, -1.4f});
1081 		WeaponSlots.emplace_back(1, sVECTOR3D{8.2f, -0.75f, -3.6f});
1082 		WeaponSlots.emplace_back(1, sVECTOR3D{-8.2f, -0.75f, -3.6f});
1083 		EnginesLocation[0] = sVECTOR3D{3.75f, -0.5f, -10.9f};
1084 		EnginesLocation[1] = sVECTOR3D{0.0f, 0.4f, -8.3f};
1085 		EnginesLocation[2] = sVECTOR3D{-3.75f, -0.5f, -10.9f};
1086 		EnginesLeftLocation[0] = sVECTOR3D{1.4f, 0.1f, 1.1f};
1087 		EnginesRightLocation[0] = sVECTOR3D{-1.4f, 0.1f, 1.1f};
1088 		break;
1089 
1090 	case 8:
1091 		WeaponSlots.reserve(2);
1092 		WeaponSlots.emplace_back(1, sVECTOR3D{1.0f, -0.3f, 0.4f});
1093 		WeaponSlots.emplace_back(1, sVECTOR3D{-1.0f, -0.3f, 0.4f});
1094 		EnginesLocation[0] = sVECTOR3D{3.5f, 1.4f, -7.4f};
1095 		EnginesLocation[1] = sVECTOR3D{-3.5f, 1.4f, -7.4f};
1096 		EnginesLocation[2] = sVECTOR3D{3.65f, 0.5f, -7.9f};
1097 		EnginesLocation[3] = sVECTOR3D{-3.65f, 0.5f, -7.9f};
1098 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, 0.0f, 2.4f};
1099 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, 0.0f, 2.4f};
1100 		break;
1101 
1102 	case 9:
1103 		WeaponSlots.reserve(2);
1104 		WeaponSlots.emplace_back(2, sVECTOR3D{1.2f, 0.2f, 1.6f});
1105 		WeaponSlots.emplace_back(2, sVECTOR3D{-1.2f, 0.2f, 1.6f});
1106 		EnginesLocation[0] = sVECTOR3D{3.30f, -1.20f, -0.7f};
1107 		EnginesLocation[1] = sVECTOR3D{-3.30f, -1.20f, -0.7f};
1108 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, 0.2f, 2.2f};
1109 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, 0.2f, 2.2f};
1110 		break;
1111 
1112 	case 10:
1113 		WeaponSlots.reserve(5);
1114 		WeaponSlots.emplace_back(2, sVECTOR3D{5.05f, -1.8f, -1.7f});
1115 		WeaponSlots.emplace_back(2, sVECTOR3D{-5.05f, -1.8f, -1.7f});
1116 		WeaponSlots.emplace_back(2, sVECTOR3D{2.55f, -0.7f, -0.7f});
1117 		WeaponSlots.emplace_back(2, sVECTOR3D{-2.55f, -0.7f, -0.7f});
1118 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -0.9f, 6.1f});
1119 		EnginesLocation[0] = sVECTOR3D{0.8f, 0.55f, -9.9f};
1120 		EnginesLocation[1] = sVECTOR3D{-0.8f, 0.55f, -9.9f};
1121 		EnginesLeftLocation[0] = sVECTOR3D{1.6f, -0.4f, 5.3f};
1122 		EnginesRightLocation[0] = sVECTOR3D{-1.6f, -0.4f, 5.3f};
1123 		break;
1124 
1125 	case 11:
1126 		WeaponSlots.reserve(3);
1127 		WeaponSlots.emplace_back(2, sVECTOR3D{2.0f, -0.55f, -2.2f});
1128 		WeaponSlots.emplace_back(2, sVECTOR3D{-2.0f, -0.55f, -2.2f});
1129 		WeaponSlots.emplace_back(1, sVECTOR3D{0.0f, -0.7f, 2.2f});
1130 		EnginesLocation[0] = sVECTOR3D{4.35f, -0.35f, -4.4f};
1131 		EnginesLocation[1] = sVECTOR3D{-4.35f, -0.35f, -4.4f};
1132 		EnginesLeftLocation[0] = sVECTOR3D{1.5f, -0.6f, 2.0f};
1133 		EnginesRightLocation[0] = sVECTOR3D{-1.5f, -0.6f, 2.0f};
1134 		break;
1135 
1136 	case 12:
1137 		WeaponSlots.reserve(3);
1138 		WeaponSlots.emplace_back(2, sVECTOR3D{2.25f, -0.85f, 3.3f});
1139 		WeaponSlots.emplace_back(2, sVECTOR3D{-2.25f, -0.85f, 3.3f});
1140 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -0.35f, 2.8f});
1141 		EnginesLocation[0] = sVECTOR3D{4.8f, -1.2f, -2.8f};
1142 		EnginesLocation[1] = sVECTOR3D{-4.8f, -1.2f, -2.8f};
1143 		EnginesLeftLocation[0] = sVECTOR3D{1.2f, -0.2f, 6.3f};
1144 		EnginesRightLocation[0] = sVECTOR3D{-1.2f, -0.2f, 6.3f};
1145 		break;
1146 
1147 	case 13:
1148 		WeaponSlots.reserve(5);
1149 		WeaponSlots.emplace_back(5, sVECTOR3D{0.0f, -2.15f, -4.4f});
1150 		WeaponSlots.emplace_back(4, sVECTOR3D{7.2f, 1.85f, -5.6f});
1151 		WeaponSlots.emplace_back(4, sVECTOR3D{-7.2f, 1.85f, -5.6f});
1152 		WeaponSlots.emplace_back(1, sVECTOR3D{3.05f, -1.95f, -0.4f});
1153 		WeaponSlots.emplace_back(1, sVECTOR3D{-3.05f, -1.95f, -0.4f});
1154 		EnginesLocation[0] = sVECTOR3D{2.2f, -1.35f, -9.8f};
1155 		EnginesLocation[1] = sVECTOR3D{-2.2f, -1.35f, -9.8f};
1156 		EnginesLocation[2] = sVECTOR3D{1.1f, -1.0f, -9.8f};
1157 		EnginesLocation[3] = sVECTOR3D{-1.1f, -1.0f, -9.8f};
1158 		EnginesLeftLocation[0] = sVECTOR3D{1.4f, -0.1f, 0.5f};
1159 		EnginesRightLocation[0] = sVECTOR3D{-1.4f, -0.1f, 0.5f};
1160 		break;
1161 
1162 	case 14:
1163 		WeaponSlots.reserve(5);
1164 		WeaponSlots.emplace_back(2, sVECTOR3D{1.70f, -1.1f, 5.5f});
1165 		WeaponSlots.emplace_back(2, sVECTOR3D{-1.70f, -1.1f, 5.5f});
1166 		WeaponSlots.emplace_back(2, sVECTOR3D{4.1f, 0.2f, -6.3f});
1167 		WeaponSlots.emplace_back(2, sVECTOR3D{-4.1f, 0.2f, -6.3f});
1168 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -0.9f, 3.3f});
1169 		EnginesLocation[0] = sVECTOR3D{0.85f, 0.1f, -8.1f};
1170 		EnginesLocation[1] = sVECTOR3D{-0.85f, 0.1f, -8.1f};
1171 		EnginesLeftLocation[0] = sVECTOR3D{1.3f, -0.7f, 6.3f};
1172 		EnginesRightLocation[0] = sVECTOR3D{-1.3f, -0.7f, 6.3f};
1173 		break;
1174 
1175 	case 15:
1176 		WeaponSlots.reserve(3);
1177 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -0.7f, 1.3f});
1178 		WeaponSlots.emplace_back(3, sVECTOR3D{7.1f, -0.2f, -5.8f});
1179 		WeaponSlots.emplace_back(3, sVECTOR3D{-7.1f, -0.2f, -5.8f});
1180 		EnginesLocation[0] = sVECTOR3D{4.75f, -0.5f, -7.2f};
1181 		EnginesLocation[1] = sVECTOR3D{-4.75f, -0.5f, -7.2f};
1182 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, -0.6f, 6.25f};
1183 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, -0.6f, 6.25f};
1184 		break;
1185 
1186 	case 16:
1187 		WeaponSlots.reserve(3);
1188 		WeaponSlots.emplace_back(3, sVECTOR3D{0.0f, -1.2f, 7.7f});
1189 		WeaponSlots.emplace_back(4, sVECTOR3D{2.0f, -1.05f, 0.4f});
1190 		WeaponSlots.emplace_back(4, sVECTOR3D{-2.0f, -1.05f, 0.4f});
1191 		EnginesLocation[0] = sVECTOR3D{3.8f, -0.75f, -11.4f};
1192 		EnginesLocation[1] = sVECTOR3D{-3.8f, -0.75f, -11.4f};
1193 		EnginesLocation[2] = sVECTOR3D{3.5f, 0.85f, -10.85f};
1194 		EnginesLocation[3] = sVECTOR3D{-3.5f, 0.85f, -10.85f};
1195 		EnginesLeftLocation[0] = sVECTOR3D{1.6f, -0.6f, 6.25f};
1196 		EnginesRightLocation[0] = sVECTOR3D{-1.6f, -0.6f, 6.25f};
1197 		break;
1198 
1199 	case 17:
1200 		WeaponSlots.reserve(5);
1201 		WeaponSlots.emplace_back(3, sVECTOR3D{3.10f, 0.2f, -4.6f});
1202 		WeaponSlots.emplace_back(3, sVECTOR3D{-3.10f, 0.2f, -4.6f});
1203 		WeaponSlots.emplace_back(2, sVECTOR3D{5.85f, -0.5f, -5.6f});
1204 		WeaponSlots.emplace_back(2, sVECTOR3D{-5.85f, -0.5f, -5.6f});
1205 		WeaponSlots.emplace_back(4, sVECTOR3D{0.0f, -0.5f, -0.5f});
1206 		EnginesLocation[0] = sVECTOR3D{0.65f, 0.2f, -8.2f};
1207 		EnginesLocation[1] = sVECTOR3D{-0.65f, 0.2f, -8.2f};
1208 		EnginesLeftLocation[0] = sVECTOR3D{1.4f, -0.5f, 6.25f};
1209 		EnginesRightLocation[0] = sVECTOR3D{-1.4f, -0.5f, 6.25f};
1210 		break;
1211 
1212 	case 18:
1213 		WeaponSlots.reserve(4);
1214 		WeaponSlots.emplace_back(5, sVECTOR3D{1.7f, -2.5f, -4.4f});
1215 		WeaponSlots.emplace_back(5, sVECTOR3D{-1.7f, -2.5f, -4.4f});
1216 		WeaponSlots.emplace_back(3, sVECTOR3D{5.1f, -1.0f, -5.4f});
1217 		WeaponSlots.emplace_back(3, sVECTOR3D{-5.1f, -1.0f, -5.4f});
1218 		EnginesLocation[0] = sVECTOR3D{7.5f, 0.15f, -9.1f};
1219 		EnginesLocation[1] = sVECTOR3D{-7.5f, 0.15f, -9.1f};
1220 		EnginesLocation[2] = sVECTOR3D{7.7f, -1.15f, -9.6f};
1221 		EnginesLocation[3] = sVECTOR3D{-7.7f, -1.15f, -9.6f};
1222 		EnginesLeftLocation[0] = sVECTOR3D{1.9f, -1.6f, 6.25f};
1223 		EnginesRightLocation[0] = sVECTOR3D{-1.9f, -1.6f, 6.25f};
1224 		break;
1225 
1226 	case 19:
1227 		WeaponSlots.reserve(3);
1228 		WeaponSlots.emplace_back(2, sVECTOR3D{0.0f, -0.75f, 0.0f});
1229 		WeaponSlots.emplace_back(2, sVECTOR3D{4.7f, -0.4f, -5.0f});
1230 		WeaponSlots.emplace_back(2, sVECTOR3D{-4.7f, -0.4f, -5.0f});
1231 		EnginesLocation[0] = sVECTOR3D{6.3f, 0.60f, -8.1f};
1232 		EnginesLocation[1] = sVECTOR3D{-6.3f, 0.60f, -8.1f};
1233 		EnginesLocation[2] = sVECTOR3D{6.7f, -0.60f, -8.8f};
1234 		EnginesLocation[3] = sVECTOR3D{-6.7f, -0.60f, -8.8f};
1235 		EnginesLeftLocation[0] = sVECTOR3D{1.45f, 0.05f, 5.0f};
1236 		EnginesRightLocation[0] = sVECTOR3D{-1.45f, 0.05f, 5.0f};
1237 		break;
1238 
1239 	case 20:
1240 		WeaponSlots.reserve(4);
1241 		WeaponSlots.emplace_back(3, sVECTOR3D{0.80f, -0.8f, -2.3f});
1242 		WeaponSlots.emplace_back(3, sVECTOR3D{-0.80f, -0.8f, -2.3f});
1243 		WeaponSlots.emplace_back(4, sVECTOR3D{3.9f, -1.25f, -3.2f});
1244 		WeaponSlots.emplace_back(4, sVECTOR3D{-3.9f, -1.25f, -3.2f});
1245 		EnginesLocation[0] = sVECTOR3D{3.45f, -0.3f, -7.3f};
1246 		EnginesLocation[1] = sVECTOR3D{-3.45f, -0.3f, -7.3f};
1247 		EnginesLocation[2] = sVECTOR3D{4.55f, -0.5f, -7.0f};
1248 		EnginesLocation[3] = sVECTOR3D{-4.55f, -0.5f, -7.0f};
1249 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, -0.4f, 1.45f};
1250 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, -0.4f, 1.45f};
1251 		break;
1252 
1253 	case 21:
1254 		WeaponSlots.reserve(3);
1255 		WeaponSlots.emplace_back(2, sVECTOR3D{2.05f, -0.22f, -1.2f});
1256 		WeaponSlots.emplace_back(2, sVECTOR3D{-2.05f, -0.22f, -1.2f});
1257 		WeaponSlots.emplace_back(2, sVECTOR3D{0.0f, -0.5f, 0.5f});
1258 		EnginesLocation[0] = sVECTOR3D{0.7f, 0.0f, -4.4f};
1259 		EnginesLocation[1] = sVECTOR3D{-0.7f, 0.0f, -4.4f};
1260 		EnginesLeftLocation[0] = sVECTOR3D{1.0f, -0.4f, 3.0f};
1261 		EnginesRightLocation[0] = sVECTOR3D{-1.0f, -0.4f, 3.0f};
1262 		break;
1263 
1264 	case 22:
1265 		WeaponSlots.emplace_back(3, sVECTOR3D{0.0f, 0.05f, 3.6f});
1266 		EnginesLocation[0] = sVECTOR3D{0.0f, 0.3f, -5.2f};
1267 		EnginesLeftLocation[0] = sVECTOR3D{1.9f, -0.3f, 2.6f};
1268 		EnginesRightLocation[0] = sVECTOR3D{-1.9f, -0.3f, 2.6f};
1269 		break;
1270 	}
1271 
1272 	// make sure, that we have all weapon slots properly sorted, since for player's ship we
1273 	// need this in weaponry menu and HUD
1274 	auto comparison = [] (const sShipWeaponSlot &A, const sShipWeaponSlot &B) {
1275 		if (A.Location.z == B.Location.z) {
1276 			// for pair, we should have fixed order of weapon slots by X
1277 			if (std::fabs(A.Location.x) == std::fabs(B.Location.x))
1278 				return A.Location.x > B.Location.x;
1279 			// closest to center by X weapon slots should be first
1280 			return std::fabs(A.Location.x) < std::fabs(B.Location.x);
1281 		}
1282 
1283 		return A.Location.z > B.Location.z;
1284 	};
1285 	std::sort(WeaponSlots.begin(), WeaponSlots.end(), comparison);
1286 }
1287 
1288 } // astromenace namespace
1289 } // viewizard namespace
1290