Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
missile_generic.cpp
Go to the documentation of this file.
1 #include "universe_util.h"
2 #include "missile_generic.h"
3 #include "unit_generic.h"
4 #include "vegastrike.h"
5 #include "vs_globals.h"
6 #include "configxml.h"
7 #include "images.h"
8 #include "collection.h"
9 #include "star_system_generic.h"
10 #include "role_bitmask.h"
11 #include "ai/order.h"
12 #include "faction_generic.h"
13 #include "unit_util.h"
15 {
16  //WARNING: This is a big performance problem...
17  //...responsible for many hiccups.
18  //TODO: Make it use the collidemap to only iterate through potential hits...
19  //PROBLEM: The current collidemap does not allow this efficiently (no way of
20  //taking the other unit's rSize() into account).
21  if ( !dischargedMissiles.empty() ) {
22  Unit *un;
23  for (un_iter ui = getUnitList().createIterator();
24  NULL != ( un = (*ui) );
25  ++ui)
26  dischargedMissiles.back()->ApplyDamage( un );
27  delete dischargedMissiles.back();
28  dischargedMissiles.pop_back();
29  }
30 }
32 {
33  float rad = (smaller->Position().Cast()-pos).Magnitude()-smaller->rSize();
34  if (rad < .001) rad = .001;
35  float orig = rad;
36  rad = rad*rad;
37  if (smaller->isUnit() != MISSILEPTR && rad < radius*radius) {
38  if ( rad < (radialmultiplier*radialmultiplier) ) {
39  rad =
40  ( radialmultiplier*radialmultiplier*radialmultiplier*radialmultiplier
41  /( (2*radialmultiplier*radialmultiplier)-(orig*orig) ) );
42  }
43  /*
44  * contrived formula to create paraboloid falloff rather than quadratic peaking at 2x damage at origin
45  * rad = radmul^4/(2radmul^2-orig^2)
46  */
47  rad = rad/(radialmultiplier*radialmultiplier); //where radialmultiplier is radius of point with 0 falloff
48 
49  Vector norm( pos-smaller->Position().Cast() );
50  norm.Normalize();
51  smaller->ApplyDamage( pos, norm, damage/rad, smaller, GFXColor( 1,
52  1,
53  1,
54  1 ), ownerDoNotDereference, phasedamage
55  > 0 ? phasedamage/rad : 0 );
56  }
57 }
58 
60 {
61  static float missile_multiplier =
62  XMLSupport::parse_float( vs_config->getVariable( "graphics", "missile_explosion_radius_mult", "1" ) );
63 
64  return radial_effect*(missile_multiplier);
65 }
66 
68 {
69  dischargedMissiles.push_back( me );
70 }
72 {
73  if ( (damage != 0 || phasedamage != 0) && !discharged )
76  discharged = true;
77 }
78 void Missile::Kill( bool erase )
79 {
80  Discharge();
81  Unit::Kill( erase );
82 }
84  const QVector &biglocation,
85  const Vector &bignormal,
86  const QVector &smalllocation,
87  const Vector &smallnormal,
88  float dist )
89 {
90  static bool doesmissilebounce = XMLSupport::parse_bool( vs_config->getVariable( "physics", "missile_bounce", "false" ) );
91  if (doesmissilebounce)
92  Unit::reactToCollision( smaller, biglocation, bignormal, smalllocation, smallnormal, dist );
93  if (smaller->isUnit() != MISSILEPTR) {
94  //2 missiles in a row can't hit each other
95  this->Velocity = smaller->Velocity;
96  Velocity = smaller->Velocity;
97  Discharge();
98  if (!killed)
99  DealDamageToHull( smalllocation.Cast(), hull+1 ); //should kill, applying addmissile effect
100  }
101 }
102 
104 {
105  return NULL; //THIS FUNCTION IS TOO SLOW__AND ECM SHOULD WORK DIFFERENTLY ANYHOW...WILL SAVE FIXING IT FOR LATER
106 
107  QVector pos( me->Position() );
108  Unit *un = NULL;
109  Unit *targ = NULL;
110  double minrange = FLT_MAX;
112  ( un = (*i) );
113  ++i) {
114  if (un == me)
115  continue;
116  if (un->isUnit() != UNITPTR)
117  continue;
118  if (un->hull < 0)
119  continue;
120  if (UnitUtil::getFactionRelation( me, un ) >= 0)
121  continue;
122  double temp = (un->Position()-pos).Magnitude()-un->rSize();
123  if (targ == NULL) {
124  targ = un;
125  minrange = temp;
126  } else if (temp < minrange) {
127  targ = un;
128  }
129  }
130  if (targ == NULL) {
132  ( un = (*i) );
133  ++i)
134  if ( UnitUtil::isSun( un ) ) {
135  targ = un;
136  break;
137  }
138  }
139  return targ;
140 }
142  const Transformation &old_physical_state,
143  const Vector &accel,
144  float difficulty,
145  const Matrix &transmat,
146  const Vector &CumulativeVelocity,
147  bool ResolveLast,
148  UnitCollection *uc )
149 {
150  Unit *targ;
151  if ( ( targ = ( Unit::Target() ) ) ) {
152  had_target = true;
153  if (targ->hull < 0) {
154  targ = NULL;
155  } else {
156  static size_t max_ecm = (size_t)XMLSupport::parse_int( vs_config->getVariable( "physics", "max_ecm", "4" ) );
157  size_t missile_hash = ( (size_t) this ) / 16383;
158  if ( (int)(missile_hash%max_ecm) < UnitUtil::getECM(targ)) {
159  Target( NULL ); //go wild
160  } else if (hull > 0) {
161  static unsigned int pointdef = ROLES::getRole( "POINTDEF" );
162  targ->graphicOptions.missilelock = true;
163  un_iter i = targ->getSubUnits();
164 
165  Unit *su;
166  for (; (su = *i) != NULL; ++i)
167  if (su->attackPreference() == pointdef) {
168  if (su->Target() == NULL) {
169  float speed, range, mrange;
170  su->getAverageGunSpeed( speed, range, mrange );
171  if ( ( Position()-su->Position() ).MagnitudeSquared() < range*range ) {
172  su->Target( this );
173  su->TargetTurret( this );
174  }
175  }
176  }
177  }
178  }
179  }
180  if (retarget == -1) {
181  if (targ)
182  retarget = 1;
183  else
184  retarget = 0;
185  }
186  if (retarget && targ == NULL)
187  Target( NULL ); //BROKEN
188  if ( had_target && !( Unit::Target() ) ) {
189  static float max_lost_target_live_time =
190  XMLSupport::parse_float( vs_config->getVariable( "physics", "max_lost_target_live_time", "30" ) );
191  if (time > max_lost_target_live_time)
192  time = max_lost_target_live_time;
193  }
194  Unit::UpdatePhysics2( trans, old_physical_state, accel, difficulty, transmat, CumulativeVelocity, ResolveLast, uc );
195  this->time -= SIMULATION_ATOM;
196  if (NULL != targ) {
197  float checker = targ->querySphere( Position()-( SIMULATION_ATOM*GetVelocity() ), Position(), rSize() );
198  if ( (checker
199  && detonation_radius >= 0)
200  || ( ( Position()-targ->Position() ).Magnitude()-targ->rSize()-rSize() < detonation_radius ) ) {
201  //spiritplumber assumes that the missile is hitting a much larger object than itself
202  static float percent_missile_match_target_velocity =
203  XMLSupport::parse_float( vs_config->getVariable( "physics", "percent_missile_match_target_velocity", ".5" ) );
204 
205  this->Velocity += percent_missile_match_target_velocity*(targ->Velocity-this->Velocity);
206  Discharge();
207  time = -1;
208  //Vector norm;
209  //float dist;
210  /*** WARNING COLLISION STUFF... TO FIX FOR SERVER SIDE SOMEDAY ***
211  * if ((targ)->queryBoundingBox (Position(),detonation_radius+rSize())) {
212  * Discharge();
213  * time=-1;
214  * }
215  */
216  }
217  }
218  if (time < 0)
219  DealDamageToHull( Vector( .1, .1, .1 ), hull+1 );
220 }
221