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 translate comments
29 
30 #include "../core/core.h"
31 #include "../config/config.h"
32 #include "../gfx/shadow_map.h"
33 #include "../command.h"
34 #include "../object3d/weapon/weapon.h"
35 #include "../object3d/space_ship/space_ship.h"
36 #include "../game.h" // FIXME "game.h" should be replaced by individual headers
37 
38 // NOTE switch to nested namespace definition (namespace A::B::C { ... }) (since C++17)
39 namespace viewizard {
40 namespace astromenace {
41 
42 //------------------------------------------------------------------------------------
43 // переменные
44 //------------------------------------------------------------------------------------
45 std::weak_ptr<cSpaceShip> WorkshopFighterGame{};
46 std::weak_ptr<cSpaceShip> WorkshopNewFighter{};
47 std::weak_ptr<cWeapon> WorkshopNewWeapon{};
48 int	CurrentWorkshopNewFighter = 1;
49 int	CurrentWorkshopNewWeapon = 1;
50 
51 
52 sVECTOR3D WorkShopPointCamera;
53 void WorkshopDrawWeapon(cWeapon *Weapon);
54 int CurrentWorkshop = 3;
55 
56 
57 // небольшая девиация оружия в слотах
58 float CurrentDeviation = 0.0f;
59 float NeedDeviation = vw_fRand0()*5.0f;
60 float CurrentDeviationSum = 0.0f;
61 float CurrentTime = 0.0f;
62 
63 // для индикации нужных надписей
64 float CurrentAlert2 = 1.0f;
65 float CurrentAlert3 = 1.0f;
66 
67 // можем рисовать
68 bool CanDrawWorkshop = false;
69 
70 
71 void Workshop_Shipyard();
72 void Workshop_Workshop();
73 void Workshop_Weaponry();
74 
75 
76 extern bool DragWeapon;
77 extern int DragWeaponNum;
78 extern int DragWeaponLevel;
79 extern int WeaponSetupSlot;
80 
81 
82 
83 //------------------------------------------------------------------------------------
84 // создание корабля игрока, в меню (не при покупке нового корпуса!)
85 //------------------------------------------------------------------------------------
WorkshopCreateShip(int Num)86 void WorkshopCreateShip(int Num)
87 {
88 	// создаем объект
89 	ReleaseSpaceShip(WorkshopFighterGame);
90 
91 	int TMPGameEnemyArmorPenalty = GameEnemyArmorPenalty;
92 	GameEnemyArmorPenalty = 1;
93 
94 	WorkshopFighterGame = CreateEarthSpaceFighter(GameConfig().Profile[CurrentProfile].ShipHull);
95 	auto sharedWorkshopFighterGame = WorkshopFighterGame.lock();
96 	if (!sharedWorkshopFighterGame)
97 		return;
98 
99 	sharedWorkshopFighterGame->ObjectStatus = eObjectStatus::none;
100 	sharedWorkshopFighterGame->EngineDestroyType = true;
101 	sharedWorkshopFighterGame->ShowStatus = false;
102 
103 	sharedWorkshopFighterGame->ArmorInitialStatus *= GameConfig().Profile[CurrentProfile].ShipHullUpgrade;
104 	sharedWorkshopFighterGame->ArmorCurrentStatus = GameConfig().Profile[CurrentProfile].ArmorStatus;
105 
106 
107 	// создаем оружие
108 	for (unsigned i = 0; i < sharedWorkshopFighterGame->WeaponSlots.size(); i++) {
109 		if (GameConfig().Profile[CurrentProfile].Weapon[i] &&
110 		    SetEarthSpaceFighterWeapon(WorkshopFighterGame, i + 1, GameConfig().Profile[CurrentProfile].Weapon[i])) {
111 			if (auto sharedWeapon = sharedWorkshopFighterGame->WeaponSlots[i].Weapon.lock()) {
112 				// убираем источник света
113 				if (auto sharedFire = sharedWeapon->Fire.lock())
114 					vw_ReleaseLight(sharedFire->Light);
115 
116 				sharedWeapon->Ammo = GameConfig().Profile[CurrentProfile].WeaponAmmo[i];
117 				sharedWorkshopFighterGame->WeaponSlots[i].YAngle = -GameConfig().Profile[CurrentProfile].WeaponSlotYAngle[i];
118 
119 				sVECTOR3D NeedAngle = sharedWorkshopFighterGame->Rotation;
120 				NeedAngle.y += sharedWorkshopFighterGame->WeaponSlots[i].YAngle;
121 				sharedWeapon->SetRotation(NeedAngle);
122 			}
123 		}
124 	}
125 
126 
127 	// создаем системы (визуальные)
128 	SetEarthSpaceFighterEngine(WorkshopFighterGame, GameConfig().Profile[CurrentProfile].EngineSystem);
129 	SetEarthSpaceFighterArmor(WorkshopFighterGame, GameConfig().Profile[CurrentProfile].ShipHullUpgrade - 1);
130 
131 	GameEnemyArmorPenalty = TMPGameEnemyArmorPenalty;
132 	sharedWorkshopFighterGame->SetLocation(sVECTOR3D{1000.0f,
133 							 -1000.0f - (sharedWorkshopFighterGame->Height / 2.0f + sharedWorkshopFighterGame->AABB[6].y),
134 							 -(sharedWorkshopFighterGame->Length / 2.0f + sharedWorkshopFighterGame->AABB[6].z)});
135 
136 	if (Num == 1)
137 		sharedWorkshopFighterGame->SetRotation(sVECTOR3D{0.0f, 150.0f, 0.0f});
138 	if (Num == 2)
139 		sharedWorkshopFighterGame->SetRotation(sVECTOR3D{0.0f, 170.0f, 0.0f});
140 	if (Num == 3)
141 		sharedWorkshopFighterGame->SetRotation(sVECTOR3D{0.0f, 180.0f, 0.0f});
142 }
143 
144 
145 
146 
147 
148 
149 //------------------------------------------------------------------------------------
150 // создание корабля для покупки
151 //------------------------------------------------------------------------------------
WorkshopCreateNewShip()152 void WorkshopCreateNewShip()
153 {
154 	// создаем объект
155 	ReleaseSpaceShip(WorkshopNewFighter);
156 
157 	int TMPGameEnemyArmorPenalty = GameEnemyArmorPenalty;
158 	GameEnemyArmorPenalty = 1;
159 
160 	WorkshopNewFighter = CreateEarthSpaceFighter(CurrentWorkshopNewFighter);
161 	auto sharedWorkshopNewFighter = WorkshopNewFighter.lock();
162 	if (!sharedWorkshopNewFighter)
163 		return;
164 
165 	sharedWorkshopNewFighter->ObjectStatus = eObjectStatus::none;
166 	sharedWorkshopNewFighter->EngineDestroyType = true;
167 
168 	GameEnemyArmorPenalty = TMPGameEnemyArmorPenalty;
169 	sharedWorkshopNewFighter->SetLocation(sVECTOR3D{2000.0f,
170 							-2000.0f - (sharedWorkshopNewFighter->Height / 2.0f + sharedWorkshopNewFighter->AABB[6].y),
171 							-(sharedWorkshopNewFighter->Length / 2.0f + sharedWorkshopNewFighter->AABB[6].z)});
172 
173 	sharedWorkshopNewFighter->SetRotation(sVECTOR3D{0.0f, -45.0f, 0.0f});
174 }
175 
176 
177 
178 
179 //------------------------------------------------------------------------------------
180 // создание пушки для покупки
181 //------------------------------------------------------------------------------------
WorkshopCreateNewWeapon()182 void WorkshopCreateNewWeapon()
183 {
184 	ReleaseWeapon(WorkshopNewWeapon);
185 
186 	int TMPGameEnemyArmorPenalty = GameEnemyArmorPenalty;
187 	GameEnemyArmorPenalty = 1;
188 
189 	WorkshopNewWeapon = CreateWeapon(CurrentWorkshopNewWeapon);
190 
191 	auto sharedWeapon = WorkshopNewWeapon.lock();
192 	if (!sharedWeapon)
193 		return;
194 
195 	sharedWeapon->ObjectStatus = eObjectStatus::none;
196 	GameEnemyArmorPenalty = TMPGameEnemyArmorPenalty;
197 
198 	sVECTOR3D Ptmp = sVECTOR3D{0.0f,
199 				   -(sharedWeapon->Height / 2.0f + sharedWeapon->AABB[6].y),
200 				   -(sharedWeapon->Length / 2.0f + sharedWeapon->AABB[6].z) - 0.5f};
201 	vw_RotatePoint(Ptmp, sVECTOR3D{0.0f, -45.0f, 0.0f});
202 
203 	sharedWeapon->SetLocation(sVECTOR3D{Ptmp.x + 3000.0f,
204 					    Ptmp.y - 3000.0f,
205 					    Ptmp.z});
206 
207 	sharedWeapon->SetRotation(sVECTOR3D{0.0f, -45.0f, 0.0f});
208 
209 	// убираем источник света
210 	if (auto sharedFire = sharedWeapon->Fire.lock())
211 		vw_ReleaseLight(sharedFire->Light);
212 }
213 
214 
215 
216 
217 
218 
219 
220 //------------------------------------------------------------------------------------
221 // общая процедура создания
222 //------------------------------------------------------------------------------------
WorkshopCreate()223 void WorkshopCreate()
224 {
225 	// все установки в исходные
226 	CurrentWorkshopNewFighter = 1;
227 	CurrentWorkshopNewWeapon = 1;
228 	CurrentDeviation = 0.0f;
229 	NeedDeviation = vw_fRand0()*5.0f;
230 	CurrentDeviationSum = 0.0f;
231 	CurrentTime = 0.0f;
232 	CurrentAlert2 = 1.0f;
233 	CurrentAlert3 = 1.0f;
234 
235 	// чтобы только при старте не повоторялись!
236 	if (CurrentWorkshopNewFighter == GameConfig().Profile[CurrentProfile].ShipHull)
237 		CurrentWorkshopNewFighter++;
238 	if (CurrentWorkshopNewFighter > 22)
239 		CurrentWorkshopNewFighter = 1;
240 
241 	WorkshopCreateShip(CurrentWorkshop);
242 	WorkshopCreateNewShip();
243 	WorkshopCreateNewWeapon();
244 
245 	// нужно для получение кнопки в веапон
246 	NeedCheck = 0;
247 
248 	CanDrawWorkshop = true;
249 }
250 
251 
252 
253 
254 
255 
256 
257 
258 
259 //------------------------------------------------------------------------------------
260 // удаление всего...
261 //------------------------------------------------------------------------------------
WorkshopDestroyData()262 void WorkshopDestroyData()
263 {
264 	ReleaseSpaceShip(WorkshopFighterGame);
265 	ReleaseSpaceShip(WorkshopNewFighter);
266 	ReleaseWeapon(WorkshopNewWeapon);
267 }
268 
269 
270 
271 
272 
273 
274 
275 
276 
277 
278 //------------------------------------------------------------------------------------
279 // покупка-установка и ремонт систем корабля
280 //------------------------------------------------------------------------------------
WorkshopMenu()281 void WorkshopMenu()
282 {
283 
284 	// небольшое качение... девиация
285 	float TimeDelta = vw_GetTimeThread(0) - CurrentTime;
286 	if (CurrentTime==0.0f) {
287 		CurrentTime = vw_GetTimeThread(0);
288 	} else {
289 		CurrentTime = vw_GetTimeThread(0);
290 		float Sign = 1.0f;
291 		// нужно двигать
292 		if (NeedDeviation < 0.0f) Sign = -1.0f;
293 		if (Sign == 1.0f) {
294 			if (NeedDeviation < CurrentDeviationSum)
295 				Sign = -1.0f;
296 		} else {
297 			if (NeedDeviation > CurrentDeviationSum)
298 				Sign = 1.0f;
299 		}
300 
301 		CurrentDeviation = Sign*0.7f*TimeDelta;
302 
303 		if (Sign == 1.0f) {
304 			if (NeedDeviation <= CurrentDeviationSum+CurrentDeviation) {
305 				CurrentDeviation -= CurrentDeviationSum+CurrentDeviation-NeedDeviation;
306 				CurrentDeviationSum += CurrentDeviation;
307 				NeedDeviation = vw_fRand0()*5.0f;
308 			} else CurrentDeviationSum += CurrentDeviation;
309 		} else {
310 			if (NeedDeviation >= CurrentDeviationSum+CurrentDeviation) {
311 				CurrentDeviation += CurrentDeviationSum+CurrentDeviation-NeedDeviation;
312 				CurrentDeviationSum += CurrentDeviation;
313 				NeedDeviation = vw_fRand0()*5.0f;
314 			} else CurrentDeviationSum += CurrentDeviation;
315 		}
316 	}
317 
318 
319 
320 	// просчитываем индикацию
321 	CurrentAlert2 += 0.4f*TimeDelta;
322 	if (CurrentAlert2 > 1.0f) CurrentAlert2 = 0.3f;
323 	CurrentAlert3 -= 1.9f*TimeDelta;
324 	if (CurrentAlert3 < 0.1f) CurrentAlert3 = 1.0f;
325 
326 
327 
328 
329 
330 
331 
332 
333 	// прорисовка 3д части
334 	switch (CurrentWorkshop) {
335 // покупка - ремонт корабля
336 	case 1:
337 		Workshop_Shipyard();
338 		break;
339 
340 
341 // покупка - внутренних систем корабля
342 	case 2:
343 		Workshop_Workshop();
344 		break;
345 
346 // покупка - оружия корабля
347 	case 3:
348 		Workshop_Weaponry();
349 		break;
350 	}
351 
352 
353 
354 
355 
356 
357 	// кнопки
358 
359 	int X = GameConfig().InternalWidth / 2 - 482;
360 	int Y = 180+100*5;
361 	if (DrawButton128_2(X,Y, vw_GetTextUTF32("BACK"), MenuContentTransp, false)) {
362 		cCommand::GetInstance().Set(eCommand::SWITCH_TO_MISSION);
363 		CanDrawWorkshop = false;
364 		// ничего не тянем... только включили меню
365 		DragWeaponNum = 0;
366 		DragWeaponLevel = 0;
367 		DragWeapon = false;
368 		WeaponSetupSlot = -1;
369 	}
370 
371 
372 
373 	X = GameConfig().InternalWidth / 2 - 320;
374 	bool Off = false;
375 	if (CurrentWorkshop == 1)
376 		Off = true;
377 	if (DrawButton200_2(X,Y, vw_GetTextUTF32("Shipyard"), MenuContentTransp, Off)) {
378 		CurrentWorkshop = 1;
379 		// используем разные повороты объектов, нужно пересоздать объект
380 		WorkshopCreateShip(CurrentWorkshop);
381 		WorkshopCreateNewShip();
382 		// ничего не тянем... только включили меню
383 		DragWeaponNum = 0;
384 		DragWeaponLevel = 0;
385 		DragWeapon = false;
386 		WeaponSetupSlot = -1;
387 
388 		if (GameConfig().NeedShowHint[1])
389 			SetCurrentDialogBox(eDialogBox::ShipyardTipsAndTricks);
390 	}
391 
392 
393 	X = GameConfig().InternalWidth / 2 - 100;
394 	Off = false;
395 	if (CurrentWorkshop == 2)
396 		Off = true;
397 	if (DrawButton200_2(X,Y, vw_GetTextUTF32("Workshop"), MenuContentTransp, Off)) {
398 		CurrentWorkshop = 2;
399 		// используем разные повороты объектов, нужно пересоздать объект
400 		WorkshopCreateShip(CurrentWorkshop);
401 		// ничего не тянем... только включили меню
402 		DragWeaponNum = 0;
403 		DragWeaponLevel = 0;
404 		DragWeapon = false;
405 		WeaponSetupSlot = -1;
406 
407 		if (GameConfig().NeedShowHint[2])
408 			SetCurrentDialogBox(eDialogBox::SystemsTipsAndTricks);
409 	}
410 
411 
412 	X = GameConfig().InternalWidth / 2 + 120;
413 	Off = false;
414 	if (CurrentWorkshop == 3)
415 		Off = true;
416 	if (DrawButton200_2(X,Y, vw_GetTextUTF32("Weaponry"), MenuContentTransp, Off)) {
417 		CurrentWorkshop = 3;
418 		// используем разные повороты объектов, нужно пересоздать объект
419 		WorkshopCreateShip(CurrentWorkshop);
420 		WorkshopCreateNewWeapon();
421 		// ничего не тянем... только включили меню
422 		DragWeaponNum = 0;
423 		DragWeaponLevel = 0;
424 		DragWeapon = false;
425 		WeaponSetupSlot = -1;
426 
427 		if (GameConfig().NeedShowHint[3])
428 			SetCurrentDialogBox(eDialogBox::WeaponryTipsAndTricks);
429 	}
430 
431 
432 
433 	X = GameConfig().InternalWidth / 2 + 354;
434 	if (DrawButton128_2(X,Y, vw_GetTextUTF32("START"), MenuContentTransp, false)) {
435 		if (GameConfig().NeedShowHint[4])
436 			SetCurrentDialogBox(eDialogBox::ShortkeyTipsAndTricks);
437 		else {
438 			MenuContentTransp = 0.98f; // небольшая "защелка" от быстрых двойных нажатий на кнопку
439 			// ничего не тянем... только включили меню
440 			DragWeaponNum = 0;
441 			DragWeaponLevel = 0;
442 			DragWeapon = false;
443 			WeaponSetupSlot = -1;
444 			//
445 			LastMenuOnOffUpdateTime = vw_GetTimeThread(0);
446 			NeedOffMenu = true;
447 		}
448 	}
449 }
450 
451 
452 
453 
454 
455 
456 
457 
458 
459 
460 //------------------------------------------------------------------------------------
461 // Прорисовка 3д части
462 //------------------------------------------------------------------------------------
WorkshopDrawShip(std::weak_ptr<cSpaceShip> & SpaceShip,int Mode)463 void WorkshopDrawShip(std::weak_ptr<cSpaceShip> &SpaceShip, int Mode)
464 {
465 	if (!CanDrawWorkshop)
466 		return;
467 
468 	auto sharedSpaceShip = SpaceShip.lock();
469 	if (!sharedSpaceShip)
470 		return;
471 
472 	float tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight;
473 	vw_GetViewport(&tmpViewportX, &tmpViewportY, &tmpViewportWidth, &tmpViewportHeight);
474 
475 	if (Mode == 1) {
476 		WorkShopPointCamera = sVECTOR3D{0.0f, 4.0f, -32.0f};
477 		sharedSpaceShip->SetRotation(sVECTOR3D{0.0f, 0.0f, CurrentDeviation});
478 		sharedSpaceShip->SetRotation(sVECTOR3D{0.0f, CurrentDeviation / 2.0f, 0.0f});
479 
480 		vw_SetViewport((GLint)((GameConfig().InternalWidth / 2 - 512) * (tmpViewportWidth / GameConfig().InternalWidth)),
481 			       0,
482 			       (GLsizei)(1024 * (tmpViewportWidth / GameConfig().InternalWidth)),
483 			       (GLsizei)(768 * (tmpViewportHeight / GameConfig().InternalHeight)));
484 		vw_ResizeScene(45.0f, 1024.0f/768.0f, 1.0f, 2000.0f);
485 		vw_Clear(RI_DEPTH_BUFFER);
486 
487 		vw_LoadIdentity();
488 		vw_SetCameraLocation(sVECTOR3D{WorkShopPointCamera.x + 1000.0f,
489 					       WorkShopPointCamera.y - 1000.0f,
490 					       WorkShopPointCamera.z});
491 		vw_SetCameraMoveAroundPoint(sVECTOR3D{1000.0f, -1000.0f - 6.0f, 0.0f}, 0.0f, sVECTOR3D{0.0f, 0.0f, 0.0f});
492 		vw_CameraLookAt();
493 
494 
495 		bool ShadowMap = false;
496 
497 		if (GameConfig().ShadowMap > 0) {
498 			float EffectiveDistance = 20.0f;
499 			ShadowMap_StartRenderToFBO(sVECTOR3D{0.0f, 5.0f, 0.0f}, EffectiveDistance, EffectiveDistance * 2);
500 
501 			sharedSpaceShip->Draw(true);
502 			if (!sharedSpaceShip->WeaponSlots.empty()) {
503 				for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
504 					if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
505 						sharedWeapon->Draw(true);
506 				}
507 			}
508 
509 			ShadowMap_EndRenderToFBO();
510 			ShadowMap = true;
511 			ShadowMap_StartFinalRender();
512 		}
513 
514 		sharedSpaceShip->Draw(false, ShadowMap);
515 		if (!sharedSpaceShip->WeaponSlots.empty()) {
516 			for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
517 				if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
518 					sharedWeapon->Draw(false, ShadowMap);
519 			}
520 		}
521 
522 		if (GameConfig().ShadowMap > 0)
523 			ShadowMap_EndFinalRender();
524 
525 		// рисуем эффекты двигателей только для этой модели
526 		vw_DrawParticleSystems(sharedSpaceShip->Engines);
527 
528 		vw_SetCameraLocation(sVECTOR3D{-50.0f, 30.0f, -50.0f});
529 		vw_SetViewport(tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight);
530 		vw_ResizeScene(45.0f, GameConfig().InternalWidth / GameConfig().InternalHeight, 1.0f, 2000.0f);
531 		return;
532 	}
533 
534 
535 
536 	if (Mode == 4) {
537 		WorkShopPointCamera = sVECTOR3D{0.0f, 35.0f, -0.01f};
538 		sharedSpaceShip->SetRotation(sVECTOR3D{0.0f, 0.0f, CurrentDeviation});
539 		vw_SetViewport((GLint)((GameConfig().InternalWidth / 2) * (tmpViewportWidth / GameConfig().InternalWidth)),
540 			       (GLint)(30 * (tmpViewportHeight / GameConfig().InternalHeight)),
541 			       (GLsizei)(512 * (tmpViewportWidth / GameConfig().InternalWidth)),
542 			       (GLsizei)(638 * (tmpViewportHeight / GameConfig().InternalHeight)));
543 		vw_ResizeScene(45.0f, 512.0f/608.0f, 1.0f, 2000.0f);
544 		vw_Clear(RI_DEPTH_BUFFER);
545 		vw_LoadIdentity();
546 		vw_SetCameraLocation(sVECTOR3D{WorkShopPointCamera.x + 1000.0f,
547 					       WorkShopPointCamera.y - 1000.0f,
548 					       WorkShopPointCamera.z});
549 		vw_SetCameraMoveAroundPoint(sVECTOR3D{1000.0f, -1000.0f, 0.0f}, 0.0f, sVECTOR3D{0.0f, 180.0f, 0.0f});
550 		vw_CameraLookAt();
551 
552 
553 		bool ShadowMap = false;
554 
555 		if (GameConfig().ShadowMap > 0) {
556 			float EffectiveDistance = 20.0f;
557 			ShadowMap_StartRenderToFBO(sVECTOR3D{0.0f, 0.0f, 0.0f}, EffectiveDistance, EffectiveDistance*2);
558 
559 			sharedSpaceShip->Draw(true);
560 			if (!sharedSpaceShip->WeaponSlots.empty()) {
561 				for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
562 					if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
563 						sharedWeapon->Draw(true);
564 				}
565 			}
566 
567 			ShadowMap_EndRenderToFBO();
568 			ShadowMap = true;
569 			ShadowMap_StartFinalRender();
570 		}
571 
572 		sharedSpaceShip->Draw(false, ShadowMap);
573 		if (!sharedSpaceShip->WeaponSlots.empty()) {
574 			for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
575 				if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
576 					sharedWeapon->Draw(false, ShadowMap);
577 			}
578 		}
579 
580 		if (GameConfig().ShadowMap > 0)
581 			ShadowMap_EndFinalRender();
582 
583 		// рисуем эффекты двигателей только для этой модели
584 		vw_DrawParticleSystems(sharedSpaceShip->Engines);
585 
586 		vw_SetCameraLocation(sVECTOR3D{-50.0f, 30.0f, -50.0f});
587 		vw_SetViewport(tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight);
588 		vw_ResizeScene(45.0f, GameConfig().InternalWidth / GameConfig().InternalHeight, 1.0f, 2000.0f);
589 		return;
590 	}
591 
592 
593 
594 
595 
596 
597 	if (Mode == 3) {
598 		WorkShopPointCamera = sVECTOR3D{0.0f, 10.0f, -34.0f};
599 		sharedSpaceShip->SetRotation(sVECTOR3D{0.0f, CurrentDeviation / 2.0f, 0.0f});
600 		vw_SetViewport((GLint)((GameConfig().InternalWidth / 2) * (tmpViewportWidth / GameConfig().InternalWidth)),
601 			       0,
602 			       (GLsizei)(512 * (tmpViewportWidth / GameConfig().InternalWidth)),
603 			       (GLsizei)(512 * (tmpViewportHeight / GameConfig().InternalHeight)));
604 		vw_ResizeScene(45.0f, 512.0f/512.0f, 1.0f, 2000.0f);
605 		vw_Clear(RI_DEPTH_BUFFER);
606 		vw_LoadIdentity();
607 		vw_SetCameraLocation(sVECTOR3D{WorkShopPointCamera.x / 1.2f + 1000.0f,
608 					       WorkShopPointCamera.y / 1.2f - 1000.0f,
609 					       WorkShopPointCamera.z / 1.2f});
610 		vw_SetCameraMoveAroundPoint(sVECTOR3D{1000.0f, -1000.0f - sharedSpaceShip->AABB[6].y - sharedSpaceShip->Height / 3.0f, 0.0f}, 0.0f, sVECTOR3D{0.0f, 0.0f, 0.0f});
611 	}
612 	if (Mode == 2) {
613 		WorkShopPointCamera = sVECTOR3D{0.0f, 10.0f, -34.0f};
614 		sVECTOR3D PointCameraTMP = WorkShopPointCamera;
615 		vw_RotatePoint(PointCameraTMP, sVECTOR3D{0.0f, -90.0f, 0.0f});
616 		sharedSpaceShip->SetRotation(sVECTOR3D{0.0f, CurrentDeviation / 2.0f, 0.0f});
617 		vw_SetViewport((GLint)((GameConfig().InternalWidth / 2 - 512) * (tmpViewportWidth / GameConfig().InternalWidth)),
618 			       0,
619 			       (GLsizei)(512 * (tmpViewportWidth / GameConfig().InternalWidth)),
620 			       (GLsizei)(512 * (tmpViewportHeight / GameConfig().InternalHeight)));
621 		vw_ResizeScene(45.0f, 512.0f/512.0f, 1.0f, 2000.0f);
622 		vw_Clear(RI_DEPTH_BUFFER);
623 		vw_LoadIdentity();
624 		vw_SetCameraLocation(sVECTOR3D{PointCameraTMP.x / 1.2f + 2000.0f,
625 					       PointCameraTMP.y / 1.2f - 2000.0f,
626 					       PointCameraTMP.z / 1.2f});
627 		vw_SetCameraMoveAroundPoint(sVECTOR3D{2000.0f, -2000.0f - sharedSpaceShip->AABB[6].y - sharedSpaceShip->Height / 3.0f, 0.0f}, 0.0f, sVECTOR3D{0.0f, 170.0f, 0.0f});
628 	}
629 	vw_CameraLookAt();
630 
631 
632 	bool ShadowMap = false;
633 
634 	if (GameConfig().ShadowMap > 0) {
635 		float EffectiveDistance = 20.0f;
636 		ShadowMap_StartRenderToFBO(sVECTOR3D{0.0f, -2.0f, 0.0f}, EffectiveDistance, EffectiveDistance * 2.0f);
637 
638 		sharedSpaceShip->Draw(true);
639 		if (!sharedSpaceShip->WeaponSlots.empty()) {
640 			for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
641 				if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
642 					sharedWeapon->Draw(true);
643 			}
644 		}
645 
646 		ShadowMap_EndRenderToFBO();
647 		ShadowMap = true;
648 		ShadowMap_StartFinalRender();
649 	}
650 
651 	sharedSpaceShip->Draw(false, ShadowMap);
652 
653 	if (!sharedSpaceShip->WeaponSlots.empty()) {
654 		for (auto &tmpWeaponSlot : sharedSpaceShip->WeaponSlots) {
655 			if (auto sharedWeapon = tmpWeaponSlot.Weapon.lock())
656 				sharedWeapon->Draw(false, ShadowMap);
657 		}
658 	}
659 
660 	if (GameConfig().ShadowMap > 0)
661 		ShadowMap_EndFinalRender();
662 
663 	// рисуем эффекты двигателей только для этой модели
664 	vw_DrawParticleSystems(sharedSpaceShip->Engines);
665 
666 	vw_SetCameraLocation(sVECTOR3D{-50.0f, 30.0f, -50.0f});
667 	vw_SetViewport(tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight);
668 	vw_ResizeScene(45.0f, GameConfig().InternalWidth / GameConfig().InternalHeight, 1.0f, 2000.0f);
669 
670 }
671 
672 
WorkshopDrawWeapon(cWeapon * Weapon)673 void WorkshopDrawWeapon(cWeapon *Weapon)
674 {
675 	if (!CanDrawWorkshop || (Weapon == nullptr))
676 		return;
677 
678 	float tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight;
679 	vw_GetViewport(&tmpViewportX, &tmpViewportY, &tmpViewportWidth, &tmpViewportHeight);
680 
681 	// удаление относительно размеров оружия
682 	if (Weapon->InternalType == 18 || Weapon->InternalType == 19)
683 		WorkShopPointCamera = sVECTOR3D{0.0f, 1.25f, -5.0f};
684 	else
685 		WorkShopPointCamera = sVECTOR3D{0.0f, 1.0f, -4.0f};
686 
687 	sVECTOR3D PointCameraTMP = WorkShopPointCamera;
688 	vw_RotatePoint(PointCameraTMP, sVECTOR3D{0.0f, -90.0f, 0.0f});
689 
690 	Weapon->SetRotation(sVECTOR3D{0.0f, CurrentDeviation / 2.0f, 0.0f});
691 	vw_SetViewport((GLint)((GameConfig().InternalWidth / 2 - 448) * (tmpViewportWidth / GameConfig().InternalWidth)),
692 		       (GLint)(105 * (tmpViewportHeight / GameConfig().InternalHeight)),
693 		       (GLsizei)(384 * (tmpViewportWidth / GameConfig().InternalWidth)),
694 		       (GLsizei)(350 * (tmpViewportHeight / GameConfig().InternalHeight)));
695 	vw_ResizeScene(45.0f, 384.0f/350.0f, 1.0f, 2000.0f);
696 	vw_Clear(RI_DEPTH_BUFFER);
697 	vw_LoadIdentity();
698 	vw_SetCameraLocation(sVECTOR3D{PointCameraTMP.x + 3000.0f,
699 				       PointCameraTMP.y - 3000.0f,
700 				       PointCameraTMP.z});
701 	vw_SetCameraMoveAroundPoint(sVECTOR3D{3000.0f, -3000.0f, 0.0f}, 0.0f, sVECTOR3D{0.0f, 170.0f, 0.0f});
702 	vw_CameraLookAt();
703 
704 	Weapon->Draw(false);
705 
706 	vw_SetCameraLocation(sVECTOR3D{-50.0f, 30.0f, -50.0f});
707 	vw_ResizeScene(45.0f, GameConfig().InternalWidth / GameConfig().InternalHeight, 1.0f, 2000.0f);
708 	vw_SetViewport(tmpViewportX, tmpViewportY, tmpViewportWidth, tmpViewportHeight);
709 }
710 
711 } // astromenace namespace
712 } // viewizard namespace
713