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 // FIXME ostringstream is not so fast, move all string initialization into setup,
29 //       all ostringstream-related code should be called only one time in init
30 
31 // TODO translate comments
32 
33 #include "../game.h"
34 #include "../config/config.h"
35 #include "../ui/font.h"
36 #include "../assets/texture.h"
37 #include "../object3d/space_ship/space_ship.h"
38 #include <sstream>
39 #include <iomanip>
40 
41 // NOTE switch to nested namespace definition (namespace A::B::C { ... }) (since C++17)
42 namespace viewizard {
43 namespace astromenace {
44 
45 extern std::weak_ptr<cSpaceShip> WorkshopFighterGame;
46 extern std::weak_ptr<cSpaceShip> WorkshopNewFighter;
47 extern int	CurrentWorkshopNewFighter;
48 extern int	CurrentWorkshopNewWeapon;
49 extern float CurrentAlert2;
50 extern float CurrentAlert3;
51 
52 void WorkshopDrawShip(std::weak_ptr<cSpaceShip> &SpaceShip, int Mode);
53 void WorkshopCreateNewShip();
54 int GetSystemCost(int Num);
55 int GetWeaponCost(int Num, int Ammo, int AmmoStart);
56 int GetWeaponBaseCost(int Num);
57 
58 // что рисовать в диалоге 6,7,8
59 extern std::weak_ptr<cSpaceShip> DialogSpaceShip;
60 
61 
62 
63 
64 
65 
66 //------------------------------------------------------------------------------------
67 // название корабля
68 //------------------------------------------------------------------------------------
GetWorkshopShipName(int Num)69 const char *GetWorkshopShipName(int Num)
70 {
71 	switch (Num) {
72 	case 1:
73 		return "Cobra";
74 	case 2:
75 		return "SpaceEagle";
76 	case 3:
77 		return "FireStorm";
78 	case 4:
79 		return "Hedgehog";
80 	case 5:
81 		return "Thunder";
82 	case 6:
83 		return "Excalibur";
84 	case 7:
85 		return "DarkStar";
86 	case 8:
87 		return "Scorpion";
88 	case 9:
89 		return "Runner";
90 	case 10:
91 		return "Kronos";
92 	case 11:
93 		return "Chameleon";
94 	case 12:
95 		return "Falcon";
96 	case 13:
97 		return "DeathRipple";
98 	case 14:
99 		return "AstroSword";
100 	case 15:
101 		return "Pulser";
102 	case 16:
103 		return "ClumsyMace";
104 	case 17:
105 		return "Raptor";
106 	case 18:
107 		return "Destroyer";
108 	case 19:
109 		return "AstroSpear";
110 	case 20:
111 		return "Mite";
112 	case 21:
113 		return "Viper";
114 	case 22:
115 		return "BlackIce";
116 
117 	default:
118 		std::cerr << __func__ << "(): " << "wrong Num.\n";
119 		break;
120 	}
121 
122 	return nullptr;
123 }
124 
125 
126 
127 
128 //------------------------------------------------------------------------------------
129 // тип корабля
130 //------------------------------------------------------------------------------------
GetShipGroupTitle(int Num)131 const char *GetShipGroupTitle(int Num)
132 {
133 	switch (Num) {
134 	case 1:
135 	case 4:
136 	case 6:
137 	case 10:
138 	case 12:
139 	case 14:
140 	case 15:
141 	case 17:
142 	case 20:
143 		return "Fighter";
144 	case 2:
145 	case 5:
146 	case 19:
147 		return "Interceptor";
148 	case 3:
149 	case 16:
150 	case 18:
151 		return "Bomber";
152 	case 7:
153 	case 13:
154 		return "Attack Ship";
155 	case 8:
156 	case 9:
157 	case 11:
158 	case 21:
159 	case 22:
160 		return "Scout";
161 
162 	default:
163 		std::cerr << __func__ << "(): " << "wrong Num.\n";
164 		break;
165 	}
166 
167 	return nullptr;
168 }
169 
170 
171 
172 //------------------------------------------------------------------------------------
173 // стоимость корпуса
174 //------------------------------------------------------------------------------------
GetWorkshopShipCost(int Num)175 int GetWorkshopShipCost(int Num)
176 {
177 	switch (Num) {
178 	case 1:
179 		return 1100;
180 	case 2:
181 		return 900;
182 	case 3:
183 		return 1500;
184 	case 4:
185 		return 1300;
186 	case 5:
187 		return 1350;
188 	case 6:
189 		return 2400;
190 	case 7:
191 		return 3000;
192 	case 8:
193 		return 3500;
194 	case 9:
195 		return 4000;
196 	case 10:
197 		return 6000;
198 	case 11:
199 		return 4500;
200 	case 12:
201 		return 5000;
202 	case 13:
203 		return 9000;
204 	case 14:
205 		return 7500;
206 	case 15:
207 		return 7000;
208 	case 16:
209 		return 9000;
210 	case 17:
211 		return 10000;
212 	case 18:
213 		return 12000;
214 	case 19:
215 		return 5000;
216 	case 20:
217 		return 9000;
218 	case 21:
219 		return 10000;
220 	case 22:
221 		return 8000;
222 
223 	default:
224 		std::cerr << __func__ << "(): " << "wrong Num.\n";
225 		break;
226 	}
227 
228 	return 0;
229 }
230 
231 
232 
233 
234 
235 
GetWorkshopShipRepairCost(int Num,std::weak_ptr<cSpaceShip> & Fighter)236 int GetWorkshopShipRepairCost(int Num, std::weak_ptr<cSpaceShip> &Fighter)
237 {
238 	int ShipCost = GetWorkshopShipCost(Num) * GameConfig().Profile[CurrentProfile].ShipHullUpgrade;
239 	// расчет стоимости ремонта корабля
240 	if (auto sharedFighter = Fighter.lock())
241 		ShipCost -= (int)(ShipCost * (sharedFighter->ArmorCurrentStatus / sharedFighter->ArmorInitialStatus));
242 	return ShipCost;
243 }
244 
245 
246 
247 
248 
249 
GetWorkshopShipFullCost(int Num,std::weak_ptr<cSpaceShip> & Fighter)250 int GetWorkshopShipFullCost(int Num, std::weak_ptr<cSpaceShip> &Fighter)
251 {
252 	// полная стоимость корпуса корабля с повреждениями корабля
253 	int ShipCost = GetWorkshopShipCost(Num) * GameConfig().Profile[CurrentProfile].ShipHullUpgrade -
254 		       GetWorkshopShipRepairCost(Num, Fighter);
255 
256 
257 	// прибавить стоимость оружия
258 	if (auto sharedWorkshopFighterGame = WorkshopFighterGame.lock()) {
259 		if (!sharedWorkshopFighterGame->WeaponSlots.empty()) {
260 			for (auto &tmpWeaponSlot : sharedWorkshopFighterGame->WeaponSlots) {
261 				if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
262 					ShipCost += GetWeaponCost(sharedWeapon->InternalType,
263 								  sharedWeapon->Ammo,
264 								  sharedWeapon->AmmoStart);
265 			}
266 		}
267 	}
268 
269 	// прибавить стоимость систем
270 	if (GameConfig().Profile[CurrentProfile].EngineSystem)
271 		ShipCost += GetSystemCost(GameConfig().Profile[CurrentProfile].EngineSystem);
272 	if (GameConfig().Profile[CurrentProfile].PowerSystem)
273 		ShipCost += GetSystemCost(GameConfig().Profile[CurrentProfile].PowerSystem + 4);
274 	if (GameConfig().Profile[CurrentProfile].TargetingSystem)
275 		ShipCost += GetSystemCost(GameConfig().Profile[CurrentProfile].TargetingSystem + 8);
276 	if (GameConfig().Profile[CurrentProfile].TargetingMechanicSystem)
277 		ShipCost += GetSystemCost(GameConfig().Profile[CurrentProfile].TargetingMechanicSystem + 12);
278 	if (GameConfig().Profile[CurrentProfile].AdvancedProtectionSystem)
279 		ShipCost += GetSystemCost(GameConfig().Profile[CurrentProfile].AdvancedProtectionSystem + 16);
280 
281 	return ShipCost;
282 }
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 //------------------------------------------------------------------------------------
293 // создание корабля игрока при покупке нового корпуса
294 //------------------------------------------------------------------------------------
WorkshopCreateBuyShip()295 void WorkshopCreateBuyShip()
296 {
297 	// продаем все оружие и все системы
298 	// 1 - Системы
299 	int EngineSystem = GameConfig().Profile[CurrentProfile].EngineSystem;
300 	if (GameConfig().Profile[CurrentProfile].EngineSystem)
301 		ChangeGameConfig().Profile[CurrentProfile].Money += GetSystemCost(GameConfig().Profile[CurrentProfile].EngineSystem);
302 	ChangeGameConfig().Profile[CurrentProfile].EngineSystem = 0;
303 
304 	int PowerSystem = GameConfig().Profile[CurrentProfile].PowerSystem;
305 	if (GameConfig().Profile[CurrentProfile].PowerSystem)
306 		ChangeGameConfig().Profile[CurrentProfile].Money += GetSystemCost(GameConfig().Profile[CurrentProfile].PowerSystem+4);
307 	ChangeGameConfig().Profile[CurrentProfile].PowerSystem = 0;
308 
309 	int TargetingSystem = GameConfig().Profile[CurrentProfile].TargetingSystem;
310 	if (GameConfig().Profile[CurrentProfile].TargetingSystem)
311 		ChangeGameConfig().Profile[CurrentProfile].Money += GetSystemCost(GameConfig().Profile[CurrentProfile].TargetingSystem+8);
312 	ChangeGameConfig().Profile[CurrentProfile].TargetingSystem = 0;
313 
314 	int TargetingMechanicSystem = GameConfig().Profile[CurrentProfile].TargetingMechanicSystem;
315 	if (GameConfig().Profile[CurrentProfile].TargetingMechanicSystem)
316 		ChangeGameConfig().Profile[CurrentProfile].Money += GetSystemCost(GameConfig().Profile[CurrentProfile].TargetingMechanicSystem+12);
317 	ChangeGameConfig().Profile[CurrentProfile].TargetingMechanicSystem = 0;
318 
319 	int AdvancedProtectionSystem = GameConfig().Profile[CurrentProfile].AdvancedProtectionSystem;
320 	if (GameConfig().Profile[CurrentProfile].AdvancedProtectionSystem)
321 		ChangeGameConfig().Profile[CurrentProfile].Money += GetSystemCost(GameConfig().Profile[CurrentProfile].AdvancedProtectionSystem+16);
322 	ChangeGameConfig().Profile[CurrentProfile].AdvancedProtectionSystem = 0;
323 
324 	// 2 - Оружие
325 	unsigned OldWeaponQuantity = 0;
326 	if (auto sharedWorkshopFighterGame = WorkshopFighterGame.lock()) {
327 		OldWeaponQuantity = sharedWorkshopFighterGame->WeaponSlots.size();
328 		for (auto &tmpWeaponSlot : sharedWorkshopFighterGame->WeaponSlots) {
329 			if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock()) {
330 				ChangeGameConfig().Profile[CurrentProfile].Money += GetWeaponCost(sharedWeapon->InternalType,
331 												  sharedWeapon->Ammo,
332 												  sharedWeapon->AmmoStart);
333 				ReleaseWeapon(tmpWeaponSlot.Weapon);
334 			}
335 		}
336 	}
337 
338 	// 3 - корпус
339 	ChangeGameConfig().Profile[CurrentProfile].Money +=
340 		GetWorkshopShipCost(ChangeGameConfig().Profile[CurrentProfile].ShipHull) *
341 		GameConfig().Profile[CurrentProfile].ShipHullUpgrade -
342 		GetWorkshopShipRepairCost(ChangeGameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame);
343 
344 
345 	// сейчас у нас все в "деньгах", покупаем корпус
346 	ChangeGameConfig().Profile[CurrentProfile].ShipHull = CurrentWorkshopNewFighter;
347 	ChangeGameConfig().Profile[CurrentProfile].Money -= GetWorkshopShipCost(GameConfig().Profile[CurrentProfile].ShipHull);
348 
349 
350 
351 	// создаем объект
352 	ReleaseSpaceShip(WorkshopFighterGame);
353 
354 	int TMPGameEnemyArmorPenalty = GameEnemyArmorPenalty;
355 	GameEnemyArmorPenalty = 1;
356 
357 	WorkshopFighterGame = CreateEarthSpaceFighter(GameConfig().Profile[CurrentProfile].ShipHull);
358 	auto sharedWorkshopFighterGame = WorkshopFighterGame.lock();
359 	if (!sharedWorkshopFighterGame)
360 		return;
361 
362 	sharedWorkshopFighterGame->ObjectStatus = eObjectStatus::none;
363 	sharedWorkshopFighterGame->EngineDestroyType = true;
364 	sharedWorkshopFighterGame->ShowStatus = false;
365 	ChangeGameConfig().Profile[CurrentProfile].ArmorStatus = sharedWorkshopFighterGame->ArmorCurrentStatus;
366 	ChangeGameConfig().Profile[CurrentProfile].ShipHullUpgrade = 1;
367 
368 
369 	// пытаемся купить
370 
371 	// 1 - Системы
372 	if (EngineSystem != 0)
373 		if (GameConfig().Profile[CurrentProfile].Money >= GetSystemCost(EngineSystem)) {
374 			ChangeGameConfig().Profile[CurrentProfile].Money -= GetSystemCost(EngineSystem);
375 			ChangeGameConfig().Profile[CurrentProfile].EngineSystem = EngineSystem;
376 		}
377 	if (PowerSystem != 0)
378 		if (GameConfig().Profile[CurrentProfile].Money >= GetSystemCost(PowerSystem+4)) {
379 			ChangeGameConfig().Profile[CurrentProfile].Money -= GetSystemCost(PowerSystem+4);
380 			ChangeGameConfig().Profile[CurrentProfile].PowerSystem = PowerSystem;
381 		}
382 	if (TargetingSystem != 0)
383 		if (GameConfig().Profile[CurrentProfile].Money >= GetSystemCost(TargetingSystem+8)) {
384 			ChangeGameConfig().Profile[CurrentProfile].Money -= GetSystemCost(TargetingSystem+8);
385 			ChangeGameConfig().Profile[CurrentProfile].TargetingSystem = TargetingSystem;
386 		}
387 	if (TargetingMechanicSystem != 0)
388 		if (GameConfig().Profile[CurrentProfile].Money >= GetSystemCost(TargetingMechanicSystem+12)) {
389 			ChangeGameConfig().Profile[CurrentProfile].Money -= GetSystemCost(TargetingMechanicSystem+12);
390 			ChangeGameConfig().Profile[CurrentProfile].TargetingMechanicSystem = TargetingMechanicSystem;
391 		}
392 	if (AdvancedProtectionSystem != 0)
393 		if (GameConfig().Profile[CurrentProfile].Money >= GetSystemCost(AdvancedProtectionSystem+16)) {
394 			ChangeGameConfig().Profile[CurrentProfile].Money -= GetSystemCost(AdvancedProtectionSystem+16);
395 			ChangeGameConfig().Profile[CurrentProfile].AdvancedProtectionSystem = AdvancedProtectionSystem;
396 		}
397 
398 
399 
400 	// покупаем оружие, если можем... нет - ставим что продали его (это сделали ранее)
401 	// всегда покупаем новое, т.е. с полным боекомплектом!
402 	for (unsigned i = 0; i < sharedWorkshopFighterGame->WeaponSlots.size(); i++) {
403 		if (GameConfig().Profile[CurrentProfile].Weapon[i] != 0) {
404 			if (GameConfig().Profile[CurrentProfile].Money >= GetWeaponBaseCost(GameConfig().Profile[CurrentProfile].Weapon[i])) {
405 				if (SetEarthSpaceFighterWeapon(WorkshopFighterGame, i + 1, GameConfig().Profile[CurrentProfile].Weapon[i])) {
406 					if (auto sharedWeapon = sharedWorkshopFighterGame->WeaponSlots[i].Weapon.lock()) {
407 						if (auto sharedFire = sharedWeapon->Fire.lock())
408 							vw_ReleaseLight(sharedFire->Light);
409 
410 						ChangeGameConfig().Profile[CurrentProfile].Money -= GetWeaponBaseCost(GameConfig().Profile[CurrentProfile].Weapon[i]);
411 						ChangeGameConfig().Profile[CurrentProfile].WeaponAmmo[i] = sharedWeapon->AmmoStart;
412 						ChangeGameConfig().Profile[CurrentProfile].WeaponSlotYAngle[i] = 0.0f;
413 					}
414 				} else { // если поставить не смогли - не такой слот
415 					ChangeGameConfig().Profile[CurrentProfile].Weapon[i] = 0;
416 					ChangeGameConfig().Profile[CurrentProfile].WeaponAmmo[i] = 0;
417 				}
418 			} else { // если не хватило денег снова купить
419 				ChangeGameConfig().Profile[CurrentProfile].Weapon[i] = 0;
420 				ChangeGameConfig().Profile[CurrentProfile].WeaponAmmo[i] = 0;
421 			}
422 		}
423 	}
424 	// если было больше слотов чем есть сейчас
425 	if (OldWeaponQuantity > sharedWorkshopFighterGame->WeaponSlots.size()) {
426 		for (unsigned j = 0; j < OldWeaponQuantity; j++) {
427 			if (sharedWorkshopFighterGame->WeaponSlots.size() <= j)
428 				ChangeGameConfig().Profile[CurrentProfile].Weapon[j] = 0;
429 		}
430 	}
431 
432 
433 	// создаем системы (визуальные)
434 	SetEarthSpaceFighterEngine(WorkshopFighterGame, GameConfig().Profile[CurrentProfile].EngineSystem);
435 	SetEarthSpaceFighterArmor(WorkshopFighterGame, GameConfig().Profile[CurrentProfile].ShipHullUpgrade - 1);
436 
437 	GameEnemyArmorPenalty = TMPGameEnemyArmorPenalty;
438 	sharedWorkshopFighterGame->SetLocation(sVECTOR3D{1000.0f,
439 							-1000.0f - (sharedWorkshopFighterGame->Height / 2.0f + sharedWorkshopFighterGame->AABB[6].y),
440 							-(sharedWorkshopFighterGame->Length / 2.0f + sharedWorkshopFighterGame->AABB[6].z)});
441 	// чтобы оружие заняло свое место...
442 	sharedWorkshopFighterGame->Update(vw_GetTimeThread(0));
443 
444 	sharedWorkshopFighterGame->SetRotation(sVECTOR3D{0.0f, 150.0f, 0.0f});
445 }
446 
447 
448 
449 
450 
BuyShip()451 void BuyShip()
452 {
453 	// сбрасываем особенные настройки слотов оружия
454 	if (auto sharedWorkshopFighterGame = WorkshopFighterGame.lock()) {
455 		for (unsigned i = 0; i < sharedWorkshopFighterGame->WeaponSlots.size(); i++) {
456 			ChangeGameConfig().Profile[CurrentProfile].WeaponSlotYAngle[i] = 0;
457 		}
458 	}
459 
460 	// создаем новый корабль
461 	WorkshopCreateBuyShip();
462 
463 	// переводим на другой корабль
464 	CurrentWorkshopNewFighter++;
465 	if (CurrentWorkshopNewFighter == GameConfig().Profile[CurrentProfile].ShipHull)
466 		CurrentWorkshopNewFighter++;
467 	if (CurrentWorkshopNewFighter > 22)
468 		CurrentWorkshopNewFighter = 1;
469 	// если это 1-й, переводим на 2-й
470 	if (CurrentWorkshopNewFighter == GameConfig().Profile[CurrentProfile].ShipHull)
471 		CurrentWorkshopNewFighter++;
472 	WorkshopCreateNewShip();
473 }
474 
475 
476 
477 
478 
479 
RepairShip()480 void RepairShip()
481 {
482 	auto sharedWorkshopFighterGame = WorkshopFighterGame.lock();
483 	if (!sharedWorkshopFighterGame)
484 		return;
485 
486 	// смотрим, если денег достаточно для полного ремонта - делаем его
487 	if (GameConfig().Profile[CurrentProfile].Money >= GetWorkshopShipRepairCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame)) {
488 		ChangeGameConfig().Profile[CurrentProfile].Money -= GetWorkshopShipRepairCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame);
489 		ChangeGameConfig().Profile[CurrentProfile].ArmorStatus = sharedWorkshopFighterGame->ArmorInitialStatus;
490 		sharedWorkshopFighterGame->ArmorCurrentStatus = sharedWorkshopFighterGame->ArmorInitialStatus;
491 		return;
492 	}
493 
494 
495 	// вычисляем, сколько можем отремонтировать
496 	float ArmorRepair = sharedWorkshopFighterGame->ArmorInitialStatus - sharedWorkshopFighterGame->ArmorCurrentStatus;
497 	float RepairCost = static_cast<float>(GetWorkshopShipRepairCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame));
498 	// сколько можем отремонтировать
499 	float CanRepair = ArmorRepair * (GameConfig().Profile[CurrentProfile].Money / RepairCost);
500 	// ремонтируем сколько можем
501 	sharedWorkshopFighterGame->ArmorCurrentStatus += CanRepair;
502 	ChangeGameConfig().Profile[CurrentProfile].ArmorStatus = sharedWorkshopFighterGame->ArmorCurrentStatus;
503 	// это будет стоить все имеющиеся деньги
504 	ChangeGameConfig().Profile[CurrentProfile].Money = 0;
505 
506 	// выводим диалог с надписью, что не достаточно денег для полного ремонта
507 	SetCurrentDialogBox(eDialogBox::RepairShip);
508 }
509 
510 
511 
512 
513 
UpgradeShip()514 void UpgradeShip()
515 {
516 	auto sharedWorkshopFighterGame = WorkshopFighterGame.lock();
517 	if (!sharedWorkshopFighterGame)
518 		return;
519 
520 	// ув. данные о базовой прочности корабля
521 	float OldStr = sharedWorkshopFighterGame->ArmorInitialStatus;
522 	sharedWorkshopFighterGame->ArmorInitialStatus /= GameConfig().Profile[CurrentProfile].ShipHullUpgrade;
523 
524 	// ув. данные о номере апгрейда
525 	ChangeGameConfig().Profile[CurrentProfile].ShipHullUpgrade++;
526 
527 	sharedWorkshopFighterGame->ArmorInitialStatus *= GameConfig().Profile[CurrentProfile].ShipHullUpgrade;
528 	sharedWorkshopFighterGame->ArmorCurrentStatus = sharedWorkshopFighterGame->ArmorInitialStatus - OldStr +
529 							GameConfig().Profile[CurrentProfile].ArmorStatus;
530 
531 	ChangeGameConfig().Profile[CurrentProfile].ArmorStatus = sharedWorkshopFighterGame->ArmorCurrentStatus;
532 
533 
534 	// вычитаем деньги за апгрейд
535 	ChangeGameConfig().Profile[CurrentProfile].Money -= GetWorkshopShipCost(GameConfig().Profile[CurrentProfile].ShipHull);
536 
537 
538 	// сообщаем о новых возможностях и т.п. которые дает этот апгрейд
539 	SetEarthSpaceFighterArmor(WorkshopFighterGame, GameConfig().Profile[CurrentProfile].ShipHullUpgrade - 1);
540 }
541 
542 
543 
544 
545 
546 
547 
548 
549 
550 
551 
552 
553 
554 
555 
556 
557 
558 //------------------------------------------------------------------------------------
559 // покупка-апгрейд корпуса
560 //------------------------------------------------------------------------------------
Workshop_Shipyard()561 void Workshop_Shipyard()
562 {
563 
564 	// затемнение при выводе
565 	int SizeI;
566 	sRECT SrcRect, DstRect;
567 
568 
569 	// затемнение
570 	SrcRect(0,0,256,256 );
571 	DstRect(GameConfig().InternalWidth/2-480, 100-32, GameConfig().InternalWidth/2-32, 450+32);
572 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/back_spot2.tga"), true, 0.45f * MenuContentTransp);
573 	DstRect(GameConfig().InternalWidth/2+32, 100-32, GameConfig().InternalWidth/2+480, 450+32);
574 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/back_spot2.tga"), true, 0.45f * MenuContentTransp);
575 
576 
577 
578 	vw_End2DMode();
579 	WorkshopDrawShip(WorkshopFighterGame, 3);
580 	WorkshopDrawShip(WorkshopNewFighter, 2);
581 	vw_Start2DMode(-1,1);
582 
583 
584 	// условия, при которых корабль купить можно
585 	bool CanBuy = false;
586 	if (GetWorkshopShipFullCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame) +
587 	    GameConfig().Profile[CurrentProfile].Money >= GetWorkshopShipCost(CurrentWorkshopNewFighter))
588 		CanBuy = true;
589 
590 
591 	// на новом корабле
592 	vw_SetFontSize(24);
593 	vw_DrawTextUTF32(GameConfig().InternalWidth/2-445, 600, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, MenuContentTransp, vw_GetTextUTF32("Ship Stock"));
594 	ResetFontSize();
595 
596 
597 	// вывод названия корабля
598 	std::ostringstream tmpStream;
599 	tmpStream << std::fixed << std::setprecision(0)
600 		  << vw_GetText(GetWorkshopShipName(CurrentWorkshopNewFighter)) << " Mk" << 1;
601 	vw_DrawText(GameConfig().InternalWidth/2-448, 50+6, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::yellow}, MenuContentTransp, tmpStream.str());
602 	if (DrawButton128_2(GameConfig().InternalWidth/2-197,50, vw_GetTextUTF32("Info"), MenuContentTransp, false)) {
603 		SetCurrentDialogBox(eDialogBox::ShowShipInfo);
604 		DialogSpaceShip = WorkshopNewFighter;
605 	}
606 
607 	auto sharedWorkshopNewFighter = WorkshopNewFighter.lock();
608 	if (!sharedWorkshopNewFighter)
609 		return;
610 
611 	// находим смещение, чтобы было красиво
612 	int SmSizeI = vw_TextWidthUTF32(vw_GetTextUTF32("Armor:"));
613 	int SmSizeI2 = vw_TextWidthUTF32(vw_GetTextUTF32("Weapon Slots:"));
614 	int SmSizeI3 = vw_TextWidthUTF32(vw_GetTextUTF32("Slot Levels:"));
615 	SmSizeI = std::max({SmSizeI, SmSizeI2, SmSizeI3});
616 
617 	vw_DrawTextUTF32(GameConfig().InternalWidth/2-440, 110, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Armor:"));
618 	tmpStream.clear();
619 	tmpStream.str(std::string{});
620 	tmpStream << sharedWorkshopNewFighter->ArmorInitialStatus;
621 	vw_DrawText(GameConfig().InternalWidth/2-440+14+SmSizeI, 110, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
622 
623 	vw_DrawTextUTF32(GameConfig().InternalWidth/2-440, 130, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Weapon Slots:"));
624 	tmpStream.clear();
625 	tmpStream.str(std::string{});
626 	tmpStream << sharedWorkshopNewFighter->WeaponSlots.size();
627 	vw_DrawText(GameConfig().InternalWidth/2-440+14+SmSizeI, 130, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
628 
629 	vw_DrawTextUTF32(GameConfig().InternalWidth/2-440, 150, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Slot Levels:"));
630 	tmpStream.clear();
631 	tmpStream.str(std::string{});
632 	if (!sharedWorkshopNewFighter->WeaponSlots.empty())
633 		tmpStream << sharedWorkshopNewFighter->WeaponSlots[0].Type;
634 	for (unsigned i = 1; i < sharedWorkshopNewFighter->WeaponSlots.size(); i++) {
635 		tmpStream << "/" << sharedWorkshopNewFighter->WeaponSlots[i].Type;
636 	}
637 	vw_DrawText(GameConfig().InternalWidth/2-440+14+SmSizeI, 150, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
638 
639 	// вывод стоимости корабля
640 	float tmpTransp{MenuContentTransp};
641 	sRGBCOLOR tmpColor{eRGBCOLOR::white};
642 	if (!CanBuy) {
643 		tmpTransp = MenuContentTransp * CurrentAlert3;
644 		tmpColor = sRGBCOLOR{eRGBCOLOR::orange};
645 	}
646 	tmpStream.clear();
647 	tmpStream.str(std::string{});
648 	tmpStream << vw_GetText("Ship Hull Cost") << ": " << GetWorkshopShipCost(CurrentWorkshopNewFighter);
649 	vw_DrawText(GameConfig().InternalWidth/2-438, 420, 0, 0, 1.0f, tmpColor, tmpTransp, tmpStream.str());
650 
651 
652 	// рамки
653 	SrcRect(0,0,400,35 );
654 	DstRect(GameConfig().InternalWidth/2-457, 100-11, GameConfig().InternalWidth/2-57, 100+35-11);
655 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/workshop_panel4.tga"), true, MenuContentTransp);
656 
657 	SrcRect(0,0,400,173 );
658 	DstRect(GameConfig().InternalWidth/2-457, 450-13, GameConfig().InternalWidth/2-57, 450+173-13);
659 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/workshop_panel1.tga"), true, MenuContentTransp);
660 
661 
662 	// проверяем колесо мышки
663 	DstRect(GameConfig().InternalWidth/2-457, 100+35-11, GameConfig().InternalWidth/2-57, 450-13);
664 	if (vw_MouseOverRect(DstRect)) {
665 		if (vw_GetWheelStatus() != 0 && !isDialogBoxDrawing()) {
666 			CurrentWorkshopNewFighter += vw_GetWheelStatus();
667 
668 			if (CurrentWorkshopNewFighter < 1)
669 				CurrentWorkshopNewFighter = 22;
670 			if (CurrentWorkshopNewFighter > 22)
671 				CurrentWorkshopNewFighter = 1;
672 
673 			WorkshopCreateNewShip();
674 
675 			vw_ResetWheelStatus();
676 		}
677 	} else if (vw_GetWheelStatus() != 0) {
678 		vw_ResetWheelStatus();
679 	}
680 
681 	if (DrawButton128_2(GameConfig().InternalWidth/2-395, 482, vw_GetTextUTF32("Prev"), MenuContentTransp, false)) {
682 		CurrentWorkshopNewFighter--;
683 		if (CurrentWorkshopNewFighter < 1)
684 			CurrentWorkshopNewFighter = 22;
685 		WorkshopCreateNewShip();
686 	}
687 	if (DrawButton128_2(GameConfig().InternalWidth/2-247, 482, vw_GetTextUTF32("Next"), MenuContentTransp, false)) {
688 		CurrentWorkshopNewFighter++;
689 		if (CurrentWorkshopNewFighter > 22)
690 			CurrentWorkshopNewFighter = 1;
691 		WorkshopCreateNewShip();
692 	}
693 	if (DrawButton200_2(GameConfig().InternalWidth/2-357, 533, vw_GetTextUTF32("Buy Ship"), MenuContentTransp, !CanBuy))
694 		BuyShip();
695 
696 
697 
698 
699 
700 
701 
702 
703 	// на корабле игрока
704 	vw_SetFontSize(24);
705 	vw_DrawTextUTF32(GameConfig().InternalWidth/2+445-vw_TextWidthUTF32(vw_GetTextUTF32("Player Ship")), 600, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, MenuContentTransp, vw_GetTextUTF32("Player Ship"));
706 	ResetFontSize();
707 
708 	// вывод названия корабля
709 	tmpStream.clear();
710 	tmpStream.str(std::string{});
711 	tmpStream << vw_GetText(GetWorkshopShipName(GameConfig().Profile[CurrentProfile].ShipHull))
712 		  << " Mk" << static_cast<int>(GameConfig().Profile[CurrentProfile].ShipHullUpgrade);
713 	vw_DrawText(GameConfig().InternalWidth/2+64, 56, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::yellow}, MenuContentTransp, tmpStream.str());
714 
715 	if (DrawButton128_2(GameConfig().InternalWidth/2+315, 50, vw_GetTextUTF32("Info"), MenuContentTransp, false)) {
716 		SetCurrentDialogBox(eDialogBox::ShowShipInfo);
717 		DialogSpaceShip = WorkshopFighterGame;
718 	}
719 
720 
721 
722 	auto sharedWorkshopFighterGame = WorkshopFighterGame.lock();
723 	if (!sharedWorkshopFighterGame)
724 		return;
725 
726 
727 	int LinePos = 420;
728 
729 	// вывод стомости модернизации
730 	// модернизация корпуса
731 	bool CanUpgrade = false;
732 	if (GameConfig().Profile[CurrentProfile].ShipHullUpgrade < 4)
733 		CanUpgrade = true;
734 
735 	if (CanUpgrade) {
736 		if (GameConfig().Profile[CurrentProfile].Money < GetWorkshopShipCost(GameConfig().Profile[CurrentProfile].ShipHull))
737 			CanUpgrade = false;
738 
739 		tmpTransp = MenuContentTransp;
740 		tmpColor = sRGBCOLOR{eRGBCOLOR::white};
741 		tmpStream.clear();
742 		tmpStream.str(std::string{});
743 		if (!CanUpgrade) {
744 			tmpTransp = MenuContentTransp * CurrentAlert3;
745 			tmpColor = sRGBCOLOR{eRGBCOLOR::orange};
746 		}
747 		tmpStream << vw_GetText("Upgrade Hull Cost") << ": " << GetWorkshopShipCost(GameConfig().Profile[CurrentProfile].ShipHull);
748 		vw_DrawText(GameConfig().InternalWidth/2+438-vw_TextWidth(tmpStream.str()), LinePos, 0, 0, 1.0f, tmpColor, tmpTransp, tmpStream.str());
749 
750 		LinePos -= 20;
751 	}
752 
753 
754 	// вывод стомости ремонта, если нужно
755 	bool NeedRepair = false;
756 	if (GetWorkshopShipRepairCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame) > 0) {
757 		tmpStream.clear();
758 		tmpStream.str(std::string{});
759 		tmpStream <<  vw_GetText("Repair Hull Cost") << ": "
760 			  << GetWorkshopShipRepairCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame);
761 		SizeI = vw_TextWidth(tmpStream.str());
762 		vw_DrawText(GameConfig().InternalWidth/2+438-SizeI, LinePos, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::red}, CurrentAlert3*MenuContentTransp, tmpStream.str());
763 		LinePos -= 20;
764 		NeedRepair = true;
765 
766 		// надпись Armor, красная
767 		vw_DrawTextUTF32(GameConfig().InternalWidth/2+74, 110, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Armor:"));
768 		tmpStream.clear();
769 		tmpStream.str(std::string{});
770 		tmpStream << static_cast<int>(sharedWorkshopFighterGame->ArmorCurrentStatus) << "/"
771 			  << static_cast<int>(sharedWorkshopFighterGame->ArmorInitialStatus);
772 		vw_DrawText(GameConfig().InternalWidth/2+74+14+SmSizeI, 110, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::red}, CurrentAlert3*MenuContentTransp, tmpStream.str());
773 	} else {
774 		// надпись Armor, нормальная
775 		vw_DrawTextUTF32(GameConfig().InternalWidth/2+74, 110, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Armor:"));
776 		tmpStream.clear();
777 		tmpStream.str(std::string{});
778 		tmpStream << static_cast<int>(sharedWorkshopFighterGame->ArmorCurrentStatus) << "/"
779 			  << static_cast<int>(sharedWorkshopFighterGame->ArmorInitialStatus);
780 		vw_DrawText(GameConfig().InternalWidth/2+74+14+SmSizeI, 110, 0, 0,1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
781 	}
782 
783 	vw_DrawTextUTF32(GameConfig().InternalWidth/2+74, 130, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Weapon Slots:"));
784 	tmpStream.clear();
785 	tmpStream.str(std::string{});
786 	tmpStream << sharedWorkshopFighterGame->WeaponSlots.size();
787 	vw_DrawText(GameConfig().InternalWidth/2+74+14+SmSizeI, 130, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
788 
789 
790 	vw_DrawTextUTF32(GameConfig().InternalWidth/2+74, 150, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, vw_GetTextUTF32("Slot Levels:"));
791 	tmpStream.clear();
792 	tmpStream.str(std::string{});
793 	if (!sharedWorkshopFighterGame->WeaponSlots.empty())
794 		tmpStream << sharedWorkshopFighterGame->WeaponSlots[0].Type;
795 	for (unsigned i = 1; i < sharedWorkshopFighterGame->WeaponSlots.size(); i++) {
796 		tmpStream << "/" << sharedWorkshopFighterGame->WeaponSlots[i].Type;
797 	}
798 	vw_DrawText(GameConfig().InternalWidth/2+74+14+SmSizeI, 150, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, 0.5f*MenuContentTransp, tmpStream.str());
799 
800 
801 
802 
803 	// вывод стоимости корабля (со всеми системами)
804 	tmpStream.clear();
805 	tmpStream.str(std::string{});
806 	tmpStream << vw_GetText("Ship Cost") << ": "
807 		  << GetWorkshopShipFullCost(GameConfig().Profile[CurrentProfile].ShipHull, WorkshopFighterGame);
808 	SizeI = vw_TextWidth(tmpStream.str());
809 	vw_DrawText(GameConfig().InternalWidth/2+438-SizeI, LinePos, 0, 0, 1.0f, sRGBCOLOR{eRGBCOLOR::white}, MenuContentTransp, tmpStream.str());
810 
811 
812 	// рамки
813 	SrcRect(0,0,400,35 );
814 	DstRect(GameConfig().InternalWidth/2+57, 100-11, GameConfig().InternalWidth/2+457, 100+35-11);
815 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/workshop_panel4.tga"), true, MenuContentTransp);
816 
817 	SrcRect(0,0,400,173 );
818 	DstRect(GameConfig().InternalWidth/2+57, 450-13, GameConfig().InternalWidth/2+457, 450+173-13);
819 	vw_Draw2D(DstRect, SrcRect, GetPreloadedTextureAsset("menu/workshop_panel1+.tga"), true, MenuContentTransp);
820 
821 
822 
823 	if (DrawButton200_2(GameConfig().InternalWidth/2+153, 482, vw_GetTextUTF32("Repair Hull"), MenuContentTransp, !NeedRepair))
824 		RepairShip();
825 
826 	if (DrawButton200_2(GameConfig().InternalWidth/2+153, 533, vw_GetTextUTF32("Upgrade Hull"), MenuContentTransp, !CanUpgrade))
827 		UpgradeShip();
828 
829 
830 
831 	// вывод информации
832 	vw_SetFontSize(20);
833 
834 	tmpTransp = MenuContentTransp;
835 	tmpColor = sRGBCOLOR{eRGBCOLOR::yellow};
836 	tmpStream.clear();
837 	tmpStream.str(std::string{});
838 	tmpStream << vw_GetText("Money") << ": "
839 		  << GameConfig().Profile[CurrentProfile].Money;
840 	SizeI = (GameConfig().InternalWidth - vw_TextWidth(tmpStream.str())) / 2;
841 	if (!CanBuy) {
842 		tmpTransp = MenuContentTransp * CurrentAlert3;
843 		tmpColor = sRGBCOLOR{eRGBCOLOR::orange};
844 	}
845 	vw_DrawText(SizeI, 630, 0, 0, 1.0f, tmpColor, tmpTransp, tmpStream.str());
846 
847 	ResetFontSize();
848 }
849 
850 } // astromenace namespace
851 } // viewizard namespace
852