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 switch to color preset in SetWeaponFire()
29
30 // TODO switch to enumeration SetWeaponFire()
31
32 // TODO codestyle should be fixed
33
34 #include "weapon.h"
35 #include "functions.h"
36 #include "../projectile/projectile.h"
37 #include "../../assets/audio.h"
38 #include "../../assets/texture.h"
39
40 // NOTE switch to nested namespace definition (namespace A::B::C { ... }) (since C++17)
41 namespace viewizard {
42 namespace astromenace {
43
44 namespace {
45
46 std::list<std::shared_ptr<cWeapon>> WeaponList{};
47
48 struct sWeaponData {
49 eGameSFX SFX;
50 bool NeedRotateOnTargeting;
51 float Armor;
52 int WeaponLevel;
53 float EnergyUse;
54 int Ammo;
55 float NextFireTime;
56 sVECTOR3D FireLocation;
57 sVECTOR3D DestrFireLocation;
58 std::string NameVW3D;
59 std::string TextureName;
60 std::string TextureIllumName;
61 };
62
63 // earth 1-99
64 #pragma GCC diagnostic push
65 #pragma GCC diagnostic ignored "-Winline"
66 const std::vector<sWeaponData> PresetEarthWeaponData{
67 // Kinetic
68 {eGameSFX::WeaponFire_Kinetic1, true, 25, 1, 1.5f, 3000, 0.4f, sVECTOR3D{0.0f, -0.613f, 2.0f}, sVECTOR3D{0.0f, -0.65f, 1.0f}, "models/earthfighter/weapon5.vw3d", "models/earthfighter/sf-text00.vw2d", "models/earthfighter/sf-illum01.vw2d"},
69 {eGameSFX::WeaponFire_Kinetic2, true, 25, 1, 3, 1500, 0.6f, sVECTOR3D{0.0f, -0.613f, 2.93f}, sVECTOR3D{0.0f, -0.6f, 1.8f}, "models/earthfighter/weapon11.vw3d", "models/earthfighter/sf-text00.vw2d", "models/earthfighter/sf-illum01.vw2d"},
70 {eGameSFX::WeaponFire_Kinetic3, true, 30, 2, 3.5, 1000, 0.7f, sVECTOR3D{0.0f, -0.613f, 3.33f}, sVECTOR3D{0.0f, -0.6f, 2.2f}, "models/earthfighter/weapon13.vw3d", "models/earthfighter/sf-text00.vw2d", "models/earthfighter/sf-illum01.vw2d"},
71 {eGameSFX::WeaponFire_Kinetic4, true, 30, 2, 5, 7000, 0.3f, sVECTOR3D{0.0f, -0.613f, 2.33f}, sVECTOR3D{0.0f, -0.6f, 1.2f}, "models/earthfighter/weapon8.vw3d", "models/earthfighter/sf-text00.vw2d", "models/earthfighter/sf-illum01.vw2d"},
72 // Ion
73 {eGameSFX::WeaponFire_Ion1, true, 10, 1, 7, 1000, 0.7f, sVECTOR3D{0.0f, -0.43f, 2.13f}, sVECTOR3D{0.0f, -0.45f, 1.5f}, "models/earthfighter/weapon1.vw3d", "models/earthfighter/sf-text04.vw2d", "models/earthfighter/sf-illum02.vw2d"},
74 {eGameSFX::WeaponFire_Ion2, true, 10, 1, 10, 2000, 0.9f, sVECTOR3D{0.0f, -0.53f, 1.86f}, sVECTOR3D{0.0f, -0.5f, 1.8f}, "models/earthfighter/weapon4.vw3d", "models/earthfighter/sf-text04.vw2d", "models/earthfighter/sf-illum02.vw2d"},
75 {eGameSFX::WeaponFire_Ion3, true, 15, 2, 11.5, 3000, 1.0f, sVECTOR3D{0.0f, -0.63f, 2.26f}, sVECTOR3D{0.0f, -0.65f, 2.3f}, "models/earthfighter/weapon6.vw3d", "models/earthfighter/sf-text04.vw2d", "models/earthfighter/sf-illum02.vw2d"},
76 // Plasma
77 {eGameSFX::WeaponFire_Plasma1, true, 10, 2, 20, 2000, 0.6f, sVECTOR3D{0.0f, -0.613f, 2.0f}, sVECTOR3D{0.0f, -0.65f, 1.8f}, "models/earthfighter/weapon3.vw3d", "models/earthfighter/sf-text06.vw2d", "models/earthfighter/sf-illum03.vw2d"},
78 {eGameSFX::WeaponFire_Plasma2, true, 15, 2, 30, 1000, 0.7f, sVECTOR3D{0.0f, -0.8f, 1.86f}, sVECTOR3D{0.0f, -0.8f, 1.8f}, "models/earthfighter/weapon2.vw3d", "models/earthfighter/sf-text06.vw2d", "models/earthfighter/sf-illum03.vw2d"},
79 {eGameSFX::WeaponFire_Plasma3, true, 10, 3, 50, 800, 0.9f, sVECTOR3D{0.0f, -0.613f, 1.2f}, sVECTOR3D{0.0f, -0.7f, 1.6f}, "models/earthfighter/weapon7.vw3d", "models/earthfighter/sf-text06.vw2d", "models/earthfighter/sf-illum03.vw2d"},
80 // Maser
81 {eGameSFX::WeaponFire_Maser1, true, 10, 3, 50, 800, 3.0f, sVECTOR3D{0.0f, -0.55f, 2.1f}, sVECTOR3D{0.0f, -0.55f, 1.4f}, "models/earthfighter/weapon10.vw3d", "models/earthfighter/sf-text07.vw2d", "models/earthfighter/sf-illum03.vw2d"},
82 {eGameSFX::WeaponFire_Maser2, true, 15, 4, 80, 1000, 2.4f, sVECTOR3D{0.0f, -0.55f, 2.5f}, sVECTOR3D{0.0f, -0.55f, 1.8f}, "models/earthfighter/weapon9.vw3d", "models/earthfighter/sf-text07.vw2d", "models/earthfighter/sf-illum03.vw2d"},
83 // Antimatter
84 {eGameSFX::WeaponFire_Antimatter, true, 20, 4, 50, 5000, 0.8f, sVECTOR3D{0.0f, -0.65f, 2.1f}, sVECTOR3D{0.0f, -0.65f, 1.9f}, "models/earthfighter/weapon12.vw3d", "models/earthfighter/sf-text09.vw2d", "models/earthfighter/sf-illum02.vw2d"},
85 // Laser
86 {eGameSFX::WeaponFire_Laser, true, 15, 5, 150, 800, 1.2f, sVECTOR3D{0.0f, -0.6f, 2.5f}, sVECTOR3D{0.0f, -0.6f, 2.1f}, "models/earthfighter/weapon14.vw3d", "models/earthfighter/sf-text05.vw2d", "models/earthfighter/sf-illum03.vw2d"},
87 // Gauss
88 {eGameSFX::WeaponFire_Gauss, true, 20, 5, 150, 2000, 0.7f, sVECTOR3D{0.0f, -0.65f, 3.6f}, sVECTOR3D{0.0f, -0.55f, 2.2f}, "models/earthfighter/weapon15.vw3d", "models/earthfighter/sf-text08.vw2d", "models/earthfighter/sf-illum03.vw2d"},
89 // Missiles
90 {eGameSFX::WeaponFire_SmallMissile, false, 30, 4, 5, 200, 3.0f, sVECTOR3D{0.0f, -0.8f, 4.7f}, sVECTOR3D{0.0f, -0.9f, 1.5f}, "models/earthfighter/lnch1.vw3d", "models/earthfighter/lnch12.tga", ""},
91 {eGameSFX::WeaponFire_NormalMissile, false, 30, 4, 15, 400, 8.0f, sVECTOR3D{0.2f, -0.95f, 2.6f}, sVECTOR3D{0.0f, -0.6f, 1.0f}, "models/earthfighter/lnch2.vw3d", "models/earthfighter/lnch12.tga", ""},
92 {eGameSFX::WeaponFire_Torpedo, false, 25, 5, 10, 50, 8.0f, sVECTOR3D{0.0f, -0.95f, 4.0f}, sVECTOR3D{0.0f, -0.9f, 1.5f}, "models/earthfighter/lnch3.vw3d", "models/earthfighter/lnch34.tga", ""},
93 {eGameSFX::WeaponFire_Bomb, false, 30, 5, 15, 25, 10.0f, sVECTOR3D{0.0f, -0.95f, 5.0f}, sVECTOR3D{0.0f, -0.9f, 1.8f}, "models/earthfighter/lnch4.vw3d", "models/earthfighter/lnch34.tga", ""}
94 };
95 #pragma GCC diagnostic pop
96
97 // alien 101-199
98 #pragma GCC diagnostic push
99 #pragma GCC diagnostic ignored "-Winline"
100 const std::vector<sWeaponData> PresetAlienWeaponData{
101 // like Kinetic1
102 {eGameSFX::WeaponFire_Ion2, true, 1.0f, 1, 1, 5000, 0.7f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
103 // homing, like Kinetic2
104 {eGameSFX::WeaponFire_Plasma1, false, 1.0f, 1, 1, 2500, 3.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
105 // like Kinetic3
106 {eGameSFX::WeaponFire_Plasma2, true, 1.0f, 1, 1, 2500, 3.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
107 // homing, like Kinetic3
108 {eGameSFX::WeaponFire_Plasma2, false, 1.0f, 1, 1, 2500, 2.5f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
109 // like Kinetic2
110 {eGameSFX::WeaponFire_Plasma1, true, 1.0f, 1, 1, 2500, 3.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
111 // emergy mine 1
112 {eGameSFX::WeaponFire_Antimatter, false, 1.0f, 1, 1, 50, 5.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
113 // emergy mine 2, with homing
114 {eGameSFX::WeaponFire_Antimatter, false, 1.0f, 1, 1, 50, 5.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
115 // like Plasma3
116 {eGameSFX::WeaponFire_Plasma3, true, 10, 3, 50, 800, 0.9f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
117 // like Plasma2
118 {eGameSFX::WeaponFire_Plasma2, true, 15, 2, 25, 1000, 0.8f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
119 // like Laser (for matherships)
120 {eGameSFX::WeaponFire_Laser, true, 15, 5, 150, 800, 1.2f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""}
121 };
122 #pragma GCC diagnostic pop
123
124 // pirate 201-299
125 #pragma GCC diagnostic push
126 #pragma GCC diagnostic ignored "-Winline"
127 const std::vector<sWeaponData> PresetPirateWeaponData{
128 // turrent 1
129 {eGameSFX::WeaponFire_Kinetic1, false, 10, 1, 1, 3000, 0.7f, sVECTOR3D{0.0f, 1.5f, 1.0f}, sVECTOR3D{0.0f, 1.5f, 1.0f}, "models/turret/turret-01.vw3d", "models/turret/turrets.tga", ""},
130 // turrent 2
131 {eGameSFX::WeaponFire_Kinetic2, false, 10, 1, 1, 3000, 0.7f, sVECTOR3D{0.0f, 1.0f, 0.0f}, sVECTOR3D{0.0f, 1.0f, 0.0f}, "models/turret/turret-02.vw3d", "models/turret/turrets.tga", ""},
132
133 // flares
134 {eGameSFX::WeaponFire_Kinetic1, false, 1.0f, 1, 1, 2500, 4.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
135
136 // like Kinetic1
137 {eGameSFX::WeaponFire_Kinetic1, true, 10, 1, 1.7f, 3000, 0.7f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
138 // like Missile1
139 {eGameSFX::WeaponFire_SmallMissile, false, 80, 4, 5, 200, 5.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
140 // like Missile2
141 {eGameSFX::WeaponFire_NormalMissile, false, 30, 4, 5, 800, 8.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
142 // like Ion2
143 {eGameSFX::WeaponFire_Ion2, true, 10, 1, 10, 2000, 0.9f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
144 // like Antimatter
145 {eGameSFX::WeaponFire_Antimatter, true, 20, 4, 50, 5000, 0.8f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
146 // like Missile3 (torpedo)
147 {eGameSFX::WeaponFire_Torpedo, false, 25, 5, 10, 200, 8.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
148 // like Missile4 (bomb)
149 {eGameSFX::WeaponFire_Bomb, false, 30, 5, 15, 100, 10.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
150 // like Kinetic2
151 {eGameSFX::WeaponFire_Kinetic2, true, 25, 1, 3, 1500, 0.6f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
152 // like Kinetic3
153 {eGameSFX::WeaponFire_Kinetic3, true, 30, 2, 3.5, 500, 0.7f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
154 // like Plasma2
155 {eGameSFX::WeaponFire_Plasma2, true, 15, 2, 25, 1000, 0.8f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
156
157 // mine 1
158 {eGameSFX::WeaponFire_Torpedo, false, 1.0f, 1, 1, 2500, 4.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
159 // mine 2
160 {eGameSFX::WeaponFire_Torpedo, false, 1.0f, 1, 1, 2500, 4.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
161 // mine 31
162 {eGameSFX::WeaponFire_Bomb, false, 1.0f, 1, 1, 2500, 4.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""},
163 // mine 4
164 {eGameSFX::WeaponFire_Bomb, false, 1.0f, 1, 1, 2500, 4.0f, sVECTOR3D{0.0f, 0.0f, 0.0f}, sVECTOR3D{0.0f, 0.0f, 0.0f}, "", "", ""}
165 };
166 #pragma GCC diagnostic pop
167
168 } // unnamed namespace
169
170
171 /*
172 * Create cWeapon object.
173 */
CreateWeapon(const int WeaponNum)174 std::weak_ptr<cWeapon> CreateWeapon(const int WeaponNum)
175 {
176 // NOTE emplace_front() return reference to the inserted element (since C++17)
177 // this two lines could be combined
178 WeaponList.emplace_front(new cWeapon{WeaponNum}, [](cWeapon *p) {delete p;});
179 return WeaponList.front();
180 }
181
182 /*
183 * Update and remove (erase) dead objects.
184 */
UpdateAllWeapon(float Time)185 void UpdateAllWeapon(float Time)
186 {
187 // NOTE use std::erase_if here (since C++20)
188 for (auto iter = WeaponList.begin(); iter != WeaponList.end();) {
189 if (!iter->get()->Update(Time))
190 iter = WeaponList.erase(iter);
191 else
192 ++iter;
193 }
194 }
195
196 /*
197 * Draw all objects.
198 */
DrawAllWeapons(bool VertexOnlyPass,unsigned int ShadowMap)199 void DrawAllWeapons(bool VertexOnlyPass, unsigned int ShadowMap)
200 {
201 for (auto &tmpWeapon : WeaponList) {
202 tmpWeapon.get()->Draw(VertexOnlyPass, ShadowMap);
203 }
204 }
205
206 /*
207 * Release particular weapon object.
208 */
ReleaseWeapon(std::weak_ptr<cWeapon> & Object)209 void ReleaseWeapon(std::weak_ptr<cWeapon> &Object)
210 {
211 auto sharedObject = Object.lock();
212 if (!sharedObject)
213 return;
214
215 for (auto iter = WeaponList.begin(); iter != WeaponList.end();) {
216 if (iter->get() == sharedObject.get()) {
217 WeaponList.erase(iter);
218 return;
219 }
220 ++iter;
221 }
222 }
223
224 /*
225 * Release particular weapon object during update cycle.
226 */
ReleaseWeaponLazy(std::weak_ptr<cWeapon> & Object)227 void ReleaseWeaponLazy(std::weak_ptr<cWeapon> &Object)
228 {
229 auto sharedObject = Object.lock();
230 if (!sharedObject)
231 return;
232
233 // make sure, that the DeleteAfterLeaveScene is disabled,
234 // in order to prevent possible Lifetime counter reset
235 sharedObject->DeleteAfterLeaveScene = eDeleteAfterLeaveScene::disabled;
236 sharedObject->Lifetime = 0.0f;
237 }
238
239 /*
240 * Release all objects.
241 */
ReleaseAllWeapons()242 void ReleaseAllWeapons()
243 {
244 WeaponList.clear();
245 }
246
247 /*
248 * Setup fire gfx.
249 */
SetWeaponFire(std::shared_ptr<cParticleSystem> & ParticleSystem,const int WeaponNum)250 static void SetWeaponFire(std::shared_ptr<cParticleSystem> &ParticleSystem, const int WeaponNum)
251 {
252 ParticleSystem->Texture = GetPreloadedTextureAsset("gfx/flare1.tga");
253 ParticleSystem->ParticlesPerSec = 50;
254 ParticleSystem->IsSuppressed = true;
255
256 switch (WeaponNum) {
257 case 1:
258 ParticleSystem->ColorStart.r = 1.00f;
259 ParticleSystem->ColorStart.g = 0.70f;
260 ParticleSystem->ColorStart.b = 0.30f;
261 ParticleSystem->ColorEnd.r = 1.00f;
262 ParticleSystem->ColorEnd.g = 0.70f;
263 ParticleSystem->ColorEnd.b = 0.00f;
264 ParticleSystem->AlphaStart = 0.60f;
265 ParticleSystem->AlphaEnd = 0.10f;
266 ParticleSystem->SizeStart = 0.4f;
267 ParticleSystem->SizeVar = 0.05f;
268 ParticleSystem->SizeEnd = 0.10f;
269 ParticleSystem->Speed = 3.00f;
270 ParticleSystem->SpeedVar = 3.00f;
271 ParticleSystem->Theta = 30.00f;
272 ParticleSystem->Life = 0.40f;
273 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.7f, 0.15f, 0.0f, 0.02f);
274 break;
275 case 2:
276 ParticleSystem->ColorStart.r = 1.00f;
277 ParticleSystem->ColorStart.g = 0.50f;
278 ParticleSystem->ColorStart.b = 0.10f;
279 ParticleSystem->ColorEnd.r = 1.00f;
280 ParticleSystem->ColorEnd.g = 0.50f;
281 ParticleSystem->ColorEnd.b = 0.00f;
282 ParticleSystem->AlphaStart = 0.60f;
283 ParticleSystem->AlphaEnd = 0.10f;
284 ParticleSystem->SizeStart = 0.50f;
285 ParticleSystem->SizeVar = 0.05f;
286 ParticleSystem->SizeEnd = 0.10f;
287 ParticleSystem->Speed = 2.00f;
288 ParticleSystem->SpeedVar = 3.00f;
289 ParticleSystem->Theta = 40.00f;
290 ParticleSystem->Life = 0.40f;
291 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.5f, 0.05f, 0.0f, 0.02f);
292 break;
293 case 3:
294 ParticleSystem->ColorStart.r = 1.00f;
295 ParticleSystem->ColorStart.g = 0.50f;
296 ParticleSystem->ColorStart.b = 0.10f;
297 ParticleSystem->ColorEnd.r = 1.00f;
298 ParticleSystem->ColorEnd.g = 0.50f;
299 ParticleSystem->ColorEnd.b = 0.00f;
300 ParticleSystem->AlphaStart = 0.60f;
301 ParticleSystem->AlphaEnd = 0.10f;
302 ParticleSystem->SizeStart = 0.60f;
303 ParticleSystem->SizeVar = 0.05f;
304 ParticleSystem->SizeEnd = 0.10f;
305 ParticleSystem->Speed = 1.00f;
306 ParticleSystem->SpeedVar = 3.00f;
307 ParticleSystem->Theta = 50.00f;
308 ParticleSystem->Life = 0.50f;
309 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.5f, 0.05f, 0.0f, 0.02f);
310 break;
311 case 4:
312 ParticleSystem->ColorStart.r = 1.00f;
313 ParticleSystem->ColorStart.g = 0.70f;
314 ParticleSystem->ColorStart.b = 0.30f;
315 ParticleSystem->ColorEnd.r = 1.00f;
316 ParticleSystem->ColorEnd.g = 0.70f;
317 ParticleSystem->ColorEnd.b = 0.00f;
318 ParticleSystem->AlphaStart = 0.60f;
319 ParticleSystem->AlphaEnd = 0.10f;
320 ParticleSystem->SizeStart = 0.30f;
321 ParticleSystem->SizeVar = 0.05f;
322 ParticleSystem->SizeEnd = 0.10f;
323 ParticleSystem->Speed = 3.00f;
324 ParticleSystem->SpeedVar = 3.00f;
325 ParticleSystem->Theta = 30.00f;
326 ParticleSystem->Life = 0.50f;
327 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.7f, 0.15f, 0.0f, 0.02f);
328 break;
329 case 5:
330 ParticleSystem->ColorStart.r = 0.70f;
331 ParticleSystem->ColorStart.g = 1.00f;
332 ParticleSystem->ColorStart.b = 0.70f;
333 ParticleSystem->ColorEnd.r = 0.00f;
334 ParticleSystem->ColorEnd.g = 0.00f;
335 ParticleSystem->ColorEnd.b = 0.00f;
336 ParticleSystem->AlphaStart = 0.60f;
337 ParticleSystem->AlphaEnd = 0.00f;
338 ParticleSystem->SizeStart = 0.30f;
339 ParticleSystem->SizeEnd = 0.00f;
340 ParticleSystem->Speed = 4.00f;
341 ParticleSystem->SpeedVar = 1.00f;
342 ParticleSystem->Theta = 10.00f;
343 ParticleSystem->Life = 0.40f;
344 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.5f, 0.35f, 0.0f, 0.02f);
345 break;
346 case 6:
347 ParticleSystem->ColorStart.r = 0.70f;
348 ParticleSystem->ColorStart.g = 1.00f;
349 ParticleSystem->ColorStart.b = 0.70f;
350 ParticleSystem->ColorEnd.r = 0.00f;
351 ParticleSystem->ColorEnd.g = 0.00f;
352 ParticleSystem->ColorEnd.b = 0.00f;
353 ParticleSystem->AlphaStart = 0.60f;
354 ParticleSystem->AlphaEnd = 0.20f;
355 ParticleSystem->SizeStart = 0.50f;
356 ParticleSystem->SizeEnd = 0.20f;
357 ParticleSystem->Speed = 3.00f;
358 ParticleSystem->SpeedVar = 1.00f;
359 ParticleSystem->Theta = 20.00f;
360 ParticleSystem->Life = 0.40f;
361 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.5f, 0.35f, 0.0f, 0.02f);
362 break;
363 case 7:
364 ParticleSystem->ColorStart.r = 0.70f;
365 ParticleSystem->ColorStart.g = 1.00f;
366 ParticleSystem->ColorStart.b = 0.70f;
367 ParticleSystem->ColorEnd.r = 0.00f;
368 ParticleSystem->ColorEnd.g = 0.00f;
369 ParticleSystem->ColorEnd.b = 0.00f;
370 ParticleSystem->AlphaStart = 0.60f;
371 ParticleSystem->AlphaEnd = 0.20f;
372 ParticleSystem->SizeStart = 0.50f;
373 ParticleSystem->SizeEnd = 0.20f;
374 ParticleSystem->Speed = 6.00f;
375 ParticleSystem->SpeedVar = 1.00f;
376 ParticleSystem->Theta = 10.00f;
377 ParticleSystem->Life = 0.40f;
378 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.5f, 0.35f, 0.0f, 0.02f);
379 break;
380 case 8:
381 ParticleSystem->ColorStart.r = 0.00f;
382 ParticleSystem->ColorStart.g = 0.50f;
383 ParticleSystem->ColorStart.b = 1.00f;
384 ParticleSystem->ColorEnd.r = 0.70f;
385 ParticleSystem->ColorEnd.g = 1.00f;
386 ParticleSystem->ColorEnd.b = 1.00f;
387 ParticleSystem->AlphaStart = 0.60f;
388 ParticleSystem->AlphaEnd = 0.10f;
389 ParticleSystem->SizeStart = 0.2f;
390 ParticleSystem->SizeVar = 0.05f;
391 ParticleSystem->SizeEnd = 0.2f;
392 ParticleSystem->Speed = 4.00f;
393 ParticleSystem->SpeedVar = 3.00f;
394 ParticleSystem->Theta = 0.00f;
395 ParticleSystem->Life = 0.30f;
396 ParticleSystem->CreationType = eParticleCreationType::Sphere;
397 ParticleSystem->CreationSize(0.4f, 0.4f, 0.4f);
398 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.75f, 1.0f, 0.0f, 0.02f);
399 break;
400 case 9:
401 ParticleSystem->ColorStart.r = 0.00f;
402 ParticleSystem->ColorStart.g = 0.50f;
403 ParticleSystem->ColorStart.b = 1.00f;
404 ParticleSystem->ColorEnd.r = 0.70f;
405 ParticleSystem->ColorEnd.g = 1.00f;
406 ParticleSystem->ColorEnd.b = 1.00f;
407 ParticleSystem->AlphaStart = 0.60f;
408 ParticleSystem->AlphaEnd = 0.10f;
409 ParticleSystem->SizeStart = 0.15f;
410 ParticleSystem->SizeVar = 0.05f;
411 ParticleSystem->SizeEnd = 0.15f;
412 ParticleSystem->Speed = 3.00f;
413 ParticleSystem->SpeedVar = 3.00f;
414 ParticleSystem->Theta = 0.00f;
415 ParticleSystem->Life = 0.40f;
416 ParticleSystem->CreationType = eParticleCreationType::Sphere;
417 ParticleSystem->CreationSize(0.3f, 0.3f, 0.3f);
418 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.75f, 1.0f, 0.0f, 0.02f);
419 break;
420 case 10:
421 ParticleSystem->ColorStart.r = 0.00f;
422 ParticleSystem->ColorStart.g = 0.50f;
423 ParticleSystem->ColorStart.b = 1.00f;
424 ParticleSystem->ColorEnd.r = 0.70f;
425 ParticleSystem->ColorEnd.g = 1.00f;
426 ParticleSystem->ColorEnd.b = 1.00f;
427 ParticleSystem->AlphaStart = 0.60f;
428 ParticleSystem->AlphaEnd = 0.10f;
429 ParticleSystem->SizeStart = 0.30f;
430 ParticleSystem->SizeVar = 0.05f;
431 ParticleSystem->SizeEnd = 0.30f;
432 ParticleSystem->Speed = 3.00f;
433 ParticleSystem->SpeedVar = 3.00f;
434 ParticleSystem->Theta = 0.00f;
435 ParticleSystem->Life = 0.50f;
436 ParticleSystem->CreationType = eParticleCreationType::Sphere;
437 ParticleSystem->CreationSize(0.3f, 0.3f, 0.3f);
438 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.35f, 0.75f, 1.0f, 0.0f, 0.02f);
439 break;
440 case 11:
441 ParticleSystem->ColorStart.r = 0.70f;
442 ParticleSystem->ColorStart.g = 1.00f;
443 ParticleSystem->ColorStart.b = 0.30f;
444 ParticleSystem->ColorEnd.r = 0.00f;
445 ParticleSystem->ColorEnd.g = 1.00f;
446 ParticleSystem->ColorEnd.b = 0.00f;
447 ParticleSystem->AlphaStart = 0.60f;
448 ParticleSystem->AlphaEnd = 0.60f;
449 ParticleSystem->SizeStart = 0.1f;
450 ParticleSystem->SizeVar = 0.05f;
451 ParticleSystem->SizeEnd = 0.00f;
452 ParticleSystem->Speed = 3.00f;
453 ParticleSystem->SpeedVar = 3.00f;
454 ParticleSystem->Theta = 30.00f;
455 ParticleSystem->Life = 0.30f;
456 ParticleSystem->IsMagnet = true;
457 ParticleSystem->ParticlesPerSec = 20;
458 ParticleSystem->CreationType = eParticleCreationType::Sphere;
459 ParticleSystem->CreationSize(0.3f, 0.2f, 0.3f);
460 break;
461 case 12:
462 ParticleSystem->ColorStart.r = 0.70f;
463 ParticleSystem->ColorStart.g = 1.00f;
464 ParticleSystem->ColorStart.b = 0.30f;
465 ParticleSystem->ColorEnd.r = 0.00f;
466 ParticleSystem->ColorEnd.g = 1.00f;
467 ParticleSystem->ColorEnd.b = 0.00f;
468 ParticleSystem->AlphaStart = 0.60f;
469 ParticleSystem->AlphaEnd = 0.60f;
470 ParticleSystem->SizeStart = 0.1f;
471 ParticleSystem->SizeVar = 0.05f;
472 ParticleSystem->SizeEnd = 0.00f;
473 ParticleSystem->Speed = 3.00f;
474 ParticleSystem->SpeedVar = 3.00f;
475 ParticleSystem->Theta = 30.00f;
476 ParticleSystem->Life = 0.30f;
477 ParticleSystem->IsMagnet = true;
478 ParticleSystem->ParticlesPerSec = 20;
479 ParticleSystem->CreationType = eParticleCreationType::Sphere;
480 ParticleSystem->CreationSize(0.3f, 0.2f, 0.3f);
481 break;
482 case 13:
483 ParticleSystem->ColorStart.r = 0.70f;
484 ParticleSystem->ColorStart.g = 1.00f;
485 ParticleSystem->ColorStart.b = 0.00f;
486 ParticleSystem->ColorEnd.r = 0.70f;
487 ParticleSystem->ColorEnd.g = 1.00f;
488 ParticleSystem->ColorEnd.b = 0.00f;
489 ParticleSystem->AlphaStart = 0.60f;
490 ParticleSystem->AlphaEnd = 0.10f;
491 ParticleSystem->SizeStart = 0.4f;
492 ParticleSystem->SizeVar = 0.05f;
493 ParticleSystem->SizeEnd = 0.10f;
494 ParticleSystem->Speed = 3.00f;
495 ParticleSystem->SpeedVar = 3.00f;
496 ParticleSystem->Theta = 30.00f;
497 ParticleSystem->Life = 0.40f;
498 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 0.7f, 1.0f, 0.0f, 0.0f, 0.02f);
499 break;
500 case 14:
501 ParticleSystem->ColorStart.r = 1.00f;
502 ParticleSystem->ColorStart.g = 1.00f;
503 ParticleSystem->ColorStart.b = 0.00f;
504 ParticleSystem->ColorEnd.r = 1.00f;
505 ParticleSystem->ColorEnd.g = 1.00f;
506 ParticleSystem->ColorEnd.b = 0.00f;
507 ParticleSystem->AlphaStart = 1.00f;
508 ParticleSystem->AlphaEnd = 1.00f;
509 ParticleSystem->SizeStart = 0.10f;
510 ParticleSystem->SizeVar = 0.05f;
511 ParticleSystem->SizeEnd = 0.00f;
512 ParticleSystem->Speed = 1.00f;
513 ParticleSystem->SpeedVar = 0.00f;
514 ParticleSystem->Theta = 360.00f;
515 ParticleSystem->Life = 0.20f;
516 ParticleSystem->ParticlesPerSec = 200;
517 ParticleSystem->CreationType = eParticleCreationType::Sphere;
518 ParticleSystem->CreationSize = sVECTOR3D{0.2f, 0.2f, 0.8f};
519 break;
520 case 15:
521 ParticleSystem->ColorStart.r = 1.00f;
522 ParticleSystem->ColorStart.g = 0.50f;
523 ParticleSystem->ColorStart.b = 0.00f;
524 ParticleSystem->ColorEnd.r = 1.00f;
525 ParticleSystem->ColorEnd.g = 0.50f;
526 ParticleSystem->ColorEnd.b = 0.00f;
527 ParticleSystem->AlphaStart = 0.60f;
528 ParticleSystem->AlphaEnd = 0.10f;
529 ParticleSystem->SizeStart = 0.4f;
530 ParticleSystem->SizeVar= 0.05f;
531 ParticleSystem->SizeEnd = 0.10f;
532 ParticleSystem->Speed = 3.00f;
533 ParticleSystem->SpeedVar = 3.00f;
534 ParticleSystem->Theta = 30.00f;
535 ParticleSystem->Life = 0.40f;
536 ParticleSystem->Light = vw_CreatePointLight(sVECTOR3D{0.0f, 0.0f, 0.0f}, 1.0f, 0.5f, 0.0f, 0.0f, 0.02f);
537 break;
538 case 16:
539 ParticleSystem->ColorStart.r = 1.00f;
540 ParticleSystem->ColorStart.g = 0.70f;
541 ParticleSystem->ColorStart.b = 0.30f;
542 ParticleSystem->ColorEnd.r = 1.00f;
543 ParticleSystem->ColorEnd.g = 0.70f;
544 ParticleSystem->ColorEnd.b = 0.00f;
545 ParticleSystem->AlphaStart = 0.60f;
546 ParticleSystem->AlphaEnd = 0.10f;
547 ParticleSystem->SizeStart = 0.4f;
548 ParticleSystem->SizeVar = 0.05f;
549 ParticleSystem->SizeEnd = 0.10f;
550 ParticleSystem->Speed = 3.00f;
551 ParticleSystem->SpeedVar = 3.00f;
552 ParticleSystem->Theta = 30.00f;
553 ParticleSystem->Life = 0.40f;
554 break;
555 case 17:
556 ParticleSystem->ColorStart.r = 1.00f;
557 ParticleSystem->ColorStart.g = 0.70f;
558 ParticleSystem->ColorStart.b = 0.30f;
559 ParticleSystem->ColorEnd.r = 1.00f;
560 ParticleSystem->ColorEnd.g = 0.70f;
561 ParticleSystem->ColorEnd.b = 0.00f;
562 ParticleSystem->AlphaStart = 0.60f;
563 ParticleSystem->AlphaEnd = 0.10f;
564 ParticleSystem->SizeStart = 0.4f;
565 ParticleSystem->SizeVar = 0.05f;
566 ParticleSystem->SizeEnd = 0.10f;
567 ParticleSystem->Speed = 3.00f;
568 ParticleSystem->SpeedVar = 3.00f;
569 ParticleSystem->Theta = 30.00f;
570 ParticleSystem->Life = 0.40f;
571 break;
572 case 18:
573 ParticleSystem->ColorStart.r = 1.00f;
574 ParticleSystem->ColorStart.g = 0.70f;
575 ParticleSystem->ColorStart.b = 0.30f;
576 ParticleSystem->ColorEnd.r = 1.00f;
577 ParticleSystem->ColorEnd.g = 0.70f;
578 ParticleSystem->ColorEnd.b = 0.00f;
579 ParticleSystem->AlphaStart = 0.60f;
580 ParticleSystem->AlphaEnd = 0.10f;
581 ParticleSystem->SizeStart = 0.4f;
582 ParticleSystem->SizeVar = 0.05f;
583 ParticleSystem->SizeEnd = 0.10f;
584 ParticleSystem->Speed = 3.00f;
585 ParticleSystem->SpeedVar = 3.00f;
586 ParticleSystem->Theta = 30.00f;
587 ParticleSystem->Life = 0.40f;
588 break;
589 case 19:
590 ParticleSystem->ColorStart.r = 1.00f;
591 ParticleSystem->ColorStart.g = 0.70f;
592 ParticleSystem->ColorStart.b = 0.30f;
593 ParticleSystem->ColorEnd.r = 1.00f;
594 ParticleSystem->ColorEnd.g = 0.70f;
595 ParticleSystem->ColorEnd.b = 0.00f;
596 ParticleSystem->AlphaStart = 0.60f;
597 ParticleSystem->AlphaEnd = 0.10f;
598 ParticleSystem->SizeStart = 0.4f;
599 ParticleSystem->SizeVar = 0.05f;
600 ParticleSystem->SizeEnd = 0.10f;
601 ParticleSystem->Speed = 3.00f;
602 ParticleSystem->SpeedVar = 3.00f;
603 ParticleSystem->Theta = 30.00f;
604 ParticleSystem->Life = 0.40f;
605 break;
606
607 default:
608 std::cerr << __func__ << "(): " << "wrong WeaponNum.\n";
609 break;
610 }
611 }
612
613 /*
614 * Constructor.
615 */
cWeapon(const int WeaponNum)616 cWeapon::cWeapon(const int WeaponNum)
617 {
618 ObjectStatus = eObjectStatus::Ally;
619 ObjectType = eObjectType::ShipWeapon;
620
621 ShowStatus = false;
622
623 if (WeaponNum <= 0) {
624 std::cerr << __func__ << "(): " << "Couldn't init cWeapon object with Number " << WeaponNum << "\n";
625 return;
626 } else if ((WeaponNum >= 1 && WeaponNum <= 99) && ((unsigned int)WeaponNum > PresetEarthWeaponData.size())) {
627 std::cerr << __func__ << "(): " << "Couldn't init cWeapon(1) object with Number " << WeaponNum << "\n";
628 return;
629 } else if ((WeaponNum >= 101 && WeaponNum <= 199) && ((unsigned int)WeaponNum - 100 > PresetAlienWeaponData.size())) {
630 std::cerr << __func__ << "(): " << "Couldn't init cWeapon(2) object with Number " << WeaponNum << "\n";
631 return;
632 } else if ((WeaponNum >= 201 && WeaponNum <= 299) && ((unsigned int)WeaponNum - 200 > PresetPirateWeaponData.size())) {
633 std::cerr << __func__ << "(): " << "Couldn't init cWeapon(3) object with Number " << WeaponNum << "\n";
634 return;
635 }
636
637 InternalType = WeaponNum;
638
639 // earth 1-99
640 if (WeaponNum >= 1 && WeaponNum <= 99) {
641 ObjectStatus = eObjectStatus::Ally;
642
643 ArmorCurrentStatus = ArmorInitialStatus = PresetEarthWeaponData[WeaponNum - 1].Armor;
644 WeaponLevel = PresetEarthWeaponData[WeaponNum - 1].WeaponLevel;
645 Ammo = AmmoStart = PresetEarthWeaponData[WeaponNum - 1].Ammo;
646 NextFireTime = PresetEarthWeaponData[WeaponNum - 1].NextFireTime;
647 SFX = PresetEarthWeaponData[WeaponNum - 1].SFX;
648 NeedRotateOnTargeting = PresetEarthWeaponData[WeaponNum - 1].NeedRotateOnTargeting;
649
650 CurrentEnergyAccumulated = EnergyUse = PresetEarthWeaponData[WeaponNum - 1].EnergyUse;
651 FireLocation = PresetEarthWeaponData[WeaponNum - 1].FireLocation;
652
653 DestroyedFireLocation = PresetEarthWeaponData[WeaponNum - 1].DestrFireLocation;
654 Fire = vw_CreateParticleSystem();
655 if (auto sharedFire = Fire.lock()) {
656 sharedFire->SetStartLocation(FireLocation);
657 sharedFire->Direction = sVECTOR3D{0.0f, 0.0f, 1.0f};
658 SetWeaponFire(sharedFire, WeaponNum);
659 }
660
661 LoadObjectData(PresetEarthWeaponData[WeaponNum - 1].NameVW3D, *this);
662
663 for (unsigned int i = 0; i < Chunks.size(); i++) {
664 Texture[i] = GetPreloadedTextureAsset(PresetEarthWeaponData[WeaponNum - 1].TextureName);
665 if (WeaponNum < 16)
666 TextureIllum[i] = GetPreloadedTextureAsset(PresetEarthWeaponData[WeaponNum - 1].TextureIllumName);
667 }
668
669 }
670 // alien 101-199
671 else if ((WeaponNum >= 101) &&
672 (WeaponNum <= 199)) {
673 int IntWeaponNum = WeaponNum - 100;
674
675 ObjectStatus = eObjectStatus::Enemy;
676
677 ArmorCurrentStatus = ArmorInitialStatus = PresetAlienWeaponData[IntWeaponNum - 1].Armor;
678 WeaponLevel = PresetAlienWeaponData[IntWeaponNum - 1].WeaponLevel;
679 Ammo = AmmoStart = PresetAlienWeaponData[IntWeaponNum - 1].Ammo;
680 NextFireTime = PresetAlienWeaponData[IntWeaponNum - 1].NextFireTime;
681 SFX = PresetAlienWeaponData[IntWeaponNum - 1].SFX;
682 NeedRotateOnTargeting = PresetAlienWeaponData[IntWeaponNum - 1].NeedRotateOnTargeting;
683
684 CurrentEnergyAccumulated = EnergyUse = PresetAlienWeaponData[IntWeaponNum - 1].EnergyUse;
685 FireLocation = PresetAlienWeaponData[IntWeaponNum - 1].FireLocation;
686
687 }
688 // pirate 201-299
689 else if ((WeaponNum >= 201) &&
690 (WeaponNum <= 299)) {
691 int IntWeaponNum = WeaponNum - 200;
692
693 ObjectStatus = eObjectStatus::Enemy;
694
695 ArmorCurrentStatus = ArmorInitialStatus = PresetPirateWeaponData[IntWeaponNum - 1].Armor;
696 WeaponLevel = PresetPirateWeaponData[IntWeaponNum - 1].WeaponLevel;
697 Ammo = AmmoStart = PresetPirateWeaponData[IntWeaponNum - 1].Ammo;
698 NextFireTime = PresetPirateWeaponData[IntWeaponNum - 1].NextFireTime;
699 SFX = PresetPirateWeaponData[IntWeaponNum - 1].SFX;
700 NeedRotateOnTargeting = PresetPirateWeaponData[IntWeaponNum - 1].NeedRotateOnTargeting;
701
702 CurrentEnergyAccumulated = EnergyUse = PresetPirateWeaponData[IntWeaponNum - 1].EnergyUse;
703 FireLocation = PresetPirateWeaponData[IntWeaponNum - 1].FireLocation;
704
705 // турели пиратов
706 switch (WeaponNum) {
707 case 201:
708 WeaponTurret = true;
709 TargetHorizChunkNum = 0;
710 TargetVertChunkNum = 1;
711 TargetVertChunkMaxAngle = 89.0f;
712 TargetVertChunkMinAngle = 0.0f;
713
714 LoadObjectData(PresetPirateWeaponData[IntWeaponNum - 1].NameVW3D, *this);
715 for (unsigned int i = 0; i < Chunks.size(); i++) {
716 Texture[i] = GetPreloadedTextureAsset(PresetPirateWeaponData[IntWeaponNum - 1].TextureName);
717 TextureIllum[i] = 0;
718 }
719 break;
720
721 case 202:
722 WeaponTurret = true;
723 TargetHorizChunkNum = 0;
724 TargetVertChunkNum = 1;
725 TargetVertChunkMaxAngle = 89.0f;
726 TargetVertChunkMinAngle = 20.0f;
727
728 LoadObjectData(PresetPirateWeaponData[IntWeaponNum - 1].NameVW3D, *this);
729 for (unsigned int i = 0; i < Chunks.size(); i++) {
730 Texture[i] = GetPreloadedTextureAsset(PresetPirateWeaponData[IntWeaponNum - 1].TextureName);
731 TextureIllum[i] = 0;
732 }
733 break;
734 }
735
736 if ((WeaponNum == 201) ||
737 (WeaponNum == 202)) {
738 if (TargetHorizChunkNum != -1) {
739 BaseBound = Chunks[TargetHorizChunkNum].Location;
740 }
741
742 if (TargetVertChunkNum != -1) {
743 if (TargetHorizChunkNum != -1)
744 MiddleBound = Chunks[TargetVertChunkNum].Location -
745 Chunks[TargetHorizChunkNum].Location;
746 else
747 MiddleBound = Chunks[TargetVertChunkNum].Location;
748 }
749
750 if (TargetVertChunkNum != -1)
751 WeaponBound = FireLocation - Chunks[TargetVertChunkNum].Location;
752 else if (TargetHorizChunkNum != -1)
753 WeaponBound = FireLocation - Chunks[TargetHorizChunkNum].Location;
754 else
755 WeaponBound = FireLocation;
756 }
757 }
758 }
759
760 /*
761 * Destructor.
762 */
~cWeapon()763 cWeapon::~cWeapon()
764 {
765 if (auto sharedFire = Fire.lock()) {
766 sharedFire->IsSuppressed = true;
767 sharedFire->DestroyIfNoParticles = true;
768 }
769 if (auto sharedDestroyedFire = DestroyedFire.lock()) {
770 sharedDestroyedFire->IsSuppressed = true;
771 sharedDestroyedFire->DestroyIfNoParticles = true;
772 }
773 if (auto sharedDestroyedSmoke = DestroyedSmoke.lock()) {
774 sharedDestroyedSmoke->IsSuppressed = true;
775 sharedDestroyedSmoke->DestroyIfNoParticles = true;
776 }
777 if (!LaserMaser.expired()) {
778 ReleaseProjectile(LaserMaser);
779 if (vw_IsSoundAvailable(LaserMaserSoundNum))
780 vw_StopSound(LaserMaserSoundNum, 150);
781 }
782 }
783
784 /*
785 * Update.
786 */
Update(float Time)787 bool cWeapon::Update(float Time)
788 {
789 if (auto sharedLaserMaser = LaserMaser.lock()) {
790 if (sharedLaserMaser->Lifetime <= 0.0f)
791 ReleaseProjectile(LaserMaser);
792 }
793
794 if (!cObject3D::Update(Time))
795 return false;
796
797 if (LastFireTime + TimeDelta <= Time)
798 if (auto sharedFire = Fire.lock())
799 sharedFire->IsSuppressed = true;
800
801 if ((InternalType >= 1) &&
802 (InternalType <= 99) &&
803 (ArmorCurrentStatus < ArmorInitialStatus) &&
804 DestroyedFire.expired()) {
805 DestroyedFire = vw_CreateParticleSystem();
806 if (auto sharedDestroyedFire = DestroyedFire.lock()) {
807 sharedDestroyedFire->ColorStart.r = 1.00f;
808 sharedDestroyedFire->ColorStart.g = 0.70f;
809 sharedDestroyedFire->ColorStart.b = 0.30f;
810 sharedDestroyedFire->ColorEnd.r = 1.00f;
811 sharedDestroyedFire->ColorEnd.g = 0.00f;
812 sharedDestroyedFire->ColorEnd.b = 0.00f;
813 sharedDestroyedFire->AlphaStart = 1.00f;
814 sharedDestroyedFire->AlphaEnd = 0.10f;
815 sharedDestroyedFire->SizeStart = 0.20f;
816 sharedDestroyedFire->SizeVar= 0.10f;
817 sharedDestroyedFire->SizeEnd = 0.10f;
818 sharedDestroyedFire->Speed = 8.00f;
819 sharedDestroyedFire->SpeedVar = 2.00f;
820 sharedDestroyedFire->Theta = 5.00f;
821 sharedDestroyedFire->Life = 0.50f * Length / 3.0f;
822 sharedDestroyedFire->ParticlesPerSec = 70;
823 sharedDestroyedFire->Texture = GetPreloadedTextureAsset("gfx/flare1.tga");
824 sharedDestroyedFire->CreationType = eParticleCreationType::Cube;
825 sharedDestroyedFire->CreationSize(Width / 2.0f, Width / 2.0f, 0.1f);
826 sharedDestroyedFire->Direction(0.0f, 0.0f, -1.0f);
827 sharedDestroyedFire->SetStartLocation(DestroyedFireLocation);
828 }
829 }
830
831 if ((InternalType >= 1) &&
832 (InternalType <= 99) &&
833 (ArmorCurrentStatus <= 0.0f) &&
834 DestroyedSmoke.expired()) {
835 DestroyedSmoke = vw_CreateParticleSystem();
836 if (auto sharedDestroyedSmoke = DestroyedSmoke.lock()) {
837 sharedDestroyedSmoke->ColorStart.r = 1.00f;
838 sharedDestroyedSmoke->ColorStart.g = 1.00f;
839 sharedDestroyedSmoke->ColorStart.b = 1.00f;
840 sharedDestroyedSmoke->ColorEnd.r = 1.00f;
841 sharedDestroyedSmoke->ColorEnd.g = 1.00f;
842 sharedDestroyedSmoke->ColorEnd.b = 1.00f;
843 sharedDestroyedSmoke->AlphaStart = 0.20f;
844 sharedDestroyedSmoke->AlphaEnd = 0.00f;
845 sharedDestroyedSmoke->SizeStart = 0.25f;
846 sharedDestroyedSmoke->SizeVar = 0.10f;
847 sharedDestroyedSmoke->SizeEnd = 0.00f;
848 sharedDestroyedSmoke->Speed = 0.00f;
849 sharedDestroyedSmoke->SpeedVar = 0.00f;
850 sharedDestroyedSmoke->Theta = 35.00f;
851 sharedDestroyedSmoke->Life = 2.00f * Length / 3.0f;
852 sharedDestroyedSmoke->ParticlesPerSec = 300;
853 sharedDestroyedSmoke->Texture = GetPreloadedTextureAsset("gfx/flare1.tga");
854 sharedDestroyedSmoke->CreationType = eParticleCreationType::Point;
855 sharedDestroyedSmoke->CreationSize(Width / 2.5f, Width / 2.5f, 0.1f);
856 sharedDestroyedSmoke->Direction(0.0f, 0.0f, -1.0f);
857 sharedDestroyedSmoke->SetStartLocation(DestroyedFireLocation);
858 }
859 }
860
861 if (InternalType == 17 && SwarmNum > 0)
862 if (LastFireTime + 0.15f < Time)
863 if (Ammo > 0 || !GameUnlimitedAmmo) {
864 LastFireTime = Time;
865
866 if (!GameUnlimitedAmmo)
867 Ammo -= 1;
868
869 float CurrentPenalty{1.0f};
870 if (ObjectStatus == eObjectStatus::Enemy)
871 CurrentPenalty = static_cast<float>(GameEnemyWeaponPenalty);
872
873 switch (SwarmNum) {
874 case 9:
875 FireLocation(-0.5f, -0.5f, 2.6f);
876 break;
877 case 8:
878 FireLocation(0.5f, -0.8f, 2.6f);
879 break;
880 case 7:
881 FireLocation(-0.5f, -0.8f, 2.6f);
882 break;
883 case 6:
884 FireLocation(0.5f, -0.5f, 2.6f);
885 break;
886 case 5:
887 FireLocation(-0.2f, -0.95f, 2.6f);
888 break;
889 case 4:
890 FireLocation(0.2f, -0.65f, 2.6f);
891 break;
892 case 3:
893 FireLocation(-0.2f, -0.3f, 2.6f);
894 break;
895 case 2:
896 FireLocation(0.2f, -0.65f, 2.6f);
897 break;
898 case 1:
899 FireLocation(0.2f, -0.3f, 2.6f);
900 break;
901 }
902 vw_Matrix33CalcPoint(FireLocation, CurrentRotationMat);
903
904 std::weak_ptr<cProjectile> tmpProjectile = CreateProjectile(InternalType);
905 if (auto sharedProjectile = tmpProjectile.lock()) {
906 sharedProjectile->SetLocation(Location + FireLocation);
907 sharedProjectile->SetRotation(Rotation);
908 for (auto &tmpGFX : sharedProjectile->GraphicFX) {
909 if (auto sharedGFX = tmpGFX.lock()) {
910 if (auto sharedFire = Fire.lock())
911 sharedGFX->Direction = sharedFire->Direction ^ -1;
912
913 if (CurrentPenalty == 2)
914 sharedGFX->ParticlesPerSec -= (int)(sharedGFX->ParticlesPerSec * 0.33f);
915 else if (CurrentPenalty == 3)
916 sharedGFX->ParticlesPerSec -= (int)(sharedGFX->ParticlesPerSec * 0.5f);
917 sharedGFX->Speed = sharedGFX->Speed / CurrentPenalty;
918 sharedGFX->Life = sharedGFX->Life * CurrentPenalty;
919 sharedGFX->MagnetFactor = sharedGFX->MagnetFactor / (CurrentPenalty * CurrentPenalty);
920 }
921 }
922 sharedProjectile->ObjectStatus = ObjectStatus;
923 sharedProjectile->SpeedStart = sharedProjectile->SpeedEnd = sharedProjectile->SpeedStart / CurrentPenalty;
924 sharedProjectile->Age = sharedProjectile->Lifetime = sharedProjectile->Age * CurrentPenalty;
925 sharedProjectile->Damage /= CurrentPenalty;
926
927 if (SFX != eGameSFX::none) {
928 float fVol = 1.0f;
929 PlayGameSFX(SFX, fVol, sharedProjectile->Location);
930 }
931 }
932 SwarmNum--;
933 }
934
935 if (InternalType == 203 && SwarmNum > 0)
936 if (LastFireTime + 0.4f < Time)
937 if (Ammo > 0 || !GameUnlimitedAmmo) {
938 LastFireTime = Time;
939
940 if (!GameUnlimitedAmmo)
941 Ammo -= 1;
942
943 float CurrentPenalty = 1.0f; // FIXME why we need if-else below if we use 1.0f only?
944
945 std::weak_ptr<cProjectile> tmpProjectile = CreateProjectile(InternalType);
946 if (auto sharedProjectile = tmpProjectile.lock()) {
947 sharedProjectile->SetLocation(Location + FireLocation);
948 sharedProjectile->SetRotation(Rotation + sVECTOR3D{vw_fRand0() * 30.0f,
949 0.0f,
950 vw_fRand0() * 30.0f});
951
952 for (auto &tmpGFX : sharedProjectile->GraphicFX) {
953 if (auto sharedGFX = tmpGFX.lock()) {
954 sharedGFX->Direction = Orientation ^ -1;
955
956 if (CurrentPenalty == 2)
957 sharedGFX->ParticlesPerSec -= (int)(sharedGFX->ParticlesPerSec * 0.33f);
958 else if (CurrentPenalty == 3)
959 sharedGFX->ParticlesPerSec -= (int)(sharedGFX->ParticlesPerSec * 0.5f);
960 sharedGFX->Speed = sharedGFX->Speed / CurrentPenalty;
961 sharedGFX->Life = sharedGFX->Life * CurrentPenalty;
962 sharedGFX->MagnetFactor = sharedGFX->MagnetFactor / (CurrentPenalty * CurrentPenalty);
963 }
964 }
965 sharedProjectile->ObjectStatus = ObjectStatus;
966 sharedProjectile->SpeedStart = sharedProjectile->SpeedEnd = sharedProjectile->SpeedStart / CurrentPenalty;
967 sharedProjectile->Age = sharedProjectile->Lifetime = sharedProjectile->Age * CurrentPenalty;
968 sharedProjectile->Damage /= CurrentPenalty;
969
970 if (SFX != eGameSFX::none)
971 PlayGameSFX(SFX, 1.0f, sharedProjectile->Location);
972 }
973 SwarmNum--;
974 }
975
976 if (WeaponTurret) {
977 sVECTOR3D NeedAngle(TargetVertChunkNeedAngle,TargetHorizChunkNeedAngle,0);
978 sVECTOR3D tmpTargetLocation{};
979 if (FindTargetLocationWithPrediction(ObjectStatus, Location + FireLocation, InternalType, tmpTargetLocation))
980 GetTurretOnTargetOrientation(Location + FireLocation, Rotation, CurrentRotationMat,
981 tmpTargetLocation, NeedAngle);
982 TargetHorizChunkNeedAngle = NeedAngle.y;
983 TargetVertChunkNeedAngle = NeedAngle.x;
984
985 if (TargetHorizChunkNum != -1)
986 if (TargetHorizChunkNeedAngle != TargetHorizChunkCurrentAngle) {
987 if (fabsf(TargetHorizChunkNeedAngle - TargetHorizChunkCurrentAngle) > 180.0f) {
988 if (TargetHorizChunkCurrentAngle - TargetHorizChunkNeedAngle > 180.0f)
989 TargetHorizChunkCurrentAngle -= 360.0f;
990 if (TargetHorizChunkNeedAngle - TargetHorizChunkCurrentAngle > 180.0f)
991 TargetHorizChunkCurrentAngle += 360.0f;
992 }
993 float NeedRotate = TargetHorizChunkCurrentAngle;
994
995 if (TargetHorizChunkNeedAngle > TargetHorizChunkCurrentAngle) {
996 NeedRotate += 80.0f * TimeDelta / GameEnemyTargetingSpeedPenalty;
997 if (NeedRotate > TargetHorizChunkNeedAngle)
998 NeedRotate = TargetHorizChunkNeedAngle;
999 } else {
1000 NeedRotate -= 80.0f * TimeDelta / GameEnemyTargetingSpeedPenalty;
1001 if (NeedRotate < TargetHorizChunkNeedAngle)
1002 NeedRotate = TargetHorizChunkNeedAngle;
1003 }
1004
1005 TargetHorizChunkCurrentAngle = NeedRotate;
1006
1007 for (auto &tmpChunk : Chunks) {
1008 sVECTOR3D tmp = tmpChunk.Location - Chunks[TargetHorizChunkNum].Location;
1009
1010 vw_RotatePointInv(tmp, tmpChunk.Rotation ^ (-1.0f));
1011
1012 tmpChunk.Rotation.y = -NeedRotate;
1013
1014 vw_RotatePoint(tmp, tmpChunk.Rotation);
1015
1016 tmpChunk.Location = tmp + Chunks[TargetHorizChunkNum].Location;
1017 }
1018 }
1019
1020 if (TargetVertChunkNum != -1)
1021 if (TargetVertChunkNeedAngle != TargetVertChunkCurrentAngle) {
1022 float NeedRotate = TargetVertChunkCurrentAngle;
1023 if (TargetVertChunkNeedAngle > TargetVertChunkCurrentAngle) {
1024 NeedRotate += 80.0f * TimeDelta / GameEnemyTargetingSpeedPenalty;
1025 if (NeedRotate > TargetVertChunkNeedAngle)
1026 NeedRotate = TargetVertChunkNeedAngle;
1027 if (NeedRotate > TargetVertChunkMaxAngle)
1028 NeedRotate = TargetVertChunkMaxAngle;
1029 } else {
1030 NeedRotate -= 80.0f * TimeDelta / GameEnemyTargetingSpeedPenalty;
1031 if (NeedRotate < TargetVertChunkNeedAngle)
1032 NeedRotate = TargetVertChunkNeedAngle;
1033 if (NeedRotate < TargetVertChunkMinAngle)
1034 NeedRotate = TargetVertChunkMinAngle;
1035 }
1036
1037 TargetVertChunkCurrentAngle = NeedRotate;
1038
1039 sVECTOR3D tmp = Chunks[TargetVertChunkNum].Location - Chunks[TargetVertChunkNum].Location; // FIXME (0,0,0)???
1040
1041 vw_RotatePointInv(tmp, Chunks[TargetVertChunkNum].Rotation ^ (-1.0f));
1042
1043 Chunks[TargetVertChunkNum].Rotation.x = -NeedRotate;
1044
1045 vw_RotatePoint(tmp, Chunks[TargetVertChunkNum].Rotation);
1046
1047 Chunks[TargetVertChunkNum].Location = tmp + Chunks[TargetVertChunkNum].Location;
1048 }
1049
1050 sVECTOR3D RotationBase = Rotation;
1051 sVECTOR3D BaseBoundTMP = BaseBound;
1052 vw_RotatePoint(BaseBoundTMP, RotationBase);
1053
1054 sVECTOR3D RotationMiddle = Rotation;
1055 sVECTOR3D MiddleBoundTMP = MiddleBound;
1056 if (TargetHorizChunkNum != -1)
1057 RotationMiddle = Chunks[TargetHorizChunkNum].Rotation + Rotation;
1058 vw_RotatePoint(MiddleBoundTMP, RotationMiddle);
1059
1060 sVECTOR3D RotationWeapon = Rotation;
1061 if (TargetVertChunkNum != -1)
1062 RotationWeapon = Chunks[TargetVertChunkNum].Rotation + Rotation;
1063
1064 sVECTOR3D WeaponBoundTMP = WeaponBound;
1065 vw_RotatePoint(WeaponBoundTMP, RotationWeapon);
1066
1067 FireLocation = BaseBoundTMP + MiddleBoundTMP + WeaponBoundTMP;
1068
1069 if ((TargetHorizChunkNum == -1) && (TargetVertChunkNum == -1))
1070 RotationWeapon = sVECTOR3D{TargetVertChunkNeedAngle,
1071 TargetHorizChunkNeedAngle,
1072 0.0f} +
1073 Rotation;
1074
1075 Orientation = sVECTOR3D{0.0f, 0.0f, 1.0f};
1076 vw_RotatePoint(Orientation, RotationWeapon);
1077 }
1078
1079 return true;
1080 }
1081
1082 /*
1083 * Set rotation.
1084 */
SetRotation(const sVECTOR3D & NewRotation)1085 void cWeapon::SetRotation(const sVECTOR3D &NewRotation)
1086 {
1087 cObject3D::SetRotation(NewRotation);
1088
1089 if (!WeaponTurret) {
1090 vw_Matrix33CalcPoint(FireLocation, OldInvRotationMat);
1091 vw_Matrix33CalcPoint(FireLocation, CurrentRotationMat);
1092
1093 if (auto sharedFire = Fire.lock()) {
1094 sharedFire->MoveSystem(Location + FireLocation);
1095 sharedFire->SetStartLocation(Location + FireLocation);
1096 sharedFire->RotateSystemByAngle(Rotation);
1097 }
1098 } else {
1099 sVECTOR3D RotationBase = Rotation;
1100 sVECTOR3D BaseBoundTMP = BaseBound;
1101 vw_RotatePoint(BaseBoundTMP, RotationBase);
1102
1103 sVECTOR3D RotationMiddle = Rotation;
1104 sVECTOR3D MiddleBoundTMP = MiddleBound;
1105 if (TargetHorizChunkNum != -1)
1106 RotationMiddle = Chunks[TargetHorizChunkNum].Rotation + Rotation;
1107 vw_RotatePoint(MiddleBoundTMP, RotationMiddle);
1108
1109 sVECTOR3D RotationWeapon = Rotation;
1110 if (TargetVertChunkNum != -1)
1111 RotationWeapon = Chunks[TargetVertChunkNum].Rotation + Rotation;
1112
1113 sVECTOR3D WeaponBoundTMP = WeaponBound;
1114 vw_RotatePoint(WeaponBoundTMP, RotationWeapon);
1115
1116 FireLocation = BaseBoundTMP + MiddleBoundTMP + WeaponBoundTMP;
1117
1118 if ((TargetHorizChunkNum == -1) && (TargetVertChunkNum == -1))
1119 RotationWeapon = sVECTOR3D{TargetVertChunkNeedAngle,
1120 TargetHorizChunkNeedAngle,
1121 0.0f} +
1122 Rotation;
1123
1124 Orientation = sVECTOR3D{0.0f, 0.0f, 1.0f};
1125 vw_RotatePoint(Orientation, RotationWeapon);
1126 }
1127
1128 if (auto sharedDestroyedFire = DestroyedFire.lock()) {
1129 vw_Matrix33CalcPoint(DestroyedFireLocation, OldInvRotationMat);
1130 vw_Matrix33CalcPoint(DestroyedFireLocation, CurrentRotationMat);
1131 sharedDestroyedFire->MoveSystem(Location + DestroyedFireLocation);
1132 sharedDestroyedFire->SetStartLocation(Location + DestroyedFireLocation);
1133 sharedDestroyedFire->RotateSystemByAngle(Rotation);
1134 }
1135 if (auto sharedDestroyedSmoke = DestroyedSmoke.lock()) {
1136 sharedDestroyedSmoke->MoveSystemLocation(Location + DestroyedFireLocation);
1137 sharedDestroyedSmoke->RotateSystemByAngle(Rotation);
1138 }
1139 if (auto sharedLaserMaser = LaserMaser.lock()) {
1140 vw_Matrix33CalcPoint(sharedLaserMaser->ProjectileCenter, OldInvRotationMat);
1141 vw_Matrix33CalcPoint(sharedLaserMaser->ProjectileCenter, CurrentRotationMat);
1142 sharedLaserMaser->SetLocation(Location + FireLocation + sharedLaserMaser->ProjectileCenter);
1143 sharedLaserMaser->SetRotation(NewRotation);
1144 }
1145 }
1146
1147 /*
1148 * Set location.
1149 */
SetLocation(const sVECTOR3D & NewLocation)1150 void cWeapon::SetLocation(const sVECTOR3D &NewLocation)
1151 {
1152 cObject3D::SetLocation(NewLocation);
1153
1154 if (auto sharedFire = Fire.lock()) {
1155 sharedFire->MoveSystem(NewLocation + FireLocation);
1156 sharedFire->SetStartLocation(NewLocation + FireLocation);
1157 }
1158 if (auto sharedDestroyedFire = DestroyedFire.lock()) {
1159 sharedDestroyedFire->MoveSystem(NewLocation + DestroyedFireLocation);
1160 sharedDestroyedFire->SetStartLocation(NewLocation + DestroyedFireLocation);
1161 }
1162 if (auto sharedDestroyedSmoke = DestroyedSmoke.lock())
1163 sharedDestroyedSmoke->MoveSystemLocation(NewLocation + DestroyedFireLocation);
1164
1165 if (auto sharedLaserMaser = LaserMaser.lock())
1166 sharedLaserMaser->SetLocation(Location + FireLocation + sharedLaserMaser->ProjectileCenter);
1167
1168 if (vw_IsSoundAvailable(LaserMaserSoundNum))
1169 vw_SetSoundLocation(LaserMaserSoundNum, Location.x, Location.y, Location.z);
1170 }
1171
1172 /*
1173 * Fire.
1174 */
WeaponFire(float Time)1175 bool cWeapon::WeaponFire(float Time)
1176 {
1177 if (InternalType == 0)
1178 return false;
1179
1180 float CurrentPenalty{1.0f};
1181 if (ObjectStatus == eObjectStatus::Enemy)
1182 CurrentPenalty = static_cast<float>(GameEnemyWeaponPenalty);
1183
1184 if (InternalType == 203) // flares
1185 CurrentPenalty = 1.0f;
1186
1187 if (Time < LastFireTime + NextFireTime * CurrentPenalty)
1188 return false;
1189 LastFireTime = Time;
1190
1191 if ((InternalType >= 1) &&
1192 (InternalType <= 99)) {
1193 bool Misfire{false};
1194 if ((ArmorCurrentStatus < ArmorInitialStatus) &&
1195 (ArmorCurrentStatus / ArmorInitialStatus > vw_fRand()))
1196 Misfire = true;
1197
1198 if ((ArmorCurrentStatus <= 0.0f) ||
1199 (Ammo == 0) ||
1200 Misfire) {
1201 float fVol = 1.0f;
1202
1203 switch (InternalType) {
1204 case 1: // Kinetic1
1205 case 2: // Kinetic2
1206 case 3: // Kinetic3
1207 case 4: // Kinetic4
1208 PlayGameSFX(eGameSFX::WeaponMalfunction_Kinetic, fVol, Location);
1209 break;
1210
1211 case 5: // Ion1
1212 case 6: // Ion2
1213 case 7: // Ion3
1214 case 8: // Plasma1
1215 case 9: // Plasma2
1216 case 10: // Plasma3
1217 PlayGameSFX(eGameSFX::WeaponMalfunction_Particle, fVol, Location);
1218 break;
1219
1220 case 11: // Maser1
1221 case 12: // Maser2
1222 case 14: // Laser
1223 PlayGameSFX(eGameSFX::WeaponMalfunction_Beam, fVol, Location);
1224 break;
1225
1226 case 13: // Antimatter
1227
1228 case 15: // Gauss
1229 PlayGameSFX(eGameSFX::WeaponMalfunction_Energy, fVol, Location);
1230 break;
1231
1232 case 16: // missiles
1233 case 17: // swarm
1234 case 18: // torpedo
1235 case 19: // bomb
1236 PlayGameSFX(eGameSFX::WeaponMalfunction_Launcher, fVol, Location);
1237 break;
1238 }
1239
1240 return false;
1241 }
1242
1243 if (ObjectStatus == eObjectStatus::Player) {
1244 if (CurrentEnergyAccumulated < EnergyUse)
1245 return false;
1246 else
1247 CurrentEnergyAccumulated = 0.0f;
1248 }
1249
1250 if (!GameUnlimitedAmmo)
1251 Ammo -= 1;
1252
1253 if (InternalType < 16) {
1254 if (auto sharedFire = Fire.lock())
1255 sharedFire->IsSuppressed = false;
1256 }
1257
1258 }
1259
1260 sVECTOR3D RotationWeapon = Rotation;
1261 if (WeaponTurret) {
1262 sVECTOR3D RotationBase = Rotation;
1263 sVECTOR3D BaseBoundTMP = BaseBound;
1264 vw_RotatePoint(BaseBoundTMP, RotationBase);
1265
1266 sVECTOR3D RotationMiddle = Rotation;
1267 sVECTOR3D MiddleBoundTMP = MiddleBound;
1268 if (TargetHorizChunkNum != -1)
1269 RotationMiddle = Chunks[TargetHorizChunkNum].Rotation + Rotation;
1270 vw_RotatePoint(MiddleBoundTMP, RotationMiddle);
1271
1272 if (TargetVertChunkNum != -1)
1273 RotationWeapon = Chunks[TargetVertChunkNum].Rotation + Rotation;
1274
1275 sVECTOR3D WeaponBoundTMP = WeaponBound;
1276 vw_RotatePoint(WeaponBoundTMP, RotationWeapon);
1277
1278 FireLocation = BaseBoundTMP + MiddleBoundTMP + WeaponBoundTMP;
1279
1280 if (TargetHorizChunkNum == -1 && TargetVertChunkNum == -1) {
1281 RotationWeapon = sVECTOR3D{TargetVertChunkNeedAngle,
1282 TargetHorizChunkNeedAngle,
1283 0.0f} +
1284 Rotation;
1285 }
1286 }
1287
1288 std::weak_ptr<cProjectile> tmpProjectile = CreateProjectile(InternalType);
1289 if (auto sharedProjectile = tmpProjectile.lock()) {
1290 if (sharedProjectile->ProjectileType == 2) {
1291 if (!LaserMaser.expired())
1292 ReleaseProjectile(LaserMaser);
1293
1294 LaserMaser = tmpProjectile;
1295 vw_Matrix33CalcPoint(sharedProjectile->ProjectileCenter, CurrentRotationMat);
1296 sharedProjectile->SetLocation(Location + FireLocation + sharedProjectile->ProjectileCenter);
1297 } else {
1298 if (sharedProjectile->ProjectileType == 0) {
1299 sVECTOR3D AddPos(0.0f, 0.0f, 4.0f);
1300 if (WeaponTurret)
1301 AddPos = sVECTOR3D{0.0f, 0.0f, 2.0f};
1302
1303 vw_RotatePoint(AddPos, RotationWeapon);
1304 sharedProjectile->SetLocation(Location+FireLocation + AddPos);
1305 } else
1306 sharedProjectile->SetLocation(Location+FireLocation);
1307 }
1308
1309 if ((sharedProjectile->ProjectileType == 3) ||
1310 (sharedProjectile->ProjectileType == 4)) {
1311 sharedProjectile->SetRotation(RotationWeapon);
1312 for (auto &tmpGFX : sharedProjectile->GraphicFX) {
1313 if (auto sharedGFX = tmpGFX.lock())
1314 sharedGFX->Direction = Orientation;
1315 }
1316 sharedProjectile->ObjectStatus = ObjectStatus;
1317 sharedProjectile->SpeedStart = sharedProjectile->SpeedEnd = sharedProjectile->SpeedStart / CurrentPenalty;
1318 sharedProjectile->Age = sharedProjectile->Lifetime = sharedProjectile->Age;
1319 sharedProjectile->Damage /= CurrentPenalty;
1320
1321 // FIXME should be revised, we use -3 in order to 'convert' to proper projectile type
1322 sharedProjectile->ProjectileType = sharedProjectile->ProjectileType - 3;
1323 } else {
1324 sharedProjectile->SetRotation(RotationWeapon);
1325 for (auto &tmpGFX : sharedProjectile->GraphicFX) {
1326 if (auto sharedGFX = tmpGFX.lock()) {
1327 sharedGFX->Direction = Orientation;
1328 // учитываем пенальти для визуальных эффектов
1329 sharedGFX->ParticlesPerSec = (int)(sharedGFX->ParticlesPerSec / CurrentPenalty);
1330
1331 sharedGFX->Speed = sharedGFX->Speed / CurrentPenalty;
1332 sharedGFX->Life = sharedGFX->Life * CurrentPenalty;
1333 sharedGFX->MagnetFactor = sharedGFX->MagnetFactor / (CurrentPenalty * CurrentPenalty);
1334 }
1335 }
1336 sharedProjectile->ObjectStatus = ObjectStatus;
1337 sharedProjectile->SpeedStart = sharedProjectile->SpeedEnd = sharedProjectile->SpeedStart / CurrentPenalty;
1338 sharedProjectile->Age = sharedProjectile->Lifetime = sharedProjectile->Age * CurrentPenalty;
1339 sharedProjectile->Damage /= CurrentPenalty;
1340 }
1341 }
1342
1343 if (SFX != eGameSFX::none) {
1344 float fVol = 1.0f;
1345 LaserMaserSoundNum = PlayGameSFX(SFX, fVol, Location + FireLocation);
1346 if (LaserMaser.expired())
1347 LaserMaserSoundNum = 0;
1348 }
1349
1350 if (InternalType == 17) // 9 more swarm missiles
1351 SwarmNum = 9;
1352
1353 if (InternalType == 203) // 4 more flares
1354 SwarmNum = 4;
1355
1356 return true;
1357 }
1358
1359 } // astromenace namespace
1360 } // viewizard namespace
1361