Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

BattleEntry.cpp

Go to the documentation of this file.
00001 /*
00002 CS Senior Project 2003
00003 Team : Leftfield
00004 Project : ModernWarfare
00005 Members :
00006 - Russ Christensen              <rchriste@cs.utah.edu>
00007 - Todd Smith                    <tcsmith@cs.utah.edu>
00008 - Usit Duongsaa                 <duongsaa@cs.utah.edu>
00009 Copyright 2003 Russ Christensen, Usit Duongsaa, and Todd Smith. All rights reserved.
00010 
00011 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00012 
00013 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
00014 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
00015 THIS SOFTWARE IS PROVIDED BY RUSS CHRISTENSEN, USIT DUONGSAA, AND TODD SMITH ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RUSS, USIT, TODD OR OTHER CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00016 */
00017 
00022 #include "BattleEntry.h"
00023 #include "Globals.h"
00024 #include "HUD.h"
00025 #include "GameState.h"
00026 #include "Sound.h"
00027 #include "Icon.h"
00028 
00029 using namespace Globals;
00030 using namespace NetworkMessages;
00031 
00032 const int SELECT_JETS   =       100;    // if m_selected >= this number, it means we're actually
00033                                                                         // select jet group # m_selected - thisNumber
00034                                                                         // i.e. 103 = Jet group #3
00035 
00036 //------------------------------------------------------------------------------------
00037 BattleEntry::BattleEntry( const Vec3D teamAColor, const Vec3D teamBColor, const Vec2D location )
00038 {
00039         m_teamAColor = teamAColor;
00040         m_teamBColor = teamBColor;
00041         m_location = location;
00042 
00043         m_camTarget = Vec3D(0.0f,0.0f,0.0f);
00044         m_camHeight = 100.0f;
00045 
00046         m_firstTime = true;
00047         m_selected = -1;
00048         m_winner = '?';
00049 
00050         BS = new BattleState();
00051 
00052         for( int i=0; i<9; i++ )  m_ctrlGroup[i] = -1;          // clear group assignment
00053 
00054         BS->m_cvLastContact     = 0;
00055         BS->m_cvLastStress      = 0;
00056         BS->m_cvLastPanick      = 0;
00057 
00058         m_rfmCalledA = m_rfmCalledB = 0;
00059         m_showBigMiniMap = true;
00060 }
00061 //------------------------------------------------------------------------------------
00062 void BattleEntry::inputSelectGroups()
00063 {
00064         Vec2D mousePos( input_getMouseX(), input_getMouseY() );
00065         Vec3D playerColor( GameState::consolePlayer()->color() );
00066         ControlMode mode = GameState::controlMode();
00067 
00068         if( input_isMouseLBClicked() && mousePos.y < 0.8f ) 
00069         {
00070                 int groupAtCursor = getGroupAtPos2D(mousePos);
00071                 if( groupAtCursor!=-1 )
00072                 {                       
00073                         if( BS->groups[groupAtCursor].m_color==playerColor || mode==GOD )       // can only select your own units
00074                                 m_selected = groupAtCursor;
00075                 }
00076                 else m_selected = -1;
00077 
00078                 if( m_selected==-1 )
00079                         HUD::clearSelections();
00080                 else
00081                 {
00082                         if(m_selected < SELECT_JETS )  HUD::setSelectedGroupType( BS->groups[m_selected].m_unitType );
00083                         else                                               HUD::setSelectedGroupType(UnitTypes::JET);
00084                         Sound::playRandomSound( Sound::CLASS_SELECT );
00085                 }
00086                         
00087         }
00088 }
00089 //------------------------------------------------------------------------------------
00090 void BattleEntry::inputSelectJets()
00091 {
00092         Vec3D playerColor( GameState::consolePlayer()->color() );
00093         Vec2D mousePos( input_getMouseX(), input_getMouseY() );
00094 
00095         if( input_isMouseLBClicked() && mousePos.x > 0.940f )
00096         {
00097                 FLOAT yOffset = 0.2f;
00098                 for( UINT i=0; i<BS->jets.size(); i++ )
00099                 {
00100                         if( BS->jets[i].m_color!=playerColor ) continue;                                        // can only select your own jets
00101 
00102                         if( mousePos.y >= yOffset && mousePos.y <= yOffset+0.07f )
00103                         {
00104                                 m_selected = i + SELECT_JETS;
00105                                 break;
00106                         }
00107                         yOffset += 0.08f;
00108                 }
00109 
00110                 if(m_selected>=SELECT_JETS)  Sound::playRandomSound( Sound::CLASS_SELECT );
00111         }
00112 
00113         if(m_selected==-1 )                                     HUD::setSelectedGroupType(-1);
00114         else if(m_selected < SELECT_JETS )  HUD::setSelectedGroupType( BS->groups[m_selected].m_unitType );
00115         else                                                            HUD::setSelectedGroupType(UnitTypes::JET);
00116 }
00117 //------------------------------------------------------------------------------------
00118 void BattleEntry::inputIssueGroupCommand()
00119 {
00120         Vec2D mousePos( input_getMouseX(),input_getMouseY() );
00121 
00122         if( m_selected!=-1 && m_selected < SELECT_JETS)                                 // stop command 
00123                 if( input_isKeyPressed(KeyCodes::key_S) || HUD::isButtonStopClicked() )
00124                 {
00125                         ostringstream cmd;
00126                         cmd << COMMAND_BATTLEMODE << " " << COMMIT_TIME << " " << (currGameTick+NETWORK_GAME_TICK_LAG)
00127                                 << " " << COMMAND_BATTLE_ID << " " << this->uniqueID();
00128                         if( net_amIServer() ) cmd << " A "; else cmd << " B ";
00129                         cmd << "Stop " << m_selected;
00130                         net_send(cmd.str());
00131                         return;
00132                 }
00133         
00134 
00135         if( input_isMouseRBClicked() && m_selected!=-1 && m_selected < SELECT_JETS)
00136         {
00137                 BattleGroup &G = BS->groups[m_selected];
00138                 int targetGrp = getGroupAtPos2D(mousePos);
00139                 Sound::playRandomSound( Sound::CLASS_ACK );
00140 
00141                 ostringstream cmd;
00142                 cmd << COMMAND_BATTLEMODE << " " << COMMIT_TIME << " " << (currGameTick+NETWORK_GAME_TICK_LAG)
00143                         << " " << COMMAND_BATTLE_ID << " " << this->uniqueID();
00144                 if( net_amIServer() ) cmd << " A "; else cmd << " B ";
00145 
00146                 if( targetGrp!=-1 && getTeamCode(targetGrp)!=getTeamCode(m_selected) )
00147                 {
00148                         if( input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL) )
00149                         {                                                                                                                                               // assign primary target command
00150                                 cmd << "AssignTarget " << m_selected << ' ' << targetGrp;
00151                         }
00152                         else                                                                                                                                    // intercept command
00153                         {
00154                                 cmd << "Intercept " << m_selected << ' ' << targetGrp;
00155                         }
00156                 }
00157                 else                                                                                                                                            // move command
00158                 {
00159                         Vec3D pt = math_translateScreenToWorldPlane( mousePos, 0.0f );
00160                         
00161                         if( !input_isKeyDown(KeyCodes::key_LSHIFT) && !input_isKeyDown(KeyCodes::key_RSHIFT) )
00162                                 cmd << "SetWaypoint "; else cmd << "AddWaypoint ";
00163                         cmd << m_selected << " ";
00164                         cmd << pt.x << " " << pt.y << " " << pt.z;                      
00165                 }
00166 
00167                 net_send(cmd.str());
00168         }
00169 }
00170 //------------------------------------------------------------------------------------
00171 void BattleEntry::inputIssueJetsCommand()
00172 {       
00173         Vec2D mousePos( input_getMouseX(),input_getMouseY() );
00174         int jSelected = m_selected - SELECT_JETS;
00175         if( jSelected<0 ) return;                                                       // the selected unit is not a jet
00176 
00177         ostringstream cmd;
00178         cmd << COMMAND_BATTLEMODE << " " << COMMIT_TIME << " " << (currGameTick+NETWORK_GAME_TICK_LAG)
00179                 << " " << COMMAND_BATTLE_ID << " " << this->uniqueID();
00180         if( net_amIServer() ) cmd << " A "; else cmd << " B ";
00181 
00182         // stop & return home
00183         if( input_isKeyPressed(KeyCodes::key_S) || HUD::isButtonStopClicked() )
00184         {
00185                 BattleJets &J = BS->jets[ jSelected ];
00186                 if( J.getCurrentCommand()!=JetCommands::IDLE )
00187                 {
00188                         Sound::playRandomSound( Sound::CLASS_ACK );
00189                         cmd << "JReturn " << jSelected;
00190                         net_send(cmd.str());
00191                         return;
00192                 }
00193         }
00194 
00195         if( input_isMouseRBClicked() )
00196         {
00197                 BattleJets &J = BS->jets[ jSelected ];
00198                 int targetGrp = getGroupAtPos2D(mousePos);
00199                 if( targetGrp!=-1 && getTeamCode(targetGrp)!=getTeamCode(m_selected) )          // bomb target
00200                 {
00201                         if( J.isReadyForOrder() )
00202                         {
00203                                 Sound::playRandomSound( Sound::CLASS_ACK );
00204                                 cmd << "JBomb " << jSelected << ' ' << targetGrp;
00205                                 net_send(cmd.str());                            
00206                         }
00207                         else if( J.getCurrentCommand()==JetCommands::BOMB )
00208                         {
00209                                 Sound::playRandomSound( Sound::CLASS_ACK );
00210                                 cmd << "JAssignNewBomb " << jSelected << ' ' << targetGrp;
00211                                 net_send(cmd.str());                            
00212                         }
00213                 }
00214                 else                                                                                                                                            // guard area
00215                 {
00216                         Vec3D pt = math_translateScreenToWorldPlane( mousePos, 0.0f );
00217                         pt.z += terrain_getHeight( BS->terrain, pt.x, pt.y ) + 5.0f;
00218 
00219                         if( J.isReadyForOrder() )
00220                         {
00221                                 Sound::playRandomSound( Sound::CLASS_ACK );
00222                                 cmd << "JGuard " << jSelected << ' ' << pt.x << ' ' << pt.y << ' ' << pt.z;
00223                                 net_send(cmd.str());                            
00224                         }
00225                         else if( J.getCurrentCommand()==JetCommands::GUARD )
00226                         {
00227                                 Sound::playRandomSound( Sound::CLASS_ACK );
00228                                 cmd << "JAssignNewGuard " << jSelected << ' ' << pt.x << ' ' << pt.y << ' ' << pt.z;
00229                                 net_send(cmd.str());                            
00230                         }
00231                 }               
00232         }
00233 }
00234 //------------------------------------------------------------------------------------
00235 void BattleEntry::inputCtrlGroup()
00236 {
00237         if( input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL) )
00238         {                                                               // assign group
00239                 if( input_isKeyPressed(KeyCodes::key_0) ) m_ctrlGroup[0] = m_selected;
00240                 if( input_isKeyPressed(KeyCodes::key_1) ) m_ctrlGroup[1] = m_selected;
00241                 if( input_isKeyPressed(KeyCodes::key_2) ) m_ctrlGroup[2] = m_selected;
00242                 if( input_isKeyPressed(KeyCodes::key_3) ) m_ctrlGroup[3] = m_selected;
00243                 if( input_isKeyPressed(KeyCodes::key_4) ) m_ctrlGroup[4] = m_selected;
00244                 if( input_isKeyPressed(KeyCodes::key_5) ) m_ctrlGroup[5] = m_selected;
00245                 if( input_isKeyPressed(KeyCodes::key_6) ) m_ctrlGroup[6] = m_selected;
00246                 if( input_isKeyPressed(KeyCodes::key_7) ) m_ctrlGroup[7] = m_selected;
00247                 if( input_isKeyPressed(KeyCodes::key_8) ) m_ctrlGroup[8] = m_selected;
00248                 if( input_isKeyPressed(KeyCodes::key_9) ) m_ctrlGroup[9] = m_selected;
00249         }
00250         else                                                    // select group
00251         {
00252                 if( input_isKeyPressed(KeyCodes::key_0) ) m_selected = m_ctrlGroup[0];
00253                 if( input_isKeyPressed(KeyCodes::key_1) ) m_selected = m_ctrlGroup[1];
00254                 if( input_isKeyPressed(KeyCodes::key_2) ) m_selected = m_ctrlGroup[2];
00255                 if( input_isKeyPressed(KeyCodes::key_3) ) m_selected = m_ctrlGroup[3];
00256                 if( input_isKeyPressed(KeyCodes::key_4) ) m_selected = m_ctrlGroup[4];
00257                 if( input_isKeyPressed(KeyCodes::key_5) ) m_selected = m_ctrlGroup[5];
00258                 if( input_isKeyPressed(KeyCodes::key_6) ) m_selected = m_ctrlGroup[6];
00259                 if( input_isKeyPressed(KeyCodes::key_7) ) m_selected = m_ctrlGroup[7];
00260                 if( input_isKeyPressed(KeyCodes::key_8) ) m_selected = m_ctrlGroup[8];
00261                 if( input_isKeyPressed(KeyCodes::key_9) ) m_selected = m_ctrlGroup[9];
00262         }
00263 }
00264 //------------------------------------------------------------------------------------
00265 void BattleEntry::inputSelectByHotKey()
00266 {
00267         if( input_isKeyPressed(KeyCodes::key_N) )               // next ground group
00268         {
00269                 int N = (int) BS->groups.size();
00270                 m_selected = (m_selected+1) % N;
00271                 Vec3D playerCol( GameState::consolePlayer()->color() );
00272                 while( BS->groups[m_selected].m_color!=playerCol || BS->groups[m_selected].m_numUnits<=0 )
00273                         m_selected = (m_selected+1) % N;
00274         }
00275 
00276         if( input_isKeyPressed(KeyCodes::key_J) )               // next jet group
00277         {
00278                 m_selected = -1;
00279                 Vec3D playerCol( GameState::consolePlayer()->color() );
00280                 for( int i=0; i<(int)BS->jets.size(); i++ )
00281                 {
00282                         BattleJets &J = BS->jets[i];
00283                         if( J.m_color==playerCol && J.getNumJets()>0 && J.isReadyForOrder() )
00284                         {
00285                                 m_selected = SELECT_JETS + i;
00286                                 return;
00287                         }
00288                 }
00289         }
00290 }
00291 //------------------------------------------------------------------------------------
00292 void BattleEntry::input()
00293 {
00294   if(HUD::processOverheadInput()) return;
00295 
00296         Vec2D mousePos( input_getMouseX(), input_getMouseY() );
00297 
00298         // camera control
00299         m_camHeight = 10.0f + 130.0f * (1 - input_getMouseWheel());
00300         if( input_getMouseX()<0.02f ) m_camTarget.y += 2.5f;
00301         if( input_getMouseX()>0.98f ) m_camTarget.y -= 2.5f;
00302         if( input_getMouseY()<0.02f ) m_camTarget.x -= 2.5f;
00303         if( input_getMouseY()>0.98f ) m_camTarget.x += 2.5f;
00304         if( input_isKeyDown(KeyCodes::key_LEFT  ) ) m_camTarget.y += 5.5f;
00305         if( input_isKeyDown(KeyCodes::key_RIGHT ) ) m_camTarget.y -= 5.5f;
00306         if( input_isKeyDown(KeyCodes::key_UP    ) ) m_camTarget.x -= 5.5f;
00307         if( input_isKeyDown(KeyCodes::key_DOWN  ) ) m_camTarget.x += 5.5f;      
00308 
00309         // keep camera in battlefield area
00310         while( math_distPlanar3D(m_camTarget,Vec3D(0,45,0)) > 290.0f )
00311                 m_camTarget = m_camTarget * 0.99f;
00312         Vec3D camPos( m_camTarget+Vec3D(60.0f+m_camHeight*0.4f,0.0f,30.0f+m_camHeight) );
00313         while( math_dist3D(camPos,Vec3D(0,45,0)) > 380.0f )
00314         {
00315                 m_camHeight *= 0.99f;
00316                 m_camTarget = m_camTarget * 0.991f;
00317                 camPos = m_camTarget+Vec3D(60.0f+m_camHeight*0.4f,0.0f,30.0f+m_camHeight);
00318         }       
00319 
00320         camera_set( camPos, m_camTarget, 0 );
00321 
00322         if( input_isKeyPressed(KeyCodes::key_TAB) )  m_showBigMiniMap = !m_showBigMiniMap;  // battle minimap toggle    
00323         Box toggleButton;
00324         if( m_showBigMiniMap )  toggleButton = Box( 0.835f, 0.05f, 0.85f, 0.065f );
00325         else                                    toggleButton = Box( 0.135f, 0.65f, 0.15f, 0.665f );     
00326         if( input_isMouseLBClicked() && toggleButton.isContain(mousePos) ) m_showBigMiniMap = !m_showBigMiniMap;
00327         
00328         inputSelectGroups();                    // select group/jets
00329         inputSelectJets();
00330         inputCtrlGroup();
00331         inputSelectByHotKey();
00332 
00333         if( m_selected >= 0 && m_selected<SELECT_JETS )                                                         // de-select if selected group dies
00334                 if( BS->groups[m_selected].m_numUnits<=0 ) m_selected = -1;
00335         if( m_selected >= SELECT_JETS )
00336                 if( BS->jets[m_selected-SELECT_JETS].getNumJets() <= 0 ) m_selected = -1;
00337         
00338         inputIssueGroupCommand();
00339         inputIssueJetsCommand();
00340 }
00341 //------------------------------------------------------------------------------------
00342 void BattleEntry::enQueueInput( string cmd )
00343 {
00344         m_cmdQueue.push_back(cmd);
00345 }
00346 //------------------------------------------------------------------------------------
00347 void BattleEntry::processQueuedInput()          // process commands in the queue
00348 {       
00349         list<string>::iterator iter;
00350         for( iter=m_cmdQueue.begin(); iter!=m_cmdQueue.end();  )
00351         {
00352                 string cmd = *iter;
00353                 sys_console() << "BattleEntry::processQueuedInput:" << cmd << endl;
00354                 istringstream strm(cmd.c_str());
00355                 string msgType;
00356                 string cmdType;
00357                 char player;
00358                 int tick;
00359                 int groupNum, targetNum, jetNum;
00360                 FLOAT x, y, z;
00361 
00362                 strm >> msgType;
00363                 assert(msgType==COMMAND_BATTLEMODE);
00364                 string strBattleID;
00365                 string commitTime;
00366                 int battleID;
00367                 strm >> commitTime >> tick >> strBattleID >> battleID >> player;
00368 
00369                 if( tick > currGameTick ) { iter++; continue; }         
00370                 
00371                 assert(battleID == this->uniqueID() && "Invalid message");
00372                 strm >> cmdType;
00373 
00374                 if(cmdType=="SetWaypoint")
00375                 {
00376                         strm >> groupNum >> x >> y >> z;                        
00377                         BS->groups[groupNum].m_waypoints.resize(0);
00378                         BS->groups[groupNum].addWaypoint(Vec3D(x,y,z));
00379                         BS->groups[groupNum].m_primaryTarget = -1;
00380                 }
00381                 else if( cmdType=="AddWaypoint")
00382                 {
00383                         strm >> groupNum >> x >> y >> z;
00384                         BS->groups[groupNum].addWaypoint(Vec3D(x,y,z));
00385                         BS->groups[groupNum].m_primaryTarget = -1;
00386                 }
00387                 else if( cmdType=="AssignTarget" )
00388                 {
00389                         strm >> groupNum >> targetNum;
00390                         BS->groups[groupNum].m_primaryTarget = targetNum;
00391                         BS->groups[groupNum].m_isChasePrimaryTarget = false;
00392                         BS->groups[groupNum].m_isStrictPrimaryTarget = true;
00393                 }
00394                 else if( cmdType=="Intercept" )
00395                 {
00396                         strm >> groupNum >> targetNum;
00397                         BS->groups[groupNum].m_primaryTarget = targetNum;
00398                         BS->groups[groupNum].m_isChasePrimaryTarget = true;
00399                         BS->groups[groupNum].m_isStrictPrimaryTarget = true;
00400                 }
00401                 else if( cmdType=="JReturn" )
00402                 {
00403                         strm >> jetNum;
00404                         BattleJets &J = BS->jets[jetNum];
00405                         if( J.getCurrentCommand()!=JetCommands::IDLE )
00406                                 J.orderToReturn();
00407                 }
00408                 else if( cmdType=="JBomb" )
00409                 {
00410                         strm >> jetNum >> targetNum;
00411                         BattleJets &J = BS->jets[jetNum];
00412                         if( J.isReadyForOrder() )                       
00413                                 J.orderToBomb(targetNum);
00414                 }
00415                 else if( cmdType=="JAssignNewBomb" )
00416                 {
00417                         strm >> jetNum >> targetNum;
00418                         BattleJets &J = BS->jets[jetNum];
00419                         if( J.getCurrentCommand()==JetCommands::BOMB )                  
00420                                 J.assignNewBombingTarget(targetNum);                    
00421                 }
00422                 else if( cmdType=="JGuard" )
00423                 {
00424                         strm >> jetNum >> x >> y >> z;
00425                         BattleJets &J = BS->jets[jetNum];
00426                         if( J.isReadyForOrder() )
00427                                 J.orderToGuard(Vec3D(x,y,z));
00428                 }
00429                 else if( cmdType=="JAssignNewGuard" )
00430                 {
00431                         strm >> jetNum >> x >> y >> z;
00432                         BattleJets &J = BS->jets[jetNum];
00433                         if( J.getCurrentCommand()==JetCommands::GUARD )                 
00434                                 J.assignNewGuardTarget(Vec3D(x,y,z));
00435                 }
00436                 else if( cmdType=="Stop" )
00437                 {
00438                         strm >> groupNum;
00439                         BattleGroup &G = BS->groups[groupNum];
00440                         G.m_waypoints.resize(0);
00441                         G.m_primaryTarget = -1;
00442                         G.m_isChasePrimaryTarget = false;
00443                         G.m_isStrictPrimaryTarget = false;
00444                 }
00445                 else
00446                 {
00447                         sys_console() << WARNING << "Invalid command" << endl;
00448                         sys_flushConsole();
00449                 }
00450 
00451                 iter++;
00452                 m_cmdQueue.pop_front();         
00453         }
00454 }
00455 //------------------------------------------------------------------------------------
00456 void BattleEntry::initBattle()
00457 {
00458         int offsetA = (int)teamAGroups.size()/2;
00459         int offsetB = (int)teamBGroups.size()/2;
00460         Vec3D offsetVecA = Vec3D( 100.0f, 100.0f, 0.0f );       // deploy forces in line formation
00461         Vec3D offsetVecB = Vec3D(-100.0f,-100.0f, 0.0f );
00462         Vec3D scaleVecA  = Vec3D( -35.0f,  35.0f, 0.0f );
00463         Vec3D scaleVecB  = Vec3D(  35.0f, -35.0f, 0.0f );
00464         Vec3D dirA = Vec3D( 225.0f, 90.0f, 0.0f );
00465         Vec3D dirB = Vec3D(  45.0f, 90.0f, 0.0f );
00466         
00467         for( int i=0; i<(int)teamAGroups.size(); i++ )
00468         {
00469                 Vec3D pos = offsetVecA + (FLOAT)(i-offsetA)*scaleVecA;
00470                 Int3Tuple &t = teamAGroups[i];
00471                 if( t.a==UnitTypes::JET )
00472                         BS->jets.push_back( BattleJets( t.b, m_teamAColor, 'A', t.c) );
00473                 else
00474                         BS->groups.push_back( BattleGroup( pos, dirA, 'A', m_teamAColor, t.a, t.b, t.c ) );
00475         }
00476 
00477         for( int i=0; i<(int)teamBGroups.size(); i++ )
00478         {
00479                 Vec3D pos = offsetVecB + (FLOAT)(i-offsetB)*scaleVecB;
00480                 Int3Tuple &t = teamBGroups[i];
00481                 if( t.a==UnitTypes::JET )
00482                         BS->jets.push_back( BattleJets( t.b, m_teamBColor, 'B', t.c) );
00483                 else
00484                         BS->groups.push_back( BattleGroup( pos, dirB, 'B', m_teamBColor, t.a, t.b, t.c ) );
00485         }
00486 
00487         BS->teamAColor = m_teamAColor;
00488         BS->teamBColor = m_teamBColor;
00489         BS->terrain = artWork->battleTerrains.at(0);
00490         sys_console() << "Battle Starts at tick = " << Globals::currGameTick << endl;
00491 
00492         // set BS pointer for all
00493         for( UINT i=0; i<BS->groups.size(); i++ )  BS->groups[i].BS = BS;
00494         for( UINT i=0; i<BS->jets.size(); i++ )    BS->jets[i].BS = BS;
00495 
00496         BS->synch_firstShotTick = -1;
00497         BS->synch_firstKillTick = -1;
00498 
00499         // start with camera on top of your own units
00500         if( GameState::consolePlayer()->color()==m_teamAColor )  m_camTarget = offsetVecA;
00501         else                                                                                                     m_camTarget = offsetVecB;
00502 }
00503 //------------------------------------------------------------------------------------
00504 void BattleEntry::updateGroups()
00505 {
00506         // move&rotate battle groups
00507         for( UINT i=0; i<BS->groups.size(); i++ )
00508         {
00509                 BS->groups[i].moveBattleGroup();
00510                 BS->groups[i].moveUnits();
00511                 BS->groups[i].acquireGroupTargets();
00512                 BS->groups[i].fire();
00513         }
00514 }
00515 //------------------------------------------------------------------------------------
00516 void BattleEntry::updateJets()
00517 {
00518         for( UINT i=0; i<BS->jets.size(); i++ )
00519                 BS->jets[i].update();
00520 }
00521 //------------------------------------------------------------------------------------
00522 void BattleEntry::updateBullets()
00523 {
00524         // move bullets
00525         FLOAT bulletSpeed[4] = { 1.2f, 2.1f, 1.6f, 2.9f };
00526         FLOAT bulletHeight[4] = { 22.0f, 10.0f, 30.0f, 8.0f };
00527         for( int i=0; i<BS->bulletCount; i++ )
00528         {
00529                 BattleBullet &b = BS->bullets[i];
00530                 b.m_time++;             
00531                 b.m_pos.x += bulletSpeed[b.m_type] * cosf( D3DXToRadian( b.m_dir[0] ));
00532                 b.m_pos.y += bulletSpeed[b.m_type] * sinf( D3DXToRadian( b.m_dir[0] ));
00533 
00534                 Vec3D delta = b.m_target - b.m_pos;                     // calc smooth-curve Z
00535                 FLOAT dist = sqrtf( delta.x*delta.x + delta.y*delta.y);
00536                 FLOAT zFactor = 0.5f-(dist/b.m_totalDist);
00537                 if(zFactor<0) zFactor = -zFactor;
00538                 b.m_pos.z =  b.m_firingZ + sqrtf(0.5f-zFactor) * bulletHeight[b.m_type];
00539                 
00540                 FLOAT deltaZ = b.m_target.z - b.m_firingZ;      // adjust for deltaZ between firing and target height
00541                 b.m_pos.z += deltaZ * (1.0f - dist/b.m_totalDist);
00542 
00543                 if( b.m_type==BulletTypes::ROCKET )                     // create rocket trails
00544                         BS->sprites.push_back( BattleSprite( b.m_pos, 15, BattleSpriteTypes::ROCKET_TRAIL ));
00545 
00546                 if( b.m_type==BulletTypes::ANTIAIR)                     // create antiair rocket trails
00547                         BS->sprites.push_back( BattleSprite( b.m_pos, 15, BattleSpriteTypes::ROCKET_TRAIL ));
00548 
00549                 // destroy bullet upon impact           
00550                 if( dist < 3.0f )
00551                 {
00552                         if( b.m_targetGroup==-1 )                                                               // bullet not directed at any particular group
00553                         {
00554                                 if( b.m_type==BulletTypes::ANTIAIR )
00555                                 {
00556                                         for( UINT i=0; i<BS->jets.size(); i++ )
00557                                                 if( BS->jets[i].m_team!=b.m_team )
00558                                                         BS->jets[i].takeHit(b);
00559                                 }
00560                                 else
00561                                 {
00562                                         for( UINT i=0; i<BS->groups.size(); i++ ) BS->groups[i].takeHit(b);     
00563                                 }
00564                         }
00565                         else if( b.m_type!=BulletTypes::ANTIAIR )
00566                                 BS->groups[ b.m_targetGroup ].takeHit(b);                       // directed at a single group
00567 
00568                         BS->bulletCount--;
00569                         BS->bullets[i] = BS->bullets[BS->bulletCount];
00570                         i--;                    // redo this same spot
00571                 }
00572         }
00573 }
00574 //------------------------------------------------------------------------------------
00575 void BattleEntry::updateParticles()
00576 {
00577         updateParticleList(BS->sprites);
00578 }
00579 //------------------------------------------------------------------------------------
00580 void BattleEntry::updateDebris()
00581 {
00582         for( list<BattleDebris>::iterator iter = BS->debris.begin(); iter!=BS->debris.end(); )
00583         {
00584                 BattleDebris &d = (*iter);
00585                 d.pos += d.speed;
00586                 d.speed.z -= 0.003f;
00587                 d.dir += d.dirSpeed;
00588 
00589                 if( sys_randInt()%5==0 )  BS->sprites.push_back( BattleSprite( d.pos, 20, BattleSpriteTypes::EXPLO_SMALL ));
00590                 if( sys_randInt()%12==0 )  BS->sprites.push_back( BattleSprite( d.pos, 60, BattleSpriteTypes::SMOKE_SMALL ));
00591 
00592                 if( d.pos.z < terrain_getHeight(BS->terrain, d.pos.x, d.pos.y) )
00593                 {
00594                          list<BattleDebris>::iterator toDel(iter);
00595                          iter++;
00596                          BS->debris.erase(toDel);
00597                 }
00598                 else
00599                         iter++;
00600         }
00601 }
00602 //------------------------------------------------------------------------------------
00603 void BattleEntry::update()
00604 {
00605         if(m_firstTime)                                 // first time init
00606         {
00607                 m_firstTime = false;
00608                 initBattle();
00609         }
00610 
00611         processQueuedInput();
00612 
00613         updateGroups();
00614         updateJets();
00615         updateBullets();
00616         updateParticles();
00617         updateDebris();
00618 
00619         BS->m_cvLastContact++;
00620         BS->m_cvLastStress++;
00621         BS->m_cvLastPanick++;
00622 }
00623 //------------------------------------------------------------------------------------
00624 //------------------------------------------------------------------------------------
00625 char BattleEntry::getTeamCode(int selected)
00626 {
00627         if( selected==-1 ) return '-';
00628         if( selected < SELECT_JETS )    return BS->groups[selected].m_team;     
00629         else                                                    return BS->jets[selected-SELECT_JETS].m_team;
00630 }
00631 //------------------------------------------------------------------------------------
00632 int BattleEntry::getGroupAtPos2D( Vec2D pos )
00633 {
00634         int s = -1;
00635         for( UINT i=0; i<BS->groups.size(); i++ )
00636                 if( BS->groups[i].m_numUnits > 0 )
00637                 {
00638                         if( BS->groups[i].isContain2DPoint(pos) )
00639                         {
00640                                 s = i;
00641                                 break;
00642                         }
00643                 }
00644         return s;
00645 }
00646 //------------------------------------------------------------------------------------
00647 void BattleEntry::renderEnvironment()
00648 {
00649         // terrain
00650         terrain_render( BS->terrain, artWork->terrainTexLow, artWork->terrainTexHigh,           //terrain
00651                                         artWork->terrainTexNormal );
00652 
00653         // sky
00654         mesh_render( artWork->skyMesh, Vec3D(0.0f,0.0f,0.0f), Vec3D(750.0f,750.0f,650.0f),      // sky
00655                                                            Vec3D(0.0f,0.0f,0.0f), artWork->skyTexture );
00656 
00657         // trees & rock
00658         const Vec3D dir(0,0,0);
00659         const Vec3D treeSize(1.9f,1.9f,5.0f);
00660         const Vec3D rockSize(2.4f,2.4f,1.1f);
00661         const Vec4D shadowMult(1,1,1,0.25f);
00662         Vec3D shadowVec(0.0f,0.0f,1.1f);
00663 
00664         for( int i=0; i<MAX_TREE; i++ )
00665         {
00666                 mesh_render( artWork->envTreeMesh, artWork->trees[i], treeSize, dir, artWork->envTreeTex );
00667                 sprite_add(artWork->shadow, BlendModes::MIX, artWork->trees[i]+shadowVec, shadowMult, 4.5f );
00668         }
00669         for( int i=0; i<MAX_ROCK; i++ )
00670                 mesh_render( artWork->envRockMesh, artWork->rocks[i], rockSize, dir, artWork->envRockTex );
00671 }
00672 //------------------------------------------------------------------------------------
00673 void BattleEntry::renderGroups()
00674 {       
00675         for( UINT i=0; i<BS->groups.size(); i++ ) BS->groups[i].render();
00676 
00677         if( m_selected >= 0 && m_selected < SELECT_JETS )                                                                       // selected group
00678         {
00679                 BattleGroup &G = BS->groups[m_selected];
00680                 Vec3D pt3D( G.m_pos );
00681                 pt3D.z += terrain_getHeight(BS->terrain, pt3D.x, pt3D.y );
00682                 Vec2D pt2D = math_translateWorldToScreen( pt3D );               
00683                 G.drawOutlineBox( G.m_color );
00684         }
00685 }
00686 //------------------------------------------------------------------------------------
00687 void BattleEntry::renderJets()
00688 {
00689         Vec3D playerColor( GameState::consolePlayer()->color() );
00690         FLOAT yOffset = 0.2f;
00691         for( UINT i=0; i<BS->jets.size(); i++ )         // jets
00692         {
00693                 BS->jets[i].render();
00694 
00695                 if( BS->jets[i].m_color!=playerColor ) continue;                                        // can only select your own jets
00696 
00697                 BS->jets[i].renderIcon(yOffset);
00698                 if( i == m_selected - SELECT_JETS )
00699                 {
00700                         Vec2D pt1( 0.940f, yOffset );
00701                         Vec2D pt2( 0.999f, yOffset+0.07f );
00702                         overlay_rect( pt1, pt2, false, Colors::yellow );
00703                 }
00704                 yOffset += 0.08f;
00705         }
00706 }
00707 //------------------------------------------------------------------------------------
00708 void BattleEntry::renderBullets()
00709 {
00710         AMesh bulletMesh[4] = { artWork->battleShellMesh,  artWork->battleRocketMesh,
00711                                                         artWork->battleICBMMesh,   artWork->battleRocketMesh   };
00712         Vec3D bulletSize[4] = { Vec3D(2.0f,1.0f,1.0f), Vec3D(3.5f,1.5f,1.5f),
00713                                                         Vec3D(6.0f,2.0f,2.0f), Vec3D(3.0f,1.2f,1.2f)  };
00714         for( int i=0; i<BS->bulletCount; i++ )
00715         {               
00716                 BattleBullet &b = BS->bullets[i];
00717                 mesh_render( bulletMesh[b.m_type], b.m_pos, bulletSize[b.m_type], b.m_dir, artWork->battleBulletTexture );
00718         }
00719 }
00720 //------------------------------------------------------------------------------------
00721 void BattleEntry::renderParticles()
00722 {
00723         renderParticleList(BS->sprites);        
00724 }
00725 //------------------------------------------------------------------------------------
00726 void BattleEntry::renderDebris()
00727 {
00728         AMesh debrisMesh[2] = { artWork->debris1, artWork->debris2 };
00729         Vec3D debrisSize[2] = { Vec3D(2.5f,2.5f,2.5f), Vec3D(0.7f,1.9f,1.9f) };
00730         for( list<BattleDebris>::iterator iter = BS->debris.begin(); iter!=BS->debris.end(); iter++ )
00731         {
00732                 mesh_render( debrisMesh[iter->type], iter->pos, debrisSize[iter->type],
00733                                          Vec3D(iter->dir,0,0), artWork->debrisTex );
00734         }
00735 }
00736 //------------------------------------------------------------------------------------
00737 void BattleEntry::renderInterface()
00738 {
00739         FLOAT mx = input_getMouseX(), my = input_getMouseY();                                           // mouse cursor
00740         Vec2D mousePos(mx,my);
00741         overlay_image( Globals::artWork->mouse, Vec2D(mx+0.025f,my+0.025f), Vec2D(0.05f,0.05f), BlendModes::ADD, 0.5f );
00742         overlay_image( Globals::artWork->mouse, Vec2D(mx+0.025f,my+0.025f), Vec2D(0.05f,0.05f), BlendModes::KEY, 1.0f, MOUSE_RENDER_PRIORITY );
00743 
00744         if( m_selected != -1 )                          // if you have your own unit selected and hover the cursor on the enemy
00745         {                                                                       // i.e. about to order an attack command, highlight the enemy
00746                 int target = getGroupAtPos2D(mousePos);
00747                 if( target!=-1 && getTeamCode(m_selected) != getTeamCode(target) )
00748                 {
00749                         BattleGroup &G = BS->groups[target];
00750                         G.drawOutlineBox( G.m_color );
00751                 }
00752         }
00753 
00754         // range indicator
00755         if( m_selected != -1 && m_selected < SELECT_JETS )
00756         {
00757                 Vec3D grpPos3D( BS->groups[m_selected].m_pos );
00758                 Vec2D grpPos2D( math_translateWorldToScreen( grpPos3D ) );
00759                 Vec3D targetPos3D( math_translateScreenToWorldPlane( mousePos, 0.0f ) );
00760                 overlay_line( mousePos, grpPos2D, Colors::white, BlendModes::ADD, 0.25f );              
00761                 FLOAT dist = math_distPlanar3D( grpPos3D, targetPos3D ) * 0.04f;                
00762                 dist = ((int)(dist*100.0f)) / 100.0f;
00763                 overlay_text() << dist << " miles";
00764                 overlay_textOut( mousePos+Vec2D(0,0.05f) );
00765         }       
00766 }
00767 //------------------------------------------------------------------------------------
00768 void BattleEntry::renderMiniMap()
00769 {
00770         Vec2D mousePos( input_getMouseX(), input_getMouseY() ); 
00771         FLOAT ptSize, lineLen;
00772         Vec2D UL, LR;           // up-left, low-right corner
00773         if( m_showBigMiniMap )
00774         {
00775                 UL = Vec2D( 0.15f, 0.05f );
00776                 LR = Vec2D( 0.85f, 0.75f );
00777                 ptSize = 4.0f;
00778                 lineLen = 0.060f;
00779         }
00780         else
00781         {
00782                 UL = Vec2D( 0.0f, 0.65f );
00783                 LR = Vec2D( 0.15f, 0.8f );
00784                 ptSize = 1.0f;
00785                 lineLen = 0.015f;
00786         }
00787         Vec2D UR( LR.x, UL.y ); 
00788 
00789         overlay_rect(  UL, LR, true, Colors::gray, BlendModes::MIX, 0.3f, 2 );                                  // background
00790         overlay_rect(  UR, UR+Vec2D(-0.015f,0.015f), true, Colors::gray, BlendModes::MIX, 0.4f, 3 );
00791         overlay_rect(  UR, UR+Vec2D(-0.015f,0.015f), false, Colors::gray, BlendModes::MIX, 0.6f, 3 );
00792 
00793         // if mouse over the map toggle button
00794         Icon toggleIcon;        
00795         if( m_showBigMiniMap )  toggleIcon = Icon( Vec2D(0.835f,0.05f), Vec2D(0.85f,0.065f), NULL );
00796         else                                    toggleIcon = Icon( Vec2D(0.135f,0.65f), Vec2D(0.15f,0.665f), NULL );
00797         toggleIcon.setHelpString("Toggle Battle MiniMap\nHotKey[Tab]");
00798         if( toggleIcon.contains(mousePos) ) toggleIcon.drawOutline(Colors::yellow);
00799         toggleIcon.drawHelpString();
00800         
00801         for( int i=0; i<(int)BS->groups.size(); i++ )                                   // ground forces
00802         {
00803                 BattleGroup &G = BS->groups[i];
00804                 if( G.m_numUnits<=0 ) continue;
00805                 Vec2D pos2D( G.m_pos.x, G.m_pos.y );
00806                 Vec2D pt( pos2D*(1.0f/800.0f) + Vec2D(0.5f,0.5f) );
00807                 swap( pt.x, pt.y );
00808                 pt.x = 1.0f - pt.x;
00809                 pt.x = pt.x * ( LR.x - UL.x );
00810                 pt.y = pt.y * ( LR.y - UL.y );          
00811                 pt += UL;
00812                 overlay_point( pt, ptSize, G.m_color, BlendModes::MIX, 0.7f, 4 );
00813                 
00814                 FLOAT theta = D3DXToRadian( G.m_dir.x );
00815                 Vec2D dirVec( lineLen*(-sinf(theta)), lineLen*cosf(theta) );
00816                 overlay_line( pt, pt+dirVec, G.m_color, BlendModes::MIX, 0.7f, 5 );
00817 
00818                 if( m_showBigMiniMap )          // type letter only shows in big map
00819                 {
00820                         char letters[4] = { 'L','H','R','A' };
00821                         overlay_text() << G.m_numUnits << letters[G.m_unitType];
00822                         overlay_textOut( pt+Vec2D(-0.001f,-0.001f), 0.6f, Colors::white, NULL, 5 );
00823                 }
00824         }
00825 
00826         for( int i=0; i<(int)BS->jets.size(); i++ )                                             // jets
00827         {
00828                 BattleJets &G = BS->jets[i];
00829                 if( G.getNumJets()<=0 ) continue;
00830                 Vec2D pos2D( G.m_pos.x, G.m_pos.y );
00831                 if( !Box(-400.0f,-400.0f,400.0f,400.0f).isContain(pos2D) )  continue;           
00832                 Vec2D pt( pos2D*(1.0f/800.0f) + Vec2D(0.5f,0.5f) );
00833                 swap( pt.x, pt.y );
00834                 pt.x = 1.0f - pt.x;
00835                 pt.x = pt.x * ( LR.x - UL.x );
00836                 pt.y = pt.y * ( LR.y - UL.y );          
00837                 pt += UL;
00838                 overlay_point( pt, ptSize, G.m_color, BlendModes::MIX, 0.7f, 4 );
00839                 
00840                 FLOAT theta = D3DXToRadian( G.m_dir.x );
00841                 Vec2D dirVec( lineLen*(-sinf(theta)), lineLen*cosf(theta) );
00842                 overlay_line( pt, pt+dirVec, G.m_color, BlendModes::MIX, 0.7f, 5 );
00843 
00844                 if( m_showBigMiniMap )          // type letter only shows in big map
00845                 {                       
00846                         overlay_text() << G.getNumJets() << 'J';
00847                         overlay_textOut( pt+Vec2D(-0.001f,-0.001f), 0.6f, Colors::white, NULL, 5 );
00848                 }
00849         }
00850 }
00851 //------------------------------------------------------------------------------------
00852 void BattleEntry::render()
00853 {
00854         if(m_firstTime) return;
00855 
00856         flare_begin( artWork->flareTexture, 512 );
00857 
00858         renderEnvironment();
00859         renderGroups();
00860         renderJets();
00861         renderBullets();
00862         renderParticles();
00863         renderDebris();
00864         renderInterface();
00865         renderMiniMap();
00866 
00867         overlay_text() << "Battle Mode";
00868         overlay_textOut( Vec2D(0.3f,0.01f), 3.0f, Colors::red );
00869 
00870         flare_end();
00871 }
00872 //------------------------------------------------------------------------------------
00873 bool BattleEntry::isBattleFinished()
00874 {       
00875         if(m_winner!='?') return true;
00876 
00877         // count the number of units each side has remaining.  If one side has 0 units, he loses
00878         int countA, countB;
00879         countA = countB = 0;
00880         for( UINT i=0; i<BS->groups.size(); i++ )
00881         {
00882                 BattleGroup &g = BS->groups[i];
00883                 if( g.m_team=='A' ) countA += g.m_numUnits;
00884                 else                            countB += g.m_numUnits;
00885         }
00886 
00887         if( countA>0 && countB>0 ) return false;
00888 
00889         HUD::clearSelections();
00890         if( countA==0 )  m_winner = 'B';
00891         else                     m_winner = 'A';
00892 
00893         teamAGroups.resize(0);          // get rid of all the input groups
00894         teamBGroups.resize(0);          // we'll calculate the survivors and put in the right values
00895         for( UINT i=0; i<BS->groups.size(); i++ )
00896         {
00897                 BattleGroup &g = BS->groups[i];
00898                 if( g.m_numUnits > 0 )
00899                         if( g.m_team=='A' )  teamAGroups.push_back( Int3Tuple( g.m_unitType, g.m_numUnits, g.m_overheadForceNumber ) );
00900                         else                             teamBGroups.push_back( Int3Tuple( g.m_unitType, g.m_numUnits, g.m_overheadForceNumber ) );
00901         }
00902 
00903         // put the surviving jets back in
00904         for( UINT i=0; i<BS->jets.size(); i++ )
00905         {
00906                 BattleJets &J = BS->jets[i];
00907                 if( J.getNumJets()>0 )
00908                         if( J.m_team=='A' ) teamAGroups.push_back( Int3Tuple( UnitTypes::JET, J.getNumJets(), J.m_cityID ) );
00909                         else                            teamBGroups.push_back( Int3Tuple( UnitTypes::JET, J.getNumJets(), J.m_cityID ) );
00910         }
00911 
00912         sys_console() << "Battle Finishes at tick = " << Globals::currGameTick << endl;
00913 
00914         return true;
00915 }
00916 //------------------------------------------------------------------------------------
00917 vector<Int3Tuple> BattleEntry::getSurvivors()
00918 {
00919         if( teamAGroups.size()==0 ) return teamBGroups;
00920         else return teamAGroups;
00921 }
00922 //------------------------------------------------------------------------------------
00923 Vec3D BattleEntry::getWinningTeamColor()
00924 {
00925         if(m_winner=='B')
00926                 return m_teamBColor;
00927         else
00928                 return m_teamAColor;
00929 }
00930 //------------------------------------------------------------------------------------
00931 Vec2D BattleEntry::getBattleLocation()
00932 {
00933         return m_location;
00934 }
00935 //------------------------------------------------------------------------------------
00936 bool BattleEntry::isFoughtBy(const Vec3D& teamColor) const
00937 {
00938   return teamColor == m_teamAColor || teamColor == m_teamBColor;
00939 }
00940 //------------------------------------------------------------------------------------
00941 int BattleEntry::countGroupsBelongingToPlayer( Vec3D playerColor )
00942 {
00943         int count = 0;
00944         for( UINT i=0; i<BS->groups.size(); i++ )                                               // ground
00945         {
00946                 BattleGroup &G = BS->groups[i];
00947                 if( G.m_color == playerColor && G.m_numUnits > 0 )
00948                         count++;
00949         }
00950         for( UINT i=0; i<BS->jets.size(); i++ )                                                 // air
00951         {
00952                 BattleJets &G = BS->jets[i];
00953                 if( G.m_color == playerColor && G.getNumJets() > 0 )
00954                         count++;
00955         }
00956         return count;
00957 }
00958 //------------------------------------------------------------------------------------
00959 bool BattleEntry::maySendGroundReinforcement( Vec3D playerColor )
00960 {
00961         //if( playerColor==m_teamAColor && m_rfmCalledA >= 8 ) return false;    // no more than 8 reinforcement calling
00962         //if( playerColor==m_teamBColor && m_rfmCalledB >= 8 ) return false;
00963 
00964         int count = 0;
00965         for( UINT i=0; i<BS->groups.size(); i++ )
00966         {
00967                 BattleGroup &G = BS->groups[i];
00968                 if( G.m_color == playerColor && G.m_numUnits > 0 )
00969                         count++;
00970         }
00971 
00972         if( count >= 8 ) return false;          // no more than 8 ground groups at once
00973         return true;
00974 }
00975 //------------------------------------------------------------------------------------
00976 bool BattleEntry::maySendAirReinforcement( Vec3D playerColor )
00977 {
00978         //if( playerColor==m_teamAColor && m_rfmCalledA >= 8 ) return false;    // no more than 8 reinforcement calling
00979         //if( playerColor==m_teamBColor && m_rfmCalledB >= 8 ) return false;
00980 
00981         int count = 0;
00982         for( UINT i=0; i<BS->jets.size(); i++ )
00983         {
00984                 BattleJets &G = BS->jets[i];
00985                 if( G.m_color == playerColor && G.getNumJets() > 0 )
00986                         count++;
00987         }
00988 
00989         if( count >= 4 ) return false;          // no more than 4 jets at once
00990         return true;
00991 }
00992 //------------------------------------------------------------------------------------
00993 void BattleEntry::sendGroundReinforcement( Vec3D playerColor, int unitType, int numUnits, int forceNum )
00994 {
00995         char team;      
00996         Vec3D pos, dir;
00997 
00998         int offsetA = 4;                                // data required to calc reinforcement deploying position
00999         int offsetB = 4;
01000         Vec3D offsetVecA = Vec3D( 130.0f, 130.0f, 0.0f );       // deploy forces in line formation
01001         Vec3D offsetVecB = Vec3D(-130.0f,-130.0f, 0.0f );
01002         Vec3D scaleVecA  = Vec3D( -32.0f,  32.0f, 0.0f );
01003         Vec3D scaleVecB  = Vec3D(  32.0f, -32.0f, 0.0f );
01004         Vec3D dirA = Vec3D( 225.0f, 90.0f, 0.0f );
01005         Vec3D dirB = Vec3D(  45.0f, 90.0f, 0.0f );
01006 
01007         if( playerColor==m_teamAColor )
01008         {
01009                 team = 'A';
01010                 pos = offsetVecA + (FLOAT)(m_rfmCalledA-offsetA)*scaleVecA;
01011                 dir = dirA;
01012                 m_rfmCalledA = (m_rfmCalledA + 1) % 8;
01013         }
01014         else
01015         {
01016                 team = 'B';
01017                 pos = offsetVecB + (FLOAT)(m_rfmCalledB-offsetB)*scaleVecB;
01018                 dir = dirB;
01019                 m_rfmCalledB = (m_rfmCalledB + 1) % 8;
01020         }
01021 
01022         BS->groups.push_back( BattleGroup( pos, dir, team, playerColor, unitType, numUnits, forceNum ) );
01023         BS->groups[ BS->groups.size()-1 ].BS = BS;
01024 }
01025 //------------------------------------------------------------------------------------
01026 void BattleEntry::sendAirReinforcement( Vec3D playerColor, int numJets, int homeTown )
01027 {
01028         char team;
01029         if( playerColor==m_teamAColor )
01030         {
01031                 m_rfmCalledA++;
01032                 team = 'A';
01033         }
01034         else
01035         {
01036                 m_rfmCalledB++;
01037                 team = 'B';
01038         }
01039         BS->jets.push_back( BattleJets( numJets, playerColor, team, homeTown) );
01040         BS->jets[ BS->jets.size()-1 ].BS = BS;  
01041 }
01042 //------------------------------------------------------------------------------------
01043 bool BattleEntry::contains(Vec3D pt)
01044 {
01045         Vec3D myLocation(this->getBattleLocation().x, this->getBattleLocation().y, BATTLE_CIRCLE_HEIGHT);
01046         if (math_dist3D(pt, myLocation) < BATTLE_RADIUS / 2.0f) return true;
01047         else return false;
01048 }
01049 //------------------------------------------------------------------------------------
01050 void BattleEntry::clearUnitSelection()
01051 {
01052         m_selected = -1;
01053 }
01054 //------------------------------------------------------------------------------------
01055 

Generated on Wed Apr 23 05:50:14 2003 for Modern Warfare by doxygen1.3-rc2