Rise
The Vieneo Province
weapon.cpp
Go to the documentation of this file.
1 #include "weapon.h"
2 #include "Viewscreen.h"
3 #include "../MathUtilities.h"
4 
6 {
7  viewscreen = ptrGame;
8  logger = ptrGame->logger;
9 
10  s = 0;
11  r = 0;
12  closest = -1;
13 
14  for (t = 0; t < MAX_WEAPONS; t++)
15  {
16  weaponarray[t].active = false;
18  }
19 }
20 
22 {
23  if (rand() < 4096 || dockprogress < 1.0f) // 12% chance
24  {
25  logger->Log("Weapons calling Undock...");
26  viewscreen->Undock();
27  viewscreen->rcsThrustOutputY -= 0.02f;
28  }
29  bool senddamage = false;
30  float f_temp = RandomFloat();
31  if (f_temp < ourcockpit.power)
32  {
33  ourcockpit.power = f_temp;
34  if (ourcockpit.power <= 0.5f)
35  {
38  }
39  }
40  if (rand() < 4096) // 12% chance
41  {
42  if (ourcockpit.vdat.thrustaug > 0)
43  ourcockpit.vdat.thrustaug -= (char)(RandomFloat()*(float)(ourcockpit.vdat.thrustaug + 1.0f));
44  senddamage = true;
45  if (!playerships[s].docked && playerships[s].reference != REF_ONGROUND)
46  {
47  playerships[s].roll += RandomFloat()*1.0f - 0.5f;
48  playerships[s].yaw += RandomFloat()*1.0f - 0.5f;
49  playerships[s].pitch += RandomFloat()*1.0f - 0.5f;
50  }
51  }
52  if (rand() < 4096) // 12% chance
53  {
54  if (ourcockpit.vdat.yawdamper > 0)
55  ourcockpit.vdat.yawdamper -= (char)(RandomFloat()*(float)(ourcockpit.vdat.yawdamper + 1.0f));
56  senddamage = true;
57  }
58  if (rand() < 2048) // 6% chance on right engine
59  {
60  if (ourcockpit.vdat.rightengine > 0)
61  ourcockpit.vdat.rightengine -= (char)(RandomFloat()*(float)(ourcockpit.vdat.rightengine + 1.0f));
62  senddamage = true;
63  }
64  if (rand() < 2048) // 6% chance on left engine
65  {
66  if (ourcockpit.vdat.leftengine > 0)
67  ourcockpit.vdat.leftengine -= (char)(RandomFloat()*(float)(ourcockpit.vdat.leftengine + 1.0f));
68  senddamage = true;
69  }
70  if (rand() < 2048) // 6% chance on tail engine
71  {
72  if (ourcockpit.vdat.clengine > 0)
73  ourcockpit.vdat.clengine -= (char)(RandomFloat()*(float)(ourcockpit.vdat.clengine + 1.0f));
74  senddamage = true;
75  }
76  if (senddamage)
77  ourcockpit.vdatChanged = true;
78 }
79 
80 void weapon::Update(float fElapsedTime)
81 {
82  viewscreen->logger->AddToCallStack("weapon::Update");
83 
84  HRESULT hr;
85 
86  // Weapons handling
87  float furthest = farplaneC;
88  closest = -1;
89  for (t = 0; t < MAX_WEAPONS; t++)
90  {
91  if (!weaponarray[t].active)
92  continue;
93 
94  // smoothing for the velocity
95  D3DXVECTOR3 cross = weaponarray[t].veliter*fElapsedTime;
96  if (D3DXVec3Length(&cross) > D3DXVec3Length(&weaponarray[t].velleft))
97  cross = weaponarray[t].velleft;
98  weaponarray[t].velleft -= cross;
99  weaponarray[t].velocity += cross;
100 
101  // smoothing for the position
102  cross = weaponarray[t].positer*fElapsedTime;
103  if (D3DXVec3Length(&cross) > D3DXVec3Length(&weaponarray[t].posleft))
104  cross = weaponarray[t].posleft;
105  weaponarray[t].posleft -= cross;
106  weaponarray[t].precisionx += static_cast<double>(cross.x);
107  weaponarray[t].precisiony += static_cast<double>(cross.y);
108  weaponarray[t].precisionz += static_cast<double>(cross.z);
109 
110  double proposedx = weaponarray[t].precisionx + static_cast<double>(weaponarray[t].velocity.x)*static_cast<double>(fElapsedTime);
111  double proposedy = weaponarray[t].precisiony + static_cast<double>(weaponarray[t].velocity.y)*static_cast<double>(fElapsedTime);
112  double proposedz = weaponarray[t].precisionz + static_cast<double>(weaponarray[t].velocity.z)*static_cast<double>(fElapsedTime);
113 
114  D3DXVECTOR3 proposed;
115  proposed.x = static_cast<float>(proposedx);
116  proposed.y = static_cast<float>(proposedy);
117  proposed.z = static_cast<float>(proposedz);
118 
119 #pragma region Collision Detection (Weapons)
120 
121  // Check against largest things first
122  D3DXVECTOR3 location;
123 
124  // Check against docks
125  if (!weaponarray[t].exploded && weaponarray[t].reference >= REF_DOCKCPOC)
126  {
127  viewscreen->logger->AddToCallStack("weapon::Update DOCK");
128 
129  for (s = 0; s < maxdockC; s++)
130  {
131  D3DXVECTOR3 dockoffset = proposed;
132  if (D3DXVec3Length(&dockoffset) <= allobjects[s].bound)
133  {
134  for (r = 0; r < allobjects[s].components; r++)
135  {
136  // Relative XYZ position
137  // Extensions
138  D3DXVECTOR3 result;
139  D3DXVec3Scale(&result, &allobjects[s].componentarray[r].extendby, allobjects[s].componentarray[r].extended);
140  D3DXVec3Add(&result, &allobjects[s].componentarray[r].nominalxyz, &result);
141 
142  location = -result;//*allobjects[s].scale;
143 
144  D3DXVec3Subtract(&cross, &location, &dockoffset);
145 
146  if (D3DXVec3Length(&cross) <= allobjects[s].componentarray[r].boundsphere)
147  {
148  weaponarray[t].target = 0; // did not hit a vessel
150  ExplodeWeapon(t, false, "Dock");
151 
152 #ifdef testingC
153  allobjects[s].componentarray[r].nominalxyz *= 1000.0f;
154 #endif
155 
156  proposedx = weaponarray[t].precisionx;
157  proposedy = weaponarray[t].precisiony;
158  proposedz = weaponarray[t].precisionz;
159 
160  s = maxdockC; // object loop
161  break; // component loop
162  }
163  }
164  } // not within main bounding sphere
165  } // object loop
166  }
167 
168  // Check against ships
169  if (!weaponarray[t].exploded)
170  {
171  viewscreen->logger->AddToCallStack("weapon::Update SHIP");
172 
173  for (s = 0; s < MAX_SCAN; s++) // including us
174  {
175  if (!playerships[s].active || !playerships[s].visible || playerships[s].reference == REF_INANOTHER)
176  continue;
177 
178  // Not the one who launched it at least for a second for it to clear
179  if (playerships[s].vehicleId == weaponarray[t].origin && weaponarray[t].elapsed < 1.0f)
180  continue;
181 
182  D3DXVECTOR3 result;
183  if (weaponarray[t].reference < REF_INANOTHER)
184  result = playerships[s].position - proposed;
185  else if (weaponarray[t].reference == playerships[s].reference)
186  result = playerships[s].dockoffset - proposed;
187  else
188  result.x = result.y = result.z = 999.0f; // no chance
189 
190  if (D3DXVec3Length(&result) >= playerships[s].bound)
191  continue;
192 
193  for (r = 0; r < playerships[s].components; r++)
194  {
195  // types to skip: no bounding sphere, interior of cargo bay
196  if (!playerships[s].componentarray[r].visible ||
197  playerships[s].componentarray[r].type == 53 ||
198  playerships[s].componentarray[r].type == 54)
199  continue;
200 
201  location = D3DXVECTOR3(0, 0, 0);
202  D3DXVec3TransformCoord(&location, &location, &playerships[s].componentarray[r].matWorld);
203 
204  if (weaponarray[t].reference < REF_INANOTHER)
205  cross = -location + playerships[0].position - proposed;
206  else
207  cross = -location + playerships[0].dockoffset - proposed;
208 
209  if (D3DXVec3Length(&cross) >= playerships[s].componentarray[r].boundsphere)
210  continue;
211 
213  if (weaponarray[t].reference >= REF_INANOTHER)
215  else
217 
218  char msg[99];
219  if (playerships[s].vehicleId == weaponarray[t].origin)
220  {
221  sprintf_s(msg, 99, "Vehicle Elapsed %i", s);
222  ExplodeWeapon(t, s == 0, msg);
223  }
224  else
225  {
226  sprintf_s(msg, 99, "Vehicle NotOrigin %i", s);
227  ExplodeWeapon(t, s == 0, msg);
228  }
229 
230  proposedx = weaponarray[t].precisionx;
231  proposedy = weaponarray[t].precisiony;
232  proposedz = weaponarray[t].precisionz;
233  proposed = D3DXVECTOR3(static_cast<float>(proposedx), static_cast<float>(proposedy), static_cast<float>(proposedz));
234  break;
235  }
236 
237  // It hit one of these objects!
238  if (weaponarray[t].exploded)
239  {
240  if (s == 0) // it was us!
242  s = MAX_SCAN; // break out of loop
243  }
244  } // object loop
245  }
246 
247  // Check collision with other weapons
248  if (!weaponarray[t].exploded)
249  {
250  viewscreen->logger->AddToCallStack("weapon::Update WEAP");
251 
252  for (s = 0; s < MAX_WEAPONS; s++)
253  {
254  if (s != t)
255  {
256  if (weaponarray[s].active && !weaponarray[s].exploded &&
257  (weaponarray[t].reference < REF_INANOTHER || weaponarray[t].reference == weaponarray[s].reference)
258  ) // can't lock the one we are looking at a second time
259  {
260  D3DXVECTOR3 result;
261  result.x = (float)weaponarray[s].precisionx;
262  result.y = (float)weaponarray[s].precisiony;
263  result.z = (float)weaponarray[s].precisionz;
264  D3DXVec3Subtract(&result, &result, &proposed);
265  if (D3DXVec3Length(&result) < 0.001f) // 1 meter
266  {
269 
270  ExplodeWeapon(t, false, "Weapon");
271  ExplodeWeapon(s, false, "Weapon");
272 
273  proposedx = weaponarray[t].precisionx;
274  proposedy = weaponarray[t].precisiony;
275  proposedz = weaponarray[t].precisionz;
276  }
277  }
278  }
279  }
280  }
281 
282  // Check collision with ground or layout/depth maps!
283  if (!weaponarray[t].exploded && !g_bAboveClouds) // only below when valid grid
284  {
285  viewscreen->logger->AddToCallStack("weapon::Update GRND/CITY");
286 
287  char wcube = viewscreen->CalculateCube(proposed);
288  VECTOR2SHORT wtcp = viewscreen->CalculateCGC(proposed, wcube);
289  wtcp.u = 31 - (viewscreen->ptrGrid->tcp.u - wtcp.u);
290  wtcp.v = 31 - (viewscreen->ptrGrid->tcp.v - wtcp.v);
291  if (wtcp.u >= 0 && wtcp.u <= 62 && wtcp.v >= 0 && wtcp.v <= 62) // within visible grid
292  {
293  float weaponAGL = viewscreen->CalculateAGL(wtcp.u, wtcp.v, proposed, false);
294 
295  float buildingAGL, buildingBGL;
296  // FIND CITY AGL ADJUSTMENT
297  VECTOR2SHORT newdepthpos; // NOLINT
298  float f_tempu, f_tempv, f_tempd;
299  D3DXVECTOR3 result = -proposed;
300  D3DXVec3Normalize(&result, &result);
301 
302  if (gridarray[wtcp.u][wtcp.v].type > PlotType::NotZoned)
303  {
304  const short buildZoneOrdinal = gridarray[wtcp.u][wtcp.v].buildzoneOrdinal;
305  if (buildZoneOrdinal != -1)
306  {
307  if (D3DXIntersectTri(&gridarray[wtcp.u+1][wtcp.v].position, &gridarray[wtcp.u][wtcp.v].position, &gridarray[wtcp.u+1][wtcp.v+1].position, &centerC, &result, &f_tempu, &f_tempv, &f_tempd))
308  {
309  newdepthpos.u = static_cast<short>((1.0f - f_tempu) * static_cast<float>(depthFloorResolutionC)); // V2-V1
310  newdepthpos.v = static_cast<short>(f_tempv * static_cast<float>(depthFloorResolutionC)); // V3-V1
311  }
312  else if (D3DXIntersectTri(&gridarray[wtcp.u][wtcp.v+1].position, &gridarray[wtcp.u+1][wtcp.v+1].position, &gridarray[wtcp.u][wtcp.v].position, &centerC, &result, &f_tempu, &f_tempv, &f_tempd))
313  {
314  newdepthpos.u = static_cast<short>(f_tempu * static_cast<float>(depthFloorResolutionC)); // V2-V1
315  newdepthpos.v = static_cast<short>((1.0f - f_tempv) * static_cast<float>(depthFloorResolutionC)); // V3-V1
316  }
317  else
318  newdepthpos.u = newdepthpos.v = -2;
319  }
320  else
321  newdepthpos.u = newdepthpos.v = -3;
322  }
323  else
324  newdepthpos.u = newdepthpos.v = -1;
325 
326  if (weaponarray[t].olddepthpos.u != newdepthpos.u || weaponarray[t].olddepthpos.v != newdepthpos.v)
327  {
329  buildingAGL = viewscreen->CheckDepthMap(newdepthpos, wtcp.u, wtcp.v);
330  buildingBGL = viewscreen->CheckFloorMap(newdepthpos, wtcp.u, wtcp.v);
331 
332  }
333  else
334  {
335  buildingAGL = 0.0f;
336  buildingBGL = 0.0f;
337  }
338 
339 
340  if (wtcp.u > 15 && wtcp.u < 48 && wtcp.v>15 && wtcp.v < 48) // in patched data
341  {
342  // wepchecklayout=CheckLayoutMap(newdepthpos, wtcp.u, wtcp.v);
343  if (!weaponarray[t].exploded)// && wepchecklayout)
344  {
345  if (gridarray[wtcp.u][wtcp.v].IsUserColony())
346  {
347  const short buildZoneOrdinal = gridarray[wtcp.u][wtcp.v].buildzoneOrdinal;
348 
349  if (buildZoneOrdinal != -1)
350  {
351  D3DXVECTOR3 oldpos, result1, result2, result3;
352  oldpos.x = -static_cast<float>(weaponarray[t].precisionx) - buildzone[buildZoneOrdinal].terpos.x;
353  oldpos.y = -static_cast<float>(weaponarray[t].precisiony) - buildzone[buildZoneOrdinal].terpos.y;
354  oldpos.z = -static_cast<float>(weaponarray[t].precisionz) - buildzone[buildZoneOrdinal].terpos.z;
355  D3DXVECTOR3 newpos = -weaponarray[t].velocity;
356  D3DXVec3Normalize(&newpos, &newpos);
357  D3DVERTEX* wepverts;
358  V(buildzone[buildZoneOrdinal].VB->Lock(0, 0, reinterpret_cast<void**>(&wepverts), D3DLOCK_READONLY));
359 
360  bool term = false;
361  for (s = 0; s < buildzone[buildZoneOrdinal].components; s++)
362  {
363  for (unsigned short r = 0; r < buildzone[buildZoneOrdinal].componentarray[s].primitives; r++)
364  {
365  if (buildzone[buildZoneOrdinal].componentarray[s].type != 8) // not field crops
366  {
367  long offset = r * 3 + buildzone[buildZoneOrdinal].componentarray[s].startvertex;
368  result1.x = (*(wepverts + offset)).x;
369  result1.y = (*(wepverts + offset)).y;
370  result1.z = (*(wepverts + offset)).z;
371  offset++;
372  result2.x = (*(wepverts + offset)).x;
373  result2.y = (*(wepverts + offset)).y;
374  result2.z = (*(wepverts + offset)).z;
375  offset++;
376  result3.x = (*(wepverts + offset)).x;
377  result3.y = (*(wepverts + offset)).y;
378  result3.z = (*(wepverts + offset)).z;
379 
380  float pu, pv, dist;
381  // this is testing for polygon collision with buildings not the ground
382  if (D3DXIntersectTri(&result1, &result2, &result3, &oldpos, &newpos, &pu, &pv, &dist))
383  {
384  if (dist <= (D3DXVec3Length(&weaponarray[t].velocity)*fElapsedTime))
385  {
386  char msg[99];
387  sprintf_s(msg, sizeof(msg), "Weapon %i hit polygon %i of module %i at %f %f (dist %f)", t, r, s, pu, pv, dist);
388  logger->Log(msg);
389  weaponarray[t].velocity = centerC;//playerships[ourshipC].barycentric;
390  weaponarray[t].target = 0; // did not hit a vessel
391  ExplodeWeapon(t, false, "Colony");
392  proposedx = weaponarray[t].precisionx;
393  proposedy = weaponarray[t].precisiony;
394  proposedz = weaponarray[t].precisionz;
395  term = true;
396  r = (unsigned short)buildzone[buildZoneOrdinal].componentarray[s].primitives;
397  }
398  }
399  }
400  }
401  if (term)
402  s = buildzone[buildZoneOrdinal].components;
403  }
404  V(buildzone[buildZoneOrdinal].VB->Unlock());
405  }
406  }
407  }
408  }
409 
410 
411  weaponAGL = D3DXVec3Length(&proposed) - weaponAGL;
412  if (weaponAGL < buildingBGL && buildingBGL != 255.0f) // so we can go under overhangs without movement.cpp repoing us
413  buildingAGL = 0.0f;
414  if (weaponAGL <= buildingAGL)
415  {
416  weaponarray[t].velocity = centerC;//playerships[ourshipC].barycentric;
417  weaponarray[t].target = 0; // did not hit a vessel
418  ExplodeWeapon(t, false, "City");
419  proposedx = weaponarray[t].precisionx;
420  proposedy = weaponarray[t].precisiony;
421  proposedz = weaponarray[t].precisionz;
422  }
423  }
424  }
425 
426 #pragma endregion
427 
428  weaponarray[t].elapsed += fElapsedTime;
429 
430 
431  // Animation
432  viewscreen->logger->AddToCallStack("weapon::Update ANIM");
433  if (!weaponarray[t].exploded)
434  {
435  // Expiry check
436  if (weaponarray[t].elapsed > 30.0f) // 30 seconds
437  weaponarray[t].active = false;
438 
439  weaponarray[t].animate += fElapsedTime * 30.0f; // 30 fps
440  if (weaponarray[t].animate >= weaponanimateC)
441  weaponarray[t].animate = 0;
442  }
443  else
444  {
445  if (weaponarray[t].type == 1 || weaponarray[t].type == 2)
446  weaponarray[t].animate += fElapsedTime * 0.5f; // should take 2 seconds
447  else
448  weaponarray[t].animate += fElapsedTime * 0.5f / (powf(weaponarray[t].yieldKg, 0.333333f) / 8.291327f);
449  if (weaponarray[t].animate > 1.0f)
450  weaponarray[t].active = false;
451  }
452 
453 
454 #ifdef smoketestC
455  // equally space them
456  D3DXVECTOR3 offset;
457  if (weaponarray[t].reference < REF_INANOTHER)
458  offset = (weaponarray[t].velocity - weaponarray[t].barycentric)*fElapsedTime;
459  else
460  offset = weaponarray[t].dockingvel*fElapsedTime;
461  weaponarray[t].smokeprog += offset;
462 
463  for (s = 0; s < smoketrailC; s++)
464  {
465  if (weaponarray[t].smoketrail[s].animate < smoketrailC)
466  {
467  if (advanceframe)
468  weaponarray[t].smoketrail[s].animate++;
469  weaponarray[t].smoketrail[s].offset += offset;
470  }
471  }
472 
473  if (D3DXVec3Length(&weaponarray[t].smokeprog) > 0.02f) // 100 meters start a new one
474  {
475  weaponarray[t].smoketrail[weaponarray[t].smokestep].animate = 0; // start at beginning
476  if (rand() > 16384)
477  weaponarray[t].smoketrail[weaponarray[t].smokestep].animate++;
478  weaponarray[t].smoketrail[weaponarray[t].smokestep].offset = centerC; // start at current location
479  weaponarray[t].smokestep++;
480  if (weaponarray[t].smokestep >= smoketrailC)
481  weaponarray[t].smokestep = 0;
482  weaponarray[t].smokeprog = centerC;
483  }
484 #endif
485 
486 
487 
488  // Set at new location (may be old location)
489  weaponarray[t].precisionx = proposedx;
490  weaponarray[t].precisiony = proposedy;
491  weaponarray[t].precisionz = proposedz;
492  // weaponarray[t].position=proposed;
493 
494  viewscreen->logger->AddToCallStack("weapon::Update DIST");
495  if (weaponarray[t].exploded || weaponarray[t].type == 1 || weaponarray[t].type == 2) // everything except active longarm missiles
496  {
497  // Find closest active weapon for illumination
498  if (weaponarray[t].reference < REF_INANOTHER)
499  D3DXVec3Subtract(&cross, &proposed, &playerships[0].position);
500  else
501  D3DXVec3Subtract(&cross, &proposed, &playerships[0].dockoffset);
502 
503  float f_temp = D3DXVec3Length(&cross);
504  if (weaponarray[t].yieldKg > 0)
505  f_temp /= (weaponarray[t].yieldKg / 570.0f); // longarm is 1
506  if (f_temp < furthest)
507  {
508  furthest = f_temp;
509  closest = t;
510  }
511  else if (f_temp > 60.0f) // 60km
512  {
513  weaponarray[t].active = false;
514  }
515  }
516  }
517 
518  if (closest != -1) // Closest for illumination, only set for sinker and fuzer
519  {
520  viewscreen->logger->AddToCallStack("weapon::Update CLOSE1");
521 
522  D3DXVECTOR4 weapcol;
523  D3DXVECTOR4 weappos;
524 
525  if (weaponarray[closest].reference < REF_INANOTHER)
526  {
527  weappos.x = static_cast<float>(playerships[0].precisionx - weaponarray[closest].precisionx);
528  weappos.y = static_cast<float>(playerships[0].precisiony - weaponarray[closest].precisiony);
529  weappos.z = static_cast<float>(playerships[0].precisionz - weaponarray[closest].precisionz);
530  }
531  else
532  {
533  weappos.x = playerships[0].dockoffset.x - static_cast<float>(weaponarray[closest].precisionx);
534  weappos.y = playerships[0].dockoffset.y - static_cast<float>(weaponarray[closest].precisiony);
535  weappos.z = playerships[0].dockoffset.z - static_cast<float>(weaponarray[closest].precisionz);
536  }
537 
538  viewscreen->logger->AddToCallStack("weapon::Update CLOSE2");
539 
540  if (weaponarray[closest].exploded)
541  {
542  const float invAnimate = 1.0f - weaponarray[closest].animate;
543  if (weaponarray[closest].type == 1) // Fuzer
544  {
545  // greenish blue
546  weapcol.x = 0.25f * invAnimate;
547  weapcol.y = 0.5f * invAnimate;
548  weapcol.z = 0.5f * invAnimate;
549  }
550  else if (weaponarray[closest].type == 2) // sinker
551  {
552  // reddish
553  weapcol.x = 1.0f * invAnimate;
554  weapcol.y = 0.36f * invAnimate;
555  weapcol.z = 0.35f * invAnimate;
556  }
557  else
558  {
559  // orange
560  const float yieldMod = powf(weaponarray[closest].yieldKg, 0.333333f) / 8.291327f;
561  weapcol.x = 1.0f * yieldMod * invAnimate * invAnimate;
562  weapcol.y = 0.5f * yieldMod * invAnimate * invAnimate;
563  const float allowBlue = min(0.0f, yieldMod - 1.0f); // 0 at longarm strength
564  weapcol.z = allowBlue * yieldMod * invAnimate* invAnimate;
565  }
566  }
567  else
568  {
569  if (weaponarray[closest].type == 1) // Fuzer
570  {
571  weapcol.x = 0.25f; weapcol.y = 0.5f; weapcol.z = 0.5f;
572  }
573  else if (weaponarray[closest].type == 2) // sinker
574  {
575  weapcol.x = 1.0f; weapcol.y = 0.36f; weapcol.z = 0.35f;
576  }
577  else
578  {
579  weapcol.x = weapcol.y = weapcol.z = 0.0f;
580  }
581  }
582 
583  weapcol.w = 0.0f; // unused
584  V(viewscreen->gameclass->graphics->g_pEffect->SetVector("WeapCol", &weapcol));
585  weappos.w = 1.0f; // active
586  V(viewscreen->gameclass->graphics->g_pEffect->SetVector("WeapPos", &weappos));
587 
588  viewscreen->logger->AddToCallStack("weapon::Update CLOSE3");
589  }
590  else
591  {
592  D3DXVECTOR4 weappos = D3DXVECTOR4(0, 0, 0, 0); // inactive
593  V(viewscreen->gameclass->graphics->g_pEffect->SetVector("WeapPos", &weappos));
594  }
595 
596  viewscreen->logger->AddToCallStack("weapon::Update DONE");
597 }
598 
599 void weapon::FireWeapon(unsigned char bay) const
600 {
601  viewscreen->logger->AddToCallStack("weapon::FireWeapon");
602 
603  if (dead || ourcockpit.power < 0.25f || fuel <= 0.0f)
604  return;
605 
606  float compare = 0.0f;
607  if (ourcockpit.vdat.weapontype[bay] == 1)
608  compare = weaponfuzerreadyC;
609  else if (ourcockpit.vdat.weapontype[bay] == 2)
610  compare = weaponsinkerreadyC;
611  else if (ourcockpit.vdat.weapontype[bay] == 3)
612  compare = weaponlongarmreadyC;
613 
614  if (weapontimer[bay] != compare || ourcockpit.vdat.weapontype[bay] == 0)
615  return;
616 
617  weapontimer[bay] = 0.0f;
618 
619  SWeaponPacket outpacket;
620  D3DXVECTOR3 result;
621 
622  result.x = 0.0f; result.y = 0.0f; result.z = 0.5f; // 1-10km/s
623  D3DXVec3TransformNormal(&result, &result, &playerships[0].matrixWorld);
624  if (playerships[0].reference < REF_INANOTHER)
625  outpacket.velocity = playerships[0].velocity - playerships[0].barycentric + result;
626  else
627  outpacket.velocity = playerships[0].dockingvel + result;
628  outpacket.reference = playerships[0].reference;
629 
630  D3DXVec3TransformCoord(&outpacket.position, &ourcockpit.headlight, &playerships[0].matrixWorld); // Find straight ahead vector
631 
632  outpacket.type = ourcockpit.vdat.weapontype[bay]; // Weapon type
633  outpacket.status = 1; // New addition
634  outpacket.array = 255; // Not assigned yet
635  outpacket.origin = playerships[0].vehicleId;
636 
637  // @todo this may not even be needed now since we send the targetVehicleId when we change targets
638  if (viewscreen->gameclass->bus->targetC >= 0)
639  outpacket.target = playerships[viewscreen->scanslot[viewscreen->gameclass->bus->targetC]].vehicleId; // Target for tracking
640  else
641  outpacket.target = 0; // No target
642 
643  viewscreen->gameclass->networking->SendToServer(&outpacket, sizeof(SWeaponPacket), true);
644 }
645 
646 void weapon::ExplodeWeapon(short t, bool wasus, std::string reason)
647 {
648  viewscreen->logger->AddToCallStack("weapon::ExplodeWeapon");
649 
650  if (!weaponarray[t].exploded) // if it wasn't sent by peer.cpp
651  {
652  SWeaponPacket outpacket;
653  outpacket.status = 3; // Explode
654  outpacket.velocity = centerC;// weaponarray[t].velocity;
655  outpacket.reference = weaponarray[t].reference;
656  outpacket.position.x = static_cast<float>(weaponarray[t].precisionx);
657  outpacket.position.y = static_cast<float>(weaponarray[t].precisiony);
658  outpacket.position.z = static_cast<float>(weaponarray[t].precisionz);
659  outpacket.origin = weaponarray[t].origin;
660  outpacket.type = weaponarray[t].type;
661  outpacket.array = static_cast<unsigned char>(t);
662  outpacket.target = weaponarray[t].target;
663  outpacket.yieldKg = weaponarray[t].yieldKg;
664  viewscreen->gameclass->networking->SendToServer(&outpacket, sizeof SWeaponPacket, true);
665 
666  weaponarray[t].exploded = true;
667  weaponarray[t].animate = 0; // start over
668  weaponarray[t].elapsed = 0; // start over
669  weaponarray[t].tilt = RandomFloat() * D3DX_TAU;
672 
673  char msg[199];
674  sprintf_s(msg, sizeof(msg), "We sent that weapon %i exploded at %.3f %.3f %.3f (%s)", t, outpacket.position.x, outpacket.position.y, outpacket.position.z, reason.c_str());
675  logger->Log(msg);
676  }
677  else
678  {
679  char msg[199];
680  sprintf_s(msg, sizeof(msg), "Received that weapon %i exploded at %.3f %.3f %.3f (%s)", t, static_cast<float>(weaponarray[t].precisionx), static_cast<float>(weaponarray[t].precisiony), static_cast<float>(weaponarray[t].precisionz), reason.c_str());
681  logger->Log(msg);
682  }
683 
684  if (wasus)
685  {
686  if (weaponarray[t].type == 1)
688  else if (weaponarray[t].type == 2)
690  else if (weaponarray[t].type == 3)
692  return;
693  }
694 
695  D3DXVECTOR3 difference;
696  difference.x = static_cast<float>(weaponarray[t].precisionx);
697  difference.y = static_cast<float>(weaponarray[t].precisiony);
698  difference.z = static_cast<float>(weaponarray[t].precisionz);
699  difference += weaponarray[t].posleft; // visuals are smoothed but explosion needs to be where it actually hits
700  if (weaponarray[t].reference < REF_INANOTHER)
701  D3DXVec3Subtract(&difference, &difference, &playerships[0].position);
702  else
703  D3DXVec3Subtract(&difference, &difference, &playerships[0].dockoffset);
704  const float distance = D3DXVec3Length(&difference);
705 
706  char msg[99];
707  sprintf_s(msg, sizeof(msg), "Explosion! Distance: %.3f", distance);
708  logger->Log(msg);
709 
710  sprintf_s(msg, sizeof(msg), "--- speed of sound at %.3f km MSL: %.3f kms", f_MSL, viewscreen->ptrPropulsion->speedOfSoundKms);
711  logger->Log(msg);
712 
713 
714  // compare our motion to weapon location
715  difference += playerships[0].velocity - playerships[0].barycentric;
716  const float distNextSecond = D3DXVec3Length(&difference);
717  const float ourClosingRate = distance - distNextSecond;
718  const float closingRate = ourClosingRate + viewscreen->ptrPropulsion->speedOfSoundKms;
719  if (ourClosingRate >= 0.001f) // closing
720  {
721  sprintf_s(msg, sizeof(msg), "--- we are closing at %.3f kms", ourClosingRate);
722  logger->Log(msg);
723  }
724  else if (ourClosingRate <= 0.001f) // distancing
725  {
726  sprintf_s(msg, sizeof(msg), "--- we are distancing at %.3f kms", -ourClosingRate);
727  logger->Log(msg);
728  }
729 
730  const float delay = distance / closingRate; // 8km at .8 kms takes 10 seconds
731 
732 
733  // shock wave/overpressure wave
734  if (weaponarray[t].yieldKg > 0) // longarm or explosionOnly
735  {
736  // we USED to for longarm get 0.01 at 0km and nothing beyond 1km
737  // now we use 9.4 kg * 0.001 for kt is 0.00047 at 0 and 0.00235 (1/4) at 1km
738  // convert from kg to kt
739  const float psi = powf(weaponarray[t].yieldKg * 0.000001f * 1.66667f / max(powf(distance, 3.0f), 0.000000001f), 0.6f);
740 
741  if (psi >= 0.1f)
742  {
743  // so if it was facing the explosion // update doesn't appear to be orientation or coefficient related!
744  const float yield = psi * 0.00178136f; // 5 psi is lethal for them in a ship
745 
746  // e-10 was perfect 2.696208 * 0.000836 but car felt nothing
747  // c2a is 0.037093
748 
749  SShockWave shockWave;
750  shockWave.timetoshock = delay; // seconds at 1km speed of sound
751  shockWave.shockspeed = 4.0f; // 0.25 sec up and then down
752  shockWave.shockramp = 0.0f; // reset
753  D3DXVec3Normalize(&shockWave.shockmag, &difference);
754  D3DXMATRIX matrixInverse; // need to make new one because we have moved since
755  D3DXQuaternionNormalize(&playerships[0].orientation, &playerships[0].orientation);
756  D3DXMatrixRotationQuaternion(&matrixInverse, &playerships[0].orientation);
757  D3DXVec3TransformNormal(&shockWave.shockmag, &shockWave.shockmag, &matrixInverse);
758  shockWave.shockmag *= yield; // 0 is far away, 0*0 is 0, .9 is close, .9*.9 is .81
759  shockwaves.emplace_back(shockWave);
760 
761  sprintf_s(msg, sizeof(msg), "--- yield: %.1f kg, tti %.1f, psi: %.1f", weaponarray[t].yieldKg, shockWave.timetoshock, psi);
762  logger->Log(msg);
763 
765  }
766  else
767  {
768  sprintf_s(msg, sizeof(msg), "--- yield: %.1f kg, no shock wave, psi: %.1f", weaponarray[t].yieldKg, psi);
769  logger->Log(msg);
770  }
771  }
772 
773  // sound effect
774  float volume = 1.0f;
775  if (weaponarray[t].yieldKg > 0)
776  volume = powf(weaponarray[t].yieldKg, 0.333333f) * 0.120608f;
777  volume -= powf(distance, 2.0f) * 0.02161f;
778 
779  sprintf_s(msg, sizeof(msg), "--- delay: %.3f, volume %.3f", delay, volume);
780  logger->Log(msg);
781 
783  if (volume > 1)
784  volume = 1;
785  else if (volume <= 0)
786  return;
787 
788  int soundEnum;
789  if (weaponarray[t].type == 1)
790  soundEnum = SOUND_EXPLODE1;
791  else if (weaponarray[t].type == 2) // sinker
792  soundEnum = SOUND_EXPLODE2;
793  else
794  soundEnum = SOUND_EXPLODE3 + rand() % 3;
795 
796  viewscreen->gameclass->sound->AddDelayedSound(soundEnum, delay, volume * viewscreen->gameclass->sound->GetAttenuation(false));
797 }
798 
799 void weapon::Render(IDirect3DDevice9* pd3dDevice, D3DXMATRIX* matrixLookAtLocal)
800 {
801  viewscreen->logger->AddToCallStack("weapon::Render");
802 
803  D3DXMATRIX matrixTemp, matrixWorld;
804  D3DXVECTOR3 result;
805 
806  viewscreen->logger->AddToCallStack("exploded weapons");
807 
808  // Exploded weapons only
809  for (t = 0; t < MAX_WEAPONS; t++)
810  {
811  if (weaponarray[t].active && weaponarray[t].exploded)
812  {
813  D3DXMatrixRotationZ(&matrixTemp, -D3DX_PI); // 1.5
814  D3DXMatrixMultiply(&matrixWorld, &matrixTemp, matrixLookAtLocal);
815  if (weaponarray[t].type == 1 || weaponarray[t].type == 2)
816  D3DXMatrixScaling(&matrixTemp, 0.005f, 0.005f, 0.005f);
817  else if (weaponarray[t].yieldKg == 0.0f)
818  D3DXMatrixScaling(&matrixTemp, 0.06f, 0.06f, 0.06f); // ~100 foot radius
819  else
820  {
821  // so longarm is 0.06 ... at 570 kg
822  float scale = powf(weaponarray[t].yieldKg, 0.333333f) * 0.00723648f; // to keep animation size at 1:1 for longarm explosion
823  // scale up over the first second
824  if (weaponarray[t].elapsed < 1.0f)
825  scale *= sqrtf(weaponarray[t].elapsed);
826  D3DXMatrixScaling(&matrixTemp, scale, scale, scale);
827  }
828  D3DXMatrixMultiply(&matrixWorld, &matrixTemp, &matrixWorld);
829  D3DXMatrixRotationY(&matrixTemp, weaponarray[t].tilt);
830  D3DXMatrixMultiply(&matrixTemp, &matrixTemp, &matrixWorld); // matrixWorld is scaled lookat matrix
831 
832  if (weaponarray[t].reference < REF_INANOTHER)
833  {
834  result.x = static_cast<float>(weaponarray[t].precisionx - playerships[0].precisionx);
835  result.y = static_cast<float>(weaponarray[t].precisiony - playerships[0].precisiony);
836  result.z = static_cast<float>(weaponarray[t].precisionz - playerships[0].precisionz);
837  }
838  else
839  {
840  result.x = static_cast<float>(weaponarray[t].precisionx) - playerships[0].dockoffset.x;
841  result.y = static_cast<float>(weaponarray[t].precisiony) - playerships[0].dockoffset.y;
842  result.z = static_cast<float>(weaponarray[t].precisionz) - playerships[0].dockoffset.z;
843  }
844  matrixTemp._41 = -result.x;
845  matrixTemp._42 = -result.y;
846  matrixTemp._43 = -result.z;
847 
848  pd3dDevice->SetTransform(D3DTS_WORLD, &matrixTemp);
849 
850  D3DXMatrixIdentity(&matrixTemp);
851  matrixTemp._33 = weaponarray[t].animate;
852  pd3dDevice->SetTransform(D3DTS_TEXTURE0, &matrixTemp);
853  pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
854 
855  if (weaponarray[t].type == 1) // fuzerX
856  {
857  pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
858  pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); // for electric, // these two techniques are the same but use volumetric map!
859  pd3dDevice->SetTexture(0, viewscreen->m_pddsFuzerX);
860  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
861  }
862  else if (weaponarray[t].type == 2) // sinkerX
863  {
864  pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
865  pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); // for electric
866  pd3dDevice->SetTexture(0, viewscreen->m_pddsSinkerX);
867  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
868  }
869  else // blastX
870  {
871  pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
872  pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // for smokey explosion, he is the only one with alpha
873  pd3dDevice->SetTexture(0, viewscreen->m_pddsBlastX);
874  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
875  }
876 
877  pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
878  }
879  }
880 
881  // Unexploded weapons...
882  pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
883  pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
884  pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
885  pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
886  /*pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
887  pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
888 */
889  // D3DXMatrixRotationY( &matrixTemp, weaponarray[t].tilt );
890  // D3DXMatrixMultiply( &matrixTemp, &matrixTemp, &matrixWorld ); // matrixWorld is scaled lookat matrix
891 
892  viewscreen->logger->AddToCallStack("unexploded weapons");
893 
894  // Unexploded weapons...
895  for (t = 0; t < MAX_WEAPONS; t++)
896  {
897  if (weaponarray[t].active && !weaponarray[t].exploded)
898  {
899  if (weaponarray[t].type == 1 || weaponarray[t].type == 2)
900  {
901  D3DXMatrixRotationZ(&matrixTemp, -D3DX_PI); // 1.5
902  D3DXMatrixMultiply(&matrixWorld, &matrixTemp, matrixLookAtLocal);
903  D3DXMatrixScaling(&matrixTemp, 0.005f, 0.005f, 0.005f);
904  D3DXMatrixMultiply(&matrixWorld, &matrixTemp, &matrixWorld);
905  }
906  else
907  {
908  result.x = static_cast<float>(weaponarray[t].precisionx);
909  result.y = static_cast<float>(weaponarray[t].precisiony);
910  result.z = static_cast<float>(weaponarray[t].precisionz);
911  D3DXVec3Normalize(&result, &result);
912 
913  D3DXVECTOR3 result1;
914  D3DXVec3Normalize(&result1, &weaponarray[t].velocity);
915 
916  D3DXMatrixLookAtRH(&matrixWorld, &centerC, &result1, &result); // eye at up
917  D3DXMatrixRotationY(&matrixTemp, -D3DX_HALFPI); // now yaw, was roll
918  D3DXMatrixMultiply(&matrixWorld, &matrixWorld, &matrixTemp);
919  D3DXMatrixInverse(&matrixWorld, nullptr, &matrixWorld);
920  }
921 
922 
923  matrixTemp = matrixWorld; // reset to scaled lookat matrix
924 
925  if (weaponarray[t].reference < REF_INANOTHER)
926  {
927  result.x = static_cast<float>(weaponarray[t].precisionx - playerships[0].precisionx);
928  result.y = static_cast<float>(weaponarray[t].precisiony - playerships[0].precisiony);
929  result.z = static_cast<float>(weaponarray[t].precisionz - playerships[0].precisionz);
930  }
931  else
932  {
933  result.x = static_cast<float>(weaponarray[t].precisionx) - playerships[0].dockoffset.x;
934  result.y = static_cast<float>(weaponarray[t].precisiony) - playerships[0].dockoffset.y;
935  result.z = static_cast<float>(weaponarray[t].precisionz) - playerships[0].dockoffset.z;
936  }
937  matrixTemp._41 = -result.x;
938  matrixTemp._42 = -result.y;
939  matrixTemp._43 = -result.z;
940 
941  if (f_MSL < 63.0f)
942  {
943  r = static_cast<short>(255.0f * (viewscreen->ptrWeather->fFogEndHorizon*2.0f - D3DXVec3Length(&result)) / (viewscreen->ptrWeather->fFogEndHorizon));
944  if (r < 0)
945  r = 0;
946  else if (r > 255)
947  r = 255;
948  }
949  else
950  r = 255;
951  if (r == 0) continue;
952  pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, r << 24);
953 
954  pd3dDevice->SetTransform(D3DTS_WORLD, &matrixTemp);
955  if (weaponarray[t].type == 1) // fuzer // both of these use a technique
956  {
957  pd3dDevice->SetFVF(D3DFVF_NONORMAL);
958  pd3dDevice->SetStreamSource(0, viewscreen->m_avSunVertices, 0, sizeof(D3DNONORMAL));
959  pd3dDevice->SetTexture(0, viewscreen->m_pddsWeapon[static_cast<int>(weaponarray[t].animate)]);
960  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
961  }
962  else if (weaponarray[t].type == 2) // sinker
963  {
964  pd3dDevice->SetFVF(D3DFVF_NONORMAL);
965  pd3dDevice->SetStreamSource(0, viewscreen->m_avSunVertices, 0, sizeof(D3DNONORMAL));
966  pd3dDevice->SetTexture(0, viewscreen->m_pddsSinker[static_cast<int>(weaponarray[t].animate)]);
967  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
968  }
969  else if (weaponarray[t].type == 3) // longarm missle // use the acl or bcl vehicle pass!
970  {
971  pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
972  pd3dDevice->SetFVF(D3DFVF_VERTEX);
973  pd3dDevice->SetStreamSource(0, polyobjects[13].VB, 0, sizeof(D3DVERTEX));
974  pd3dDevice->SetTexture(0, viewscreen->m_pddsCityTexture[101]); // WEP-Source
975  pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, polyobjects[13].polygons);
976  pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
977  }
978  }
979  }
980 
981  viewscreen->logger->AddToCallStack("weapon::Render DONE");
982 }
983 
984 void weapon::ProcessPacket(SWeaponPacket datapacket)
985 {
986  const unsigned char slot = datapacket.array;
987 
988  if (datapacket.status == 0) // expired
989  {
990  weaponarray[slot].active = false;
991  return;
992  }
993 
994  if (datapacket.status == 1 || datapacket.status == 4) // new or explosionOnly
995  {
996  weaponarray[slot].active = true;
997  weaponarray[slot].exploded = false;
998  weaponarray[slot].animate = RandomFloat() * static_cast<float>(weaponanimateC - 1);
999  weaponarray[slot].elapsed = 0.0f;
1000  weaponarray[slot].origin = datapacket.origin; // Who launched it or 0 for explosionOnly
1001  weaponarray[slot].target = datapacket.target; // Aimed at who
1002  weaponarray[slot].type = datapacket.type; // 1=fuzer, 2=sinker, 3=longarm, 4=explosionOnly
1003  weaponarray[slot].reference = datapacket.reference;
1004  weaponarray[slot].tilt = RandomFloat() * D3DX_TAU;
1005  weaponarray[slot].yieldKg = datapacket.yieldKg;
1006 
1007  weaponarray[slot].velocity = datapacket.velocity;
1008  weaponarray[slot].veliter = weaponarray[slot].velleft = centerC;
1009 
1010  // So the theory is the FIRST packet IF IT HAS AN ORIGIN VEHICLE will use that vehicle's position, otherwise we use the universe coordinates
1011  if (datapacket.origin)
1012  {
1013  for (short t = 0; t < MAX_SCAN; t++)
1014  {
1015  if (playerships[t].active && playerships[t].vehicleId == datapacket.origin)
1016  {
1017  // when we get launch the position is offset from the vehicle that launched it
1018  if (weaponarray[slot].reference < REF_INANOTHER)
1019  {
1020  weaponarray[slot].precisionx = static_cast<double>(datapacket.position.x) + playerships[t].precisionx;
1021  weaponarray[slot].precisiony = static_cast<double>(datapacket.position.y) + playerships[t].precisiony;
1022  weaponarray[slot].precisionz = static_cast<double>(datapacket.position.z) + playerships[t].precisionz;
1023  }
1024  else
1025  {
1026  weaponarray[slot].precisionx = static_cast<double>(datapacket.position.x + playerships[t].dockoffset.x);
1027  weaponarray[slot].precisiony = static_cast<double>(datapacket.position.y + playerships[t].dockoffset.y);
1028  weaponarray[slot].precisionz = static_cast<double>(datapacket.position.z + playerships[t].dockoffset.z);
1029  }
1030  break;
1031  }
1032  }
1033  }
1034  else
1035  {
1036  // when we get explosionOnly then we get the universe coordinates
1037  weaponarray[slot].precisionx = static_cast<double>(datapacket.position.x);
1038  weaponarray[slot].precisiony = static_cast<double>(datapacket.position.y);
1039  weaponarray[slot].precisionz = static_cast<double>(datapacket.position.z);
1040  }
1041 
1042  weaponarray[slot].positer = weaponarray[slot].posleft = centerC;
1043 
1044  if (datapacket.status != 4) // launch sound effect
1045  {
1046  for (short t = 0; t < MAX_SCAN; t++)
1047  {
1048  if (playerships[t].active && playerships[t].vehicleId == datapacket.origin)
1049  {
1050  if (t == 0)
1051  {
1052  logger->Log("Weapon::ProcessPacket Weapon launched!");
1053  if (datapacket.type == 1)
1055  else if (datapacket.type == 2)
1057  else if (datapacket.type == 3)
1059  }
1060  else // not our vessel
1061  {
1062  D3DXVECTOR3 result = playerships[t].position - playerships[0].position;
1063  float distance = D3DXVec3Length(&result);
1064  if (distance < 20.0f) // 20 km limit
1065  {
1066  float f_temp = distance / 20.0f; // 0 is close, 1 is far
1067  f_temp = 1.0f - f_temp; // 1 is close, 0 is far
1069  const float inverse_f_temp = 1.0f - f_temp; // 0 is close, 1 is far
1070 
1071  logger->Log("Weapon::ProcessPacket Weapon detected!");
1072  if (f_temp < 1.0f)
1073  {
1074  int soundEnum;
1075  if (datapacket.type == 1)
1076  soundEnum = SOUND_WEAPON1;
1077  else if (datapacket.type == 2)
1078  soundEnum = SOUND_WEAPON2;
1079  else
1080  soundEnum = SOUND_WEAPON3;
1082  sqrtf(f_temp)*viewscreen->gameclass->sound->GetAttenuation(false));
1083  }
1084  }
1085  }
1086  break;
1087  }
1088  }
1089  }
1090  }
1091 
1092  bool doItAnyway = false;
1093  if (datapacket.status == 3 || datapacket.status == 4) // exploded weapons or explosionOnly
1094  {
1095  if (!weaponarray[slot].exploded)
1096  {
1097  weaponarray[slot].exploded = true;
1098  weaponarray[slot].animate = 0; // start over
1099  weaponarray[slot].elapsed = 0; // start over
1100  ExplodeWeapon(slot, datapacket.target == playerships[0].vehicleId, "Network");
1101  doItAnyway = true;
1102  }
1103  }
1104 
1105  if (datapacket.status == 2 || doItAnyway) // iterate
1106  {
1107  weaponarray[slot].velleft = datapacket.velocity - weaponarray[slot].velocity;
1108  weaponarray[slot].veliter = weaponarray[slot].velleft; // 1 seconds
1109 
1110  weaponarray[slot].posleft.x = datapacket.position.x - static_cast<float>(weaponarray[slot].precisionx);
1111  weaponarray[slot].posleft.y = datapacket.position.y - static_cast<float>(weaponarray[slot].precisiony);
1112  weaponarray[slot].posleft.z = datapacket.position.z - static_cast<float>(weaponarray[slot].precisionz);
1113  weaponarray[slot].positer = weaponarray[slot].posleft*0.25f; // 4 seconds
1114  }
1115 }
void Undock() const
float animate
Definition: globals.h:387
Scockpit ourcockpit
Definition: globals.cpp:176
LPDIRECT3DTEXTURE9 m_pddsWeapon[weaponanimateC]
Definition: Viewscreen.h:136
VECTOR2SHORT tcp
Definition: grid.h:34
VECTOR2SHORT olddepthpos
Definition: globals.h:392
s_mesh_component * componentarray
Definition: globals.h:497
float staticDensity
Definition: propulsion.h:84
D3DXVECTOR3 dockingvel
Definition: globals.h:540
weapon(Viewscreen *prtGame)
Definition: weapon.cpp:5
void EnergyWeaponImpact()
Definition: weapon.cpp:21
ID3DXEffect * g_pEffect
Definition: Graphics.h:30
float elapsed
Definition: globals.h:389
float power
Definition: globals.h:608
float fuel
Definition: globals.cpp:143
#define farplaneC
Definition: globals.h:18
bool g_bAboveClouds
Definition: globals.cpp:22
LPDIRECT3DTEXTURE9 m_pddsCityTexture[citytextureC]
Definition: Viewscreen.h:188
D3DXVECTOR3 position
Definition: globals.h:549
float yieldKg
Definition: globals.h:393
GameClass * gameclass
Definition: Viewscreen.h:292
double precisiony
Definition: globals.h:383
double precisionx
Definition: globals.h:383
LPDIRECT3DTEXTURE9 m_pddsSinker[weaponanimateC]
Definition: Viewscreen.h:137
void SendToServer(void *pData, DWORD dwSize, bool bGuaranteed, PacketOrdering order=ORDERING_NONE) const
Definition: Networking.cpp:59
D3DXVECTOR3 terpos
Definition: globals.h:449
VECTOR2SHORT CalculateCGC(D3DXVECTOR3 position, char cube) const
unsigned short vehicleId
Definition: globals.h:570
double precisiony
Definition: globals.h:550
D3DXVECTOR3 position
Definition: globals.h:280
s_network_objects playerships[MAX_SCAN]
Definition: globals.cpp:174
bool IsUserColony() const
Definition: globals.h:302
bool active
Definition: globals.h:390
D3DXVECTOR3 veliter
Definition: globals.h:385
void ProcessPacket(SWeaponPacket datapacket)
Definition: weapon.cpp:984
float weapontimer[2]
Definition: globals.cpp:142
D3DXVECTOR3 velleft
Definition: globals.h:385
short t
Definition: weapon.h:27
#define weaponanimateC
Definition: globals.h:44
short scanslot[MAX_SCAN]
Definition: Viewscreen.h:276
weather * ptrWeather
Definition: Viewscreen.h:287
#define weaponsinkerreadyC
Definition: globals.h:68
D3DXVECTOR3 velocity
Definition: globals.h:384
float shockramp
Definition: globals.h:795
PlotType type
Definition: globals.h:282
float CheckDepthMap(VECTOR2SHORT newdepthpos, short u, short v)
int closest
Definition: weapon.h:28
float fFogEndHorizon
Definition: weather.h:74
bool exploded
Definition: globals.h:390
propulsion * ptrPropulsion
Definition: Viewscreen.h:285
#define D3DFVF_NONORMAL
Definition: globals.h:108
s_universe_object allobjects[maxstarC]
Definition: globals.cpp:170
void RequestScannerData() const
Definition: GameClass.cpp:132
s_mesh_component * componentarray
Definition: globals.h:457
float CheckFloorMap(VECTOR2SHORT newdepthpos, short u, short v)
void Update(float fElapsedTime)
Definition: weapon.cpp:80
Viewscreen * viewscreen
Definition: weapon.h:24
LPDIRECT3DVOLUMETEXTURE9 m_pddsFuzerX
Definition: Viewscreen.h:138
Networking * networking
Definition: GameClass.h:107
float f_MSL
Definition: globals.cpp:36
double precisionx
Definition: globals.h:550
void Render(IDirect3DDevice9 *pd3dDevice, D3DXMATRIX *matrixLookAtLocal)
Definition: weapon.cpp:799
char reference
Definition: globals.h:386
#define weaponlongarmreadyC
Definition: globals.h:69
D3DXVECTOR3 nominalxyz
Definition: globals.h:416
bool vdatChanged
Definition: globals.h:670
float rcsThrustOutputY
Definition: Viewscreen.h:238
short s
Definition: weapon.h:27
void ExplodeWeapon(short t, bool wasus, std::string reason)
Definition: weapon.cpp:646
char type
Definition: globals.h:386
void KillScannerData() const
Definition: GameClass.cpp:125
D3DXVECTOR3 shockmag
Definition: globals.h:798
float CalculateAGL(short u, short v, D3DXVECTOR3 position, bool makeleveler)
#define depthFloorResolutionC
Definition: Viewscreen.h:28
BUILDZONE buildzone[buildingVBC]
Definition: globals.cpp:165
float timetoshock
Definition: globals.h:794
void AddDelayedSound(int soundEnum, float delay, float volume=1.0f)
Definition: Sound.cpp:1927
short targetC
Definition: Bus.h:378
LPDIRECT3DVOLUMETEXTURE9 m_pddsSinkerX
Definition: Viewscreen.h:139
float tilt
Definition: globals.h:389
VECTOR2SHORT newdepthpos
Definition: globals.cpp:140
Graphics * graphics
Definition: GameClass.h:109
D3DXVECTOR3 velocity
Definition: globals.cpp:9
const D3DXVECTOR3 centerC
D3DXVECTOR3 velocity
Definition: globals.h:540
Sound * sound
Definition: GameClass.h:108
D3DXMATRIX matrixWorld
Definition: globals.h:555
short buildzoneOrdinal
Definition: globals.h:292
float GetAttenuation(bool applyDensity) const
Definition: Sound.cpp:1062
short r
Definition: weapon.h:27
void Log(const char *msg, Level level=Info, int errorCode=0)
Definition: Logger.cpp:11
grid * ptrGrid
Definition: Viewscreen.h:279
s_polygon_object polyobjects[maxpolyC]
Definition: globals.cpp:160
std::vector< SShockWave > shockwaves
Definition: globals.cpp:56
unsigned short origin
Definition: globals.h:391
D3DXVECTOR3 headlight
Definition: globals.h:613
D3DXVECTOR3 posleft
Definition: globals.h:385
#define maxdockC
Definition: globals.h:25
Logger * logger
Definition: weapon.h:25
LPDIRECT3DVOLUMETEXTURE9 m_pddsBlastX
Definition: Viewscreen.h:140
double precisionz
Definition: globals.h:383
UINT startvertex
Definition: globals.h:408
char CalculateCube(D3DXVECTOR3 position) const
float dockprogress
Definition: globals.cpp:44
#define weaponfuzerreadyC
Definition: globals.h:67
char dead
Definition: globals.cpp:49
unsigned short components
Definition: globals.h:496
LOCALGRID2 gridarray[64][64]
Definition: globals.cpp:153
#define D3DFVF_VERTEX
Definition: globals.h:101
D3DXVECTOR3 barycentric
Definition: globals.h:540
float speedOfSoundKms
Definition: propulsion.h:74
void PlayEx(int soundEnum, bool loop, float volume=1.0f, float frequencyMod=1.0f, float pan=0.0f, bool restart=true)
Definition: Sound.cpp:606
unsigned short components
Definition: globals.h:456
void AddToCallStack(const char *msg)
Definition: Logger.cpp:86
Bus * bus
Definition: GameClass.h:112
void FireWeapon(unsigned char bay) const
Definition: weapon.cpp:599
D3DXVECTOR3 positer
Definition: globals.h:385
unsigned short target
Definition: globals.h:391
float shockspeed
Definition: globals.h:796
float RandomFloat()
Definition: MathUtilities.h:98
Logger * logger
Definition: Viewscreen.h:293
double precisionz
Definition: globals.h:550
SWeaponData weaponarray[MAX_WEAPONS]
Definition: weapon.h:30
D3DXVECTOR3 dockoffset
Definition: globals.h:549
unsigned short components
Definition: globals.h:577
LPDIRECT3DVERTEXBUFFER9 m_avSunVertices
Definition: Viewscreen.h:103
SVesselDC vdat
Definition: globals.h:669