00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "BattleJets.h"
00023 #include "BattleState.h"
00024 #include "Sound.h"
00025 #include "GameState.h"
00026
00027
00028 BattleJets::BattleJets(int numJets, Vec3D color, char team, int cityID )
00029 {
00030 m_totalHealth = numJets * BattleUnitData::getObj().armor()[4];
00031 m_color = color;
00032 m_team = team;
00033 m_cmdType = JetCommands::IDLE;
00034 m_numMissiles = numJets * 2;
00035 m_delayTime = 62 * 5;
00036 m_targetGroup = -1;
00037 m_cityID = cityID;
00038 m_pos = Vec3D(10000.0f,10000.0f,0.0f);
00039 }
00040
00041 int BattleJets::getNumJets()
00042 {
00043 int jetMaxHealth = BattleUnitData::getObj().armor()[4];
00044 return ( m_totalHealth + jetMaxHealth - 1 ) / jetMaxHealth;
00045 }
00046
00047 bool BattleJets::isReadyForOrder()
00048 {
00049 return m_cmdType == JetCommands::IDLE && m_delayTime == 0;
00050 }
00051
00052 void BattleJets::orderToBomb( int targetGroup )
00053 {
00054 m_targetGroup = targetGroup;
00055 m_target = BS->groups[targetGroup].m_pos;
00056 m_target.z += terrain_getHeight( BS->terrain, m_target.x, m_target.y );
00057
00058 m_cmdType = JetCommands::BOMB;
00059
00060 if( m_team=='A' ) m_pos = Vec3D( 800.0f, 800.0f, 0.0f );
00061 else m_pos = Vec3D(-800.0f,-800.0f, 0.0f );
00062 m_dir.x = clipAngle( 90-D3DXToDegree( atan2f( -m_pos.x, -m_pos.y ) ) );
00063 m_dir.y = 0.0f;
00064 m_dir.z = 0.0f;
00065 }
00066
00067 void BattleJets::orderToReturn()
00068 {
00069 m_cmdType = JetCommands::RETURN;
00070 if( m_team=='A' ) m_target = Vec3D( 800.0f, 800.0f, 0.0f );
00071 else m_target = Vec3D(-800.0f,-800.0f, 0.0f );
00072 m_targetGroup = -1;
00073 }
00074
00075 void BattleJets::orderToGuard( Vec3D target )
00076 {
00077 m_cmdType = JetCommands::GUARD;
00078 m_target = target;
00079
00080 if( m_team=='A' ) m_pos = Vec3D( 800.0f, 800.0f, 0.0f );
00081 else m_pos = Vec3D(-800.0f,-800.0f, 0.0f );
00082 m_dir.x = clipAngle( 90-D3DXToDegree( atan2f( -m_pos.x, -m_pos.y ) ) );
00083 m_dir.y = 0.0f;
00084 m_dir.z = 0.0f;
00085 }
00086
00087 void BattleJets::assignNewGuardTarget( Vec3D target )
00088 {
00089 m_target = target;
00090 }
00091
00092 void BattleJets::takeHit( BattleBullet &b )
00093 {
00094 bool isActive = false;
00095 if( GameState::activeBattle() )
00096 if( GameState::activeBattle()->getBSPtr() == BS ) isActive = true;
00097 float vol = Sound::getMasterSFXVol();
00098 if( !isActive ) vol *= 0.92f;
00099 Vec3D playerCol( GameState::consolePlayer()->color() );
00100 if( BS->teamAColor!=playerCol && BS->teamBColor!=playerCol ) vol = 0.0f;
00101
00102 if( math_distPlanar3D( b.m_pos, m_pos ) < 80.0f )
00103 {
00104 int prevNumJets = getNumJets();
00105 m_totalHealth -= BattleUnitData::getObj().baseDamage()[4];
00106 int newNumJets = getNumJets();
00107
00108 for( int i=0; i<prevNumJets-newNumJets; i++ )
00109 {
00110 int debrisType = sys_randInt()%2;
00111 Vec3D speed = Vec3D( 0.3f*sys_randFloat(), 0.3f*sys_randFloat(), 0.16f*(sys_randFloat()+1.0f) );
00112 FLOAT dirSpeed = 3.5f;
00113 Vec3D pos( m_pos ), target( m_target );
00114 pos.x += 6.0f * (1.0f + sys_randFloat());
00115 pos.y += 15.0f * sys_randFloat();
00116 pos.z += 30.0f;
00117 BS->debris.push_back( BattleDebris(pos,speed,dirSpeed,debrisType) );
00118
00119 Sound::play(Sound::SMPL_SFX_EXPLOSION_LARGE,vol);
00120 }
00121
00122 if( m_totalHealth < 0 ) m_totalHealth = 0;
00123 }
00124 }
00125
00126 void BattleJets::flyTo( Vec3D target )
00127 {
00128 if( m_targetGroup!= -1 )
00129 {
00130 Vec3D targetPos( BS->groups[m_targetGroup].m_pos );
00131 targetPos.z += terrain_getHeight( BS->terrain, targetPos.x, targetPos.y ) + 5.0f;
00132 m_target = targetPos;
00133 }
00134
00135 Vec3D targetVec = target - m_pos;
00136 FLOAT targetDir = clipAngle( 90-D3DXToDegree( atan2f( targetVec.x, targetVec.y ) ) );
00137 if( m_cmdType==JetCommands::GUARD ) targetDir = clipAngle(targetDir+25.0f+10.0f*sys_randFloat() );
00138
00139 FLOAT currentDir = m_dir[0];
00140 FLOAT delta;
00141 if( targetDir<0.0f ) targetDir += 360.0f;
00142 else if( targetDir>=360.0f ) targetDir -= 360.0f;
00143 if(targetDir>currentDir)
00144 {
00145 delta = targetDir - currentDir;
00146 if(delta>180.0f) delta = delta - 360.0f;
00147 }
00148 else
00149 {
00150 delta = targetDir - currentDir;
00151 if(delta<-180.0f) delta = 360.0f - delta;
00152 }
00153
00154 const FLOAT turnRate = BattleUnitData::getObj().BGTurnRate()[4];
00155 FLOAT turnAngle = delta;
00156 if( delta > turnRate ) turnAngle = turnRate;
00157 else if( delta < -turnRate ) turnAngle = -turnRate;
00158 else turnAngle = delta;
00159 m_dir[0] = clipAngle( currentDir + turnAngle );
00160
00161 FLOAT rad = D3DXToRadian( m_dir[0] );
00162 FLOAT speed = BattleUnitData::getObj().BGFullSpeed()[4];
00163 m_pos += speed * Vec3D( cosf(rad), sinf(rad), 0.0f );
00164 }
00165
00166 void BattleJets::fireAntiSurfaceMissiles()
00167 {
00168 if( m_numMissiles==0 ) return;
00169
00170 bool isActive = false;
00171 if( GameState::activeBattle() )
00172 if( GameState::activeBattle()->getBSPtr() == BS ) isActive = true;
00173 float vol = Sound::getMasterSFXVol();
00174 if( !isActive ) vol *= 0.92f;
00175 Vec3D playerCol( GameState::consolePlayer()->color() );
00176 if( BS->teamAColor!=playerCol && BS->teamBColor!=playerCol ) vol = 0.0f;
00177
00178 FLOAT dist = math_distPlanar3D(m_pos,m_target);
00179 FLOAT targetDir = math_getDir( m_pos, m_target );
00180 FLOAT deltaAngle = math_deltaDir( targetDir, m_dir.x );
00181 if( dist<=100.0f && sys_randInt()%3==0 && deltaAngle<15.0f )
00182 {
00183 m_numMissiles--;
00184 Vec3D pos( m_pos ), target( m_target );
00185 pos.x += 6.0f * (1.0f + sys_randFloat());
00186 pos.y += 15.0f * sys_randFloat();
00187 pos.z += 30.0f;
00188 target.x += 10.0f * sys_randFloat();
00189 target.y += 10.0f * sys_randFloat();
00190 BS->addBullet( BattleBullet( BulletTypes::ROCKET, m_team, -1, pos, target ));
00191 target = m_target;
00192 target.x += 15.0f * sys_randFloat();
00193 target.y += 15.0f * sys_randFloat();
00194 BS->addBullet( BattleBullet( BulletTypes::ROCKET, m_team, -1, pos, target ));
00195
00196 Sound::play(Sound::SMPL_SFX_FIRE_JET,vol);
00197 }
00198 }
00199
00200 void BattleJets::fireAntiAirMissiles()
00201 {
00202 if( m_numMissiles==0 ) return;
00203
00204 bool isActive = false;
00205 if( GameState::activeBattle() )
00206 if( GameState::activeBattle()->getBSPtr() == BS ) isActive = true;
00207 float vol = Sound::getMasterSFXVol();
00208 if( !isActive ) vol *= 0.92f;
00209 Vec3D playerCol( GameState::consolePlayer()->color() );
00210 if( BS->teamAColor!=playerCol && BS->teamBColor!=playerCol ) vol = 0.0f;
00211
00212 for( UINT i=0; i<BS->jets.size(); i++ )
00213 {
00214 BattleJets &J = BS->jets[i];
00215 if( J.m_team == m_team ) continue;
00216 if( sys_randInt()%3!=0 ) continue;
00217 FLOAT dist = math_distPlanar3D(m_pos,J.m_pos);
00218 if( dist > 100.0f ) continue;
00219 FLOAT targetDir = math_getDir( m_pos, J.m_pos );
00220 FLOAT deltaAngle = math_deltaDir( targetDir, m_dir.x );
00221 if( deltaAngle>35.0f ) continue;
00222
00223 m_numMissiles--;
00224 Vec3D pos( m_pos ), target( J.m_pos );
00225 pos.x += 6.0f * (1.0f + sys_randFloat());
00226 pos.y += 15.0f * sys_randFloat();
00227 pos.z += 30.0f;
00228
00229 target.x += 5.0f * sys_randFloat();
00230 target.y += 5.0f * sys_randFloat();
00231 target.z += 30.0f;
00232 BS->addBullet( BattleBullet( BulletTypes::ANTIAIR, m_team, -1, pos, target ));
00233 Sound::play(Sound::SMPL_SFX_FIRE_JET,vol);
00234 }
00235 }
00236
00237 int BattleJets::getCurrentCommand()
00238 {
00239 return m_cmdType;
00240 }
00241
00242 void BattleJets::assignNewBombingTarget( int targetGroup )
00243 {
00244 m_targetGroup = targetGroup;
00245 }
00246
00247 void BattleJets::update()
00248 {
00249 if( m_totalHealth <= 0 ) return;
00250
00251 if( m_delayTime>0 ) m_delayTime--;
00252
00253 if( m_cmdType==JetCommands::BOMB || m_cmdType==JetCommands::RETURN || m_cmdType==JetCommands::GUARD )
00254 flyTo(m_target);
00255
00256 if( m_cmdType==JetCommands::BOMB ) fireAntiSurfaceMissiles();
00257 if( m_cmdType==JetCommands::GUARD) fireAntiAirMissiles();
00258
00259 if( m_numMissiles==0 && m_cmdType!=JetCommands::RETURN && m_cmdType!=JetCommands::IDLE )
00260 orderToReturn();
00261
00262
00263
00264 if( m_cmdType==JetCommands::RETURN && math_distPlanar3D(m_pos,m_target) < 100.0f )
00265 {
00266 m_cmdType = JetCommands::IDLE;
00267 m_delayTime = 62 * 5;
00268 m_numMissiles = getNumJets() * 2;
00269 }
00270 }
00271
00272 void BattleJets::render()
00273 {
00274 if( m_totalHealth <= 0 ) return;
00275
00276
00277 const Vec3D crossHairSize(35.0f, 35.0f, 0.05f), dir(0,0,0);
00278 if( m_cmdType==JetCommands::BOMB )
00279 mesh_render( artWork->crossHair, m_target, crossHairSize, dir, artWork->colorRed );
00280
00281
00282 if( m_cmdType==JetCommands::GUARD )
00283 mesh_render( artWork->crossHair, m_target, crossHairSize*1.5f, dir, artWork->colorGreen );
00284
00285
00286 if( m_cmdType != JetCommands::IDLE )
00287 {
00288 Vec3D leftPt = math_translateObjectToWorld( m_pos, m_dir, Vec3D( -4.0f, -3.5f, 0.0f) );
00289 Vec3D rightPt = math_translateObjectToWorld( m_pos, m_dir, Vec3D( -4.0f, +3.5f, 0.0f) );
00290 Vec3D leftVec( leftPt - m_pos );
00291 Vec3D rightVec( rightPt - m_pos );
00292
00293 Vec3D size( BattleUnitData::getObj().jetSize() );
00294 const FLOAT leftStep[12] = { 0.0f, 1.0f, 0.0f, 2.0f, 1.0f, 0.0f, 3.0f, 2.0f, 1.0f, 0.0f, 3.0f,-1.0f };
00295 const FLOAT rightStep[12] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2.0f, 0.0f, 1.0f, 2.0f, 3.0f,-1.0f, 3.0f };
00296 int N = getNumJets();
00297 for( int i=0; i<N; i++ )
00298 {
00299 Vec3D pos( m_pos + leftStep[i]*leftVec + rightStep[i]*rightVec );
00300 pos.z += 30.0f;
00301 mesh_render( artWork->jet_mesh, pos, size, m_dir, artWork->jet_texture, NULL, m_color );
00302 }
00303 }
00304 }
00305
00306 void BattleJets::renderIcon(FLOAT y)
00307 {
00308 if( m_totalHealth <= 0 ) return;
00309
00310 overlay_image( artWork->jetsIconTex, Vec2D(0.970f,y+0.035f), Vec2D(0.06f,0.07f) );
00311
00312
00313 overlay_text() << getNumJets();
00314 overlay_textOut( Vec2D(0.946f, y+0.010f), 0.70f, Colors::black );
00315
00316
00317 if( m_cmdType==JetCommands::IDLE)
00318 {
00319 if( m_delayTime==0 ) overlay_text() << "Ready";
00320 else
00321 {
00322 int sec = m_delayTime / 62;
00323 int min = sec / 60;
00324 sec = sec % 60;
00325 overlay_text() << min << ":";
00326 if( sec<10 ) overlay_text() << 0;
00327 overlay_text() << sec;
00328 }
00329 }
00330 else if( m_cmdType==JetCommands::BOMB) overlay_text() << "Bombing";
00331 else if( m_cmdType==JetCommands::RETURN) overlay_text() << "Returning";
00332 else overlay_text() << "Guarding";
00333
00334 overlay_textOut( Vec2D(0.948f, y+0.048f), 0.58f, Colors::black );
00335 }
00336