00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include "Network.h"
00024 #include "Overhead.h"
00025 #include "BattleEntry.h"
00026 #include "Map.h"
00027 #include "Bank.h"
00028 #include "Player.h"
00029 #include "GameConfig.h"
00030 #include "EconData.h"
00031 #include "BattleUnitData.h"
00032 #include "Sound.h"
00033 #include "Typer.h"
00034 #include "HUD.h"
00035 #include "GameState.h"
00036 #include "Tutorial.h"
00037 #include "Icon.h"
00038
00039 using namespace std;
00040 using namespace NetworkSubsystem;
00041 using namespace NetworkMessages;
00042 using namespace Helper;
00043
00044
00045 namespace Overhead {
00046 const int TRANSITION_TIME = 30;
00047 vector<DrawableObject*>& drawableObjects = GameState::drawables();
00048 vector<MilitaryUnit*>& units = GameState::units();
00049 vector<City*>& cities = GameState::cities();
00050 vector<BattleEntry*>& battles = GameState::battles();
00052 vector<MilitaryUnit*>& selectedUnits = GameState::selectedUnits();
00053 Vec2D dragCorner;
00054 bool dragging;
00055 City* selectedCity(0);
00056 FLOAT camHeight;
00057 bool focusOverhead = true;
00059 PlayerVec& players = GameState::players();
00060 bool showThreatMap = false;
00061 Typer chatBox;
00062 bool chatBoxOn = false;
00063 Tutorial tutorial;
00064 list<BattleSprite> battleCircleAnimation;
00065 Icon unitMaintenance(Vec2D(0.65f,0.81f), Vec2D(0.76f,0.85f), 0);
00066
00067 const int MODE_PLAYERS_LIST = 0;
00068
00069 const int MODE_NONE = 2;
00070 int playersNBattleListMode;
00071
00072
00073 BattleEntry *prevBattle;
00074 int transitionTimeRemaining;
00075
00076 bool youWin, youLose;
00077 int creditTimer;
00078
00079
00080 bool showConfirmQuitMenu;
00081
00082 void mainMenuCredit()
00083 {
00084 youWin = true;
00085 youLose = false;
00086 creditTimer = 0;
00087 }
00088
00089 void updateCredit()
00090 {
00091 if( creditTimer==0 )
00092 {
00093 if( youWin ) Sound::getObj().playMusic( Sound::SMPL_SONG_WIN );
00094 if( youLose ) Sound::getObj().playMusic( Sound::SMPL_SONG_LOST );
00095 }
00096
00097 if( creditTimer >= 0 ) creditTimer++;
00098 }
00099
00100 #define R() vec.push_back( "Russ Christensen" )
00101 #define T() vec.push_back( "Todd Smith" )
00102 #define U() vec.push_back( "Usit Duongsaa" )
00103 #define S() vec.push_back( "" );
00104 void renderCredit()
00105 {
00106 static vector<string> vec;
00107 if( vec.size()==0 )
00108 {
00109 S(); vec.push_back( "_Overhead Mode" ); R(); T();
00110 S(); vec.push_back( "_Battle Mode" ); U();
00111 S(); vec.push_back( "_3D Graphics Engine" ); U();
00112 S(); vec.push_back( "_Input Interface" ); U();
00113 S(); vec.push_back( "_Sound Interface" ); T();
00114 S(); vec.push_back( "_Network Interface" ); U();
00115 S(); vec.push_back( "_Multiplayer Support" ); R(); U();
00116 S(); vec.push_back( "_Chat System" ); R();
00117 S(); vec.push_back( "_Game State Synchronization" ); U(); R();
00118 S(); vec.push_back( "_HUD" ); T(); U();
00119 S(); vec.push_back( "_Game Data Management" ); T();
00120 S(); vec.push_back( "_Special Effects" ); U();
00121 S(); vec.push_back( "_Tutorial" ); R();
00122 S(); vec.push_back( "_3D Models" ); U();
00123 S(); vec.push_back( "_Textures" ); U(); T();
00124 S(); vec.push_back( "_Box Art & Quick Reference" ); R();
00125 S(); vec.push_back( "_Voice Acting" ); T();
00126 S(); vec.push_back( "_Maps" ); T();
00127 S(); vec.push_back( "_Source Control Server Maintenance" ); R();
00128 S(); vec.push_back( "_Web Site Maintenance" ); R();
00129 S(); vec.push_back( "_Internal Testing" ); U(); R(); T();
00130 S(); vec.push_back( "_Special Thanks to All Beta Testers" );
00131 vec.push_back( "Dr. John Regehr" );
00132 vec.push_back( "Michael Warner" );
00133 vec.push_back( "Tyler Beuchert" );
00134 vec.push_back( "Thanh Do" );
00135 vec.push_back( "Gregory Mayberry" );
00136 vec.push_back( "Anthony Nguyen" );
00137 vec.push_back( "Jamie Moench" );
00138 vec.push_back( "James Jensen" );
00139 vec.push_back( "Nathan Beddes" );
00140 vec.push_back( "Chantel Beck" );
00141 vec.push_back( "Scott Little" );
00142 vec.push_back( "Allison Kelly" );
00143 vec.push_back( "Justin Olson" );
00144 vec.push_back( "Kina Kousoum" );
00145 vec.push_back( "And Several Other People Whose Names We Don't Have" );
00146 vec.push_back( "_Thank you all for the excellent feedback" );
00147 }
00148
00149 FLOAT y = 1.6f - creditTimer*0.001f;
00150 for( UINT i=0; i<vec.size(); i++ )
00151 {
00152 FLOAT x = 0.15f;
00153 FLOAT size = 1.3f;
00154 Vec3D col( Colors::white );
00155 string line = vec[i];
00156 if( line[0]=='_' )
00157 {
00158 line = line.substr(1);
00159 size = 1.6f;
00160 col = Colors::yellow;
00161 }
00162
00163 if( y>=-0.2f && y<=0.7f )
00164 {
00165 overlay_text() << line;
00166 overlay_textOut( Vec2D(x,y), size, col, NULL, 9 );
00167 }
00168 y += 0.10f;
00169 }
00170
00171 }
00172
00173 void askForRandomNumbers()
00174 {
00175 static askedNumber(0);
00176 stringstream sstr;
00177 sstr << COMMAND_ASK_FOR_RANDOM_NUMBER << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG
00178 << " " << ++askedNumber;
00179 net_send(sstr.str());
00180 }
00181
00182 void doVictoryTest()
00183 {
00184 bool hasLost = true;
00185 bool hasWon = true;
00186 for(vector<City*>::iterator iter(GameState::cities().begin()); iter != GameState::cities().end(); ++iter)
00187 {
00188 if ((*iter)->color() == GameState::consolePlayer()->color()) hasLost = false;
00189 else if ((*iter)->owner() ) hasWon = false;
00190 }
00191 for(vector<MilitaryUnit*>::iterator iter(GameState::units().begin()); iter != GameState::units().end(); ++iter)
00192 {
00193 if ((*iter)->color() == GameState::consolePlayer()->color()) hasLost = false;
00194 else if( (*iter)->owner() ) hasWon = false;
00195 }
00196
00197
00198 if( GameState::battles().size()>0 ) hasWon = false;
00199
00200
00201 Vec3D playerCol( GameState::consolePlayer()->color() );
00202 for( vector<BattleEntry*>::iterator iter(GameState::battles().begin()); iter!=GameState::battles().end(); iter++ )
00203 if( (*iter)->isFoughtBy(playerCol) ) hasLost = false;
00204
00205
00206 if( input_isKeyDown(KeyCodes::key_LCONTROL) && input_isKeyDown(KeyCodes::key_LSHIFT) )
00207 {
00208 if( input_isKeyDown(KeyCodes::key_W) ) hasWon = true;
00209 if( input_isKeyDown(KeyCodes::key_L) ) hasLost = true;
00210 if( input_isKeyDown(KeyCodes::key_R) ) { creditTimer = -1; youWin=youLose=false; }
00211 }
00212
00213 if (hasLost) youLose = true;
00214 if (hasWon) youWin = true;
00215 if( hasWon || hasLost )
00216 if( creditTimer==-1 ) creditTimer = 0;
00217 }
00218
00219 int playerStrength(int playerNumber)
00220 {
00221 int strength = 0;
00222 Player* player(Helper::playerNumberToPlayerPointer(playerNumber));
00223 if (player == 0)
00224 {
00225 static bool errorReported = false;
00226 if (!errorReported)
00227 {
00228 sys_console() << "ERROR!!! Helper::playerNumberToPlayerPointer(" << playerNumber << ") returned NULL" << endl;
00229 errorReported = true;
00230 }
00231 return 0;
00232 }
00233
00234 int cityCount = Helper::totalCitiesForPlayer(player->color());
00235 if(cityCount>0) strength += player->bank().balance() / 1000;
00236 strength += Helper::totalUnitsForPlayer(player->color());
00237 strength += Helper::totalUnitsBeingBuiltForPlayer(player->color()) / 2;
00238 strength += cityCount * 5;
00239 return strength;
00240 }
00241
00242 void printPlayerList()
00243 {
00244 vector<string> playerList(net_getAllPlayers());
00245
00246
00247 pair<int,int> maxPlayerStrength;
00248 const FLOAT lineHeight = 0.037f;
00249 int strength;
00250 int totalPlayerStrength = 0;
00251 static bool tauntSent = false;
00252 for (uint i(0); i < playerList.size(); ++i)
00253 {
00254 int j = net_getPlayerNumUsingName( playerList[i] );
00255 strength = playerStrength(j);
00256 totalPlayerStrength += strength;
00257 if (strength > maxPlayerStrength.second)
00258 {
00259 maxPlayerStrength.second = strength;
00260 maxPlayerStrength.first = j;
00261 }
00262 }
00263
00264 for (uint i(0); i < playerList.size(); ++i)
00265 {
00266 Vec3D plyrColor( playerNumberToPlayerColor(i) );
00267 string plyrName( net_getPlayerNameUsingNum(i) );
00268 FLOAT plyrStr = playerStrength(i)*1.0f / totalPlayerStrength;
00269 if( plyrName.length()>13 ) plyrName = plyrName.substr(0,12) + "-";
00270 overlay_text() << plyrName;
00271 overlay_textOut( Vec2D(0.01f, 0.043f+lineHeight*i), 0.8f, plyrColor, NULL, 7 );
00272 overlay_rect( Vec2D( 0.13f,0.044f+lineHeight*i), Vec2D( 0.13f+plyrStr*0.068f, 0.038f+lineHeight*(i+1) ),
00273 true, Colors::gray, BlendModes::MIX, 0.6f, 6 );
00274 }
00275
00276 if (maxPlayerStrength.second >= totalPlayerStrength && !tauntSent)
00277 {
00278 tauntSent = true;
00279 stringstream sstr;
00280 sstr << Helper::playerColorToPlayerName(Helper::playerNumberToPlayerColor(maxPlayerStrength.first)) << " says: ";
00281 sstr << "I kicking your pfft you w00t!!!";
00282 GameState::messagesReceived().addMessage(sstr.str());
00283
00284 }
00285
00286 int numPlayers = (int)net_getAllPlayers().size();
00287 overlay_rect( Vec2D(0,0.04f), Vec2D(0.2f,0.04f + lineHeight*numPlayers), true,
00288 Colors::green, BlendModes::MIX, 0.2f, 5 );
00289 overlay_rect( Vec2D(0,0.04f), Vec2D(0.2f,0.04f + lineHeight*numPlayers), false,
00290 Colors::gray, BlendModes::MIX, 0.4f, 5 );
00291 }
00292
00293 void printBattleList()
00294 {
00295 }
00296
00297 void printTaunts()
00298 {
00299 }
00300
00301 void doTutorial()
00302 {
00303 if (!GameState::battles().empty()) tutorial.battleMode();
00304 if (GameState::battles().size() > 1) tutorial.twoBattlesAtOnce();
00305 if (selectedCity) tutorial.city();
00306 if (!selectedUnits.empty()) tutorial.unit();
00307 }
00308
00309 void sendMessageToPrintARandomNumberToTheConsole()
00310 {
00311 stringstream sstr;
00312 sstr << COMMAND_PRINT_A_RANDOM_NUMBER_TO_THE_CONSOLE << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG;
00313 net_send(sstr.str());
00314 }
00315
00316 bool playerExists(const string & player)
00317 {
00318 vector<string> playerList(net_getAllPlayers());
00319 for(vector<string>::iterator iter = playerList.begin(); iter != playerList.end(); ++iter)
00320 {
00321 string tmp(Helper::toLower(*iter));
00322 if (tmp == player) return true;
00323 }
00324 return false;
00325 }
00326
00327 void processCommand(string command)
00328 {
00329 const string WHOAMI("/whoami");
00330 const string MORE_MONEY("/moremoney");
00331 const string ABILITY_TO_CONTROL_EVERYTHING("/iamgod");
00332 const string ABILITY_TO_CONTROL_ONLY_SELF("/godisdead");
00333 const string PLAYER_LIST("/playerlist");
00334 const string SEND_MONEY("/send");
00335 string lowerCommand(Helper::toLower(command));
00336 stringstream sstr(lowerCommand);
00337 string first;
00338 sstr >> first;
00339 if (lowerCommand == WHOAMI)
00340 {
00341 GameState::messagesReceived().addMessage(lowerCommand + ':' + Helper::serialize(GameState::consolePlayer()->color()));
00342 } else if (lowerCommand == MORE_MONEY)
00343 {
00344 stringstream sstr;
00345 sstr << COMMAND_MORE_MONEY << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG;
00346 net_send(sstr.str());
00347 } else if (lowerCommand == ABILITY_TO_CONTROL_EVERYTHING)
00348 {
00349 GameState::setControlMode(GOD);
00350 GameState::messagesReceived().addMessage("God Mode Turned On");
00351 } else if (lowerCommand == ABILITY_TO_CONTROL_ONLY_SELF)
00352 {
00353 selectedUnits.clear();
00354 selectedCity = 0;
00355 HUD::setSelectedCity(selectedCity = 0);
00356 HUD::setSelectedUnit(0);
00357 GameState::setControlMode(NORMAL);
00358 GameState::messagesReceived().addMessage("God Mode Turned Off");
00359 } else if (lowerCommand == PLAYER_LIST)
00360 {
00361 vector<string> playerList(net_getAllPlayers());
00362 stringstream sstr;
00363 sstr << "Player List:";
00364 for(vector<string>::iterator iter = playerList.begin(); iter != playerList.end(); ++iter)
00365 {
00366 sstr << *iter << ",";
00367 }
00368 GameState::messagesReceived().addMessage(sstr.str());
00369 } else if (first == SEND_MONEY)
00370 {
00371 int amount;
00372 sstr >> amount;
00373 string to;
00374 sstr >> to;
00375 string player;
00376 getline(sstr,player);
00377 player = Helper::eatEarlyWhiteSpace(player);
00378 if (sstr.bad() || to != "to")
00379 {
00380 GameState::messagesReceived().addMessage("Invalid syntax for send money command");
00381 GameState::messagesReceived().addMessage("/send <amount> to <player>");
00382 } else if (playerExists(player))
00383 {
00384 if (GameState::consolePlayer()->bank().balance() >= amount)
00385 {
00386 if (amount < 0)
00387 {
00388 GameState::messagesReceived().addMessage("You cannot send a negative amount of money");
00389 } else
00390 {
00391 GameState::consolePlayer()->bank().withdraw(amount);
00392 stringstream netOut;
00393 netOut << COMMAND_SEND_MONEY << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG << " "
00394 << amount << " " << player;
00395 net_send(netOut.str());
00396 GameState::messagesReceived().addMessage("Money sent");
00397 }
00398 } else
00399 {
00400 GameState::messagesReceived().addMessage("you do not have enough money");
00401 }
00402 } else
00403 {
00404 GameState::messagesReceived().addMessage("player:" + player + " does not exist");
00405 }
00406 } else
00407 {
00408 GameState::messagesReceived().addMessage(lowerCommand + " : is an unknown command");
00409 }
00410 }
00411
00412 void printAllMilitaryUnits(void)
00413 {
00414 sys_console() << "printAllMilitaryUnits begin:" << endl;
00415 for(vector<MilitaryUnit*>::iterator iter = units.begin(); iter != units.end(); ++iter)
00416 {
00417 sys_console() << (*iter)->uniqueID() << endl;
00418 }
00419 sys_console() << "printAllMilitaryUnits End" << endl;
00420 }
00421
00423 void deleteMilitaryUnit(MilitaryUnit* unit)
00424 {
00425 DrawableIter dIter( find(drawableObjects.begin(), drawableObjects.end(), unit) );
00426 assert(dIter != drawableObjects.end());
00427 UnitIter uIter( find(units.begin(), units.end(), unit));
00428 assert(uIter != units.end());
00429 units.erase(uIter);
00430 drawableObjects.erase(dIter);
00431 uIter = find(selectedUnits.begin(), selectedUnits.end(), unit);
00432 if (uIter != selectedUnits.end()) selectedUnits.erase(uIter);
00433 battleCircleAnimation.push_back( BattleSprite(unit->position(), 50, BattleSpriteTypes::EXPLO_LARGE));
00434 delete unit;
00435 }
00436
00438 void deleteCity(CityIter iter)
00439 {
00440 City* tmp(*iter);
00441 cities.erase(iter);
00442 delete tmp;
00443 }
00444
00445
00446
00447 bool addUnitToSelection(MilitaryUnit *u)
00448 {
00449 selectedCity = 0;
00450 HUD::setSelectedCity(selectedCity);
00451 bool exists = false;
00452 for(vector<MilitaryUnit*>::iterator mIter = selectedUnits.begin(); mIter != selectedUnits.end(); ++mIter)
00453 {
00454 if (*mIter == u) exists = true;
00455 }
00456 if (!exists)
00457 {
00458 selectedUnits.push_back(u);
00459 HUD::setSelectedUnit(u);
00460 return true;
00461 }
00462
00463 return false;
00464 }
00465
00466 bool amIInThisBattle(BattleEntry* entry)
00467 {
00468 if (entry->getTeamAColor() == GameState::consolePlayer()->color()) return true;
00469 else if (entry->getTeamBColor() == GameState::consolePlayer()->color()) return true;
00470 else return false;
00471 }
00472
00473 void setSelectedUnits(int key)
00474 {
00475 for(vector<MilitaryUnit*>::iterator iter(GameState::units().begin()); iter != GameState::units().end(); ++iter)
00476 {
00477 if ((*iter)->shortcutKey() == key) (*iter)->setShortcutKey(-1);
00478 }
00479 for(vector<MilitaryUnit*>::iterator iter(selectedUnits.begin()); iter != selectedUnits.end(); ++iter)
00480 {
00481 (*iter)->setShortcutKey(key);
00482 }
00483 }
00484
00485 void getSelectedUnits(int key)
00486 {
00487 selectedCity = 0;
00488 HUD::setSelectedCity(0);
00489 selectedUnits.clear();
00490 for(vector<MilitaryUnit*>::iterator iter(GameState::units().begin()); iter != GameState::units().end(); ++iter)
00491 {
00492 if ((*iter)->shortcutKey() == key) selectedUnits.push_back(*iter);
00493 }
00494 }
00495
00497 void processOverheadInput(void)
00498 {
00499 if (!GameState::battles().empty()) tutorial.overheadWhileBattle();
00500 if (HUD::processOverheadInput()) return;
00501
00502 Vec2D mouse2D( input_getMouseX(), input_getMouseY() );
00503 Vec3D mouse3D( math_translateScreenToWorldPlane( mouse2D, 0.0f) );
00504
00505
00506 Box but1( 0,0, 0.07f,0.04f );
00507
00508 Box but3( 0.161f,0, 0.20f,0.04f);
00509 if( input_isMouseLBClicked() )
00510 {
00511 if( but1.isContain(mouse2D)) { playersNBattleListMode = MODE_PLAYERS_LIST; return; }
00512
00513 if( but3.isContain(mouse2D)) { playersNBattleListMode = MODE_NONE; return; }
00514 }
00515 if( input_isKeyPressed(KeyCodes::key_F1)) { playersNBattleListMode = MODE_PLAYERS_LIST; return; }
00516
00517 if( input_isKeyPressed(KeyCodes::key_F2)) { playersNBattleListMode = MODE_NONE; return; }
00518
00519
00520 camHeight = 10.0f + 180.0f * (1 - input_getMouseWheel());
00521 if( input_getMouseX()<0.01f ) GameState::camTarget().x -= 2.5f;
00522 if( input_getMouseX()>0.98f ) GameState::camTarget().x += 2.5f;
00523 if( input_getMouseY()<0.01f ) GameState::camTarget().y -= 2.5f;
00524 if( input_getMouseY()>0.98f ) GameState::camTarget().y += 2.5f;
00525 if( input_isKeyDown(KeyCodes::key_DOWN ) ) GameState::camTarget().y += 5.5f;
00526 if( input_isKeyDown(KeyCodes::key_UP ) ) GameState::camTarget().y -= 5.5f;
00527 if( input_isKeyDown(KeyCodes::key_LEFT ) ) GameState::camTarget().x -= 5.5f;
00528 if( input_isKeyDown(KeyCodes::key_RIGHT ) ) GameState::camTarget().x += 5.5f;
00529 if (GameState::camTarget().x > 400) GameState::camTarget().x = 400;
00530 if (GameState::camTarget().y > 440) GameState::camTarget().y = 440;
00531 if (GameState::camTarget().x < -400) GameState::camTarget().x = -400;
00532 if (GameState::camTarget().y < -400) GameState::camTarget().y = -400;
00533 camera_set( GameState::camTarget()+Vec3D(0.0f,60.0f+camHeight*0.4f,20.0f+camHeight), GameState::camTarget(), 0 );
00534
00535 if( input_isMouseRBClicked() )
00536 {
00537
00538 if( GameState::worldMap().bounds.contains(Vec2D(mouse3D.x, mouse3D.y)) )
00539 {
00540 if( selectedUnits.size()>0 ) Sound::playRandomSound(Sound::CLASS_ACK);
00541 for(vector<MilitaryUnit*>::iterator iter = selectedUnits.begin(); iter != selectedUnits.end(); ++iter)
00542 {
00543 stringstream sstr;
00544 sstr << COMMAND_OVERHEAD << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG << " " << COMMAND_GOAL << " "
00545 << (*iter)->uniqueID() << " " << serialize(mouse3D);
00546 net_send(sstr.str());
00547 }
00548 if (selectedCity)
00549 {
00550 stringstream sstr;
00551 sstr << COMMAND_OVERHEAD << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG << " " <<
00552 COMMAND_SET_RALLY_POINT << " " << selectedCity->uniqueID() << " " << serialize(mouse3D);
00553 net_send(sstr.str());
00554 }
00555 }
00556 }
00557
00558 Player* plyr = GameState::consolePlayer();
00559 ControlMode controlMode = GameState::controlMode();
00560
00561
00562 if (input_isMouseLBClicked() ) {
00563 if (!input_isKeyDown(KeyCodes::key_LSHIFT) && !input_isKeyDown(KeyCodes::key_RSHIFT))
00564 {
00565 selectedUnits.clear();
00566 }
00567 bool isSelected = false;
00568 for(UnitIter iter = units.begin(); iter != units.end(); ++iter)
00569 {
00570 bool permissionCheck = ((*iter)->color() == plyr->color()) || (controlMode == GOD);
00571 if ((*iter)->contains(mouse3D) && permissionCheck)
00572 {
00573 if( addUnitToSelection(*iter) )
00574 {
00575 isSelected = true;
00576 break;
00577 }
00578 }
00579 }
00580 if(isSelected) Sound::playRandomSound(Sound::CLASS_SELECT);
00581
00582 for(CityIter iter = cities.begin(); iter != cities.end(); ++iter)
00583 {
00584 bool permissionCheck = ((*iter)->color() == plyr->color()) || (controlMode == GOD);
00585 if ((*iter)->contains(mouse2D) && permissionCheck)
00586 {
00587 selectedUnits.clear();
00588 selectedCity = *iter;
00589 HUD::setSelectedCity(selectedCity);
00590 HUD::setSelectedUnit(0);
00591 }
00592 }
00593 }
00594
00595
00596 if( input_isMouseLBDown() && !dragging )
00597 {
00598 dragging = true;
00599 dragCorner = mouse2D;
00600 }
00601 else if( !input_isMouseLBDown() && dragging )
00602 {
00603 dragging = false;
00604 if( math_dist2D(dragCorner,mouse2D) > 0.03f )
00605 {
00606 if (!input_isKeyDown(KeyCodes::key_LSHIFT) && !input_isKeyDown(KeyCodes::key_RSHIFT))
00607 selectedUnits.clear();
00608
00609 Box b;
00610 b.top = min( dragCorner.y, mouse2D.y );
00611 b.bottom = max( dragCorner.y, mouse2D.y );
00612 b.left = min( dragCorner.x, mouse2D.x );
00613 b.right = max( dragCorner.x, mouse2D.x );
00614 bool isSelected = false;
00615 for(UnitIter iter = units.begin(); iter != units.end(); ++iter)
00616 {
00617 bool permissionCheck = ((*iter)->color() == plyr->color()) || (controlMode == GOD);
00618 if( !permissionCheck ) continue;
00619 Vec3D unitPos3D( (*iter)->position() );
00620 Vec2D unitPos2D( math_translateWorldToScreen(unitPos3D) );
00621 if ( b.isContain(unitPos2D) )
00622 {
00623 addUnitToSelection(*iter);
00624 isSelected = true;
00625 }
00626 }
00627 if(isSelected) Sound::playRandomSound(Sound::CLASS_SELECT);
00628 }
00629 }
00630
00631
00632 if (selectedCity)
00633 {
00634 if (input_isKeyPressed(KeyCodes::key_L) )
00635 {
00636 sendBuildMessage( COMMAND_BUILD_LIGHTTANK, selectedCity->uniqueID() );
00637 } else if (input_isKeyPressed(KeyCodes::key_H) ) {
00638 sendBuildMessage( COMMAND_BUILD_HEAVYTANK, selectedCity->uniqueID() );
00639 } else if (input_isKeyPressed(KeyCodes::key_R) ) {
00640 sendBuildMessage( COMMAND_BUILD_ROCKET_LAUNCHER, selectedCity->uniqueID() );
00641 } else if (input_isKeyPressed(KeyCodes::key_A) ) {
00642 sendBuildMessage( COMMAND_BUILD_ARTILLERY, selectedCity->uniqueID() );
00643 } else if (input_isKeyPressed(KeyCodes::key_J) ) {
00644 sendBuildMessage( COMMAND_BUILD_JET, selectedCity->uniqueID() );
00645 }
00646 }
00647
00648 if (input_isMouseLBDblClicked())
00649 {
00650 for(vector<BattleEntry*>::iterator iter = GameState::battles().begin(); iter != GameState::battles().end(); ++iter)
00651 {
00652 if ((*iter)->contains(mouse3D) && amIInThisBattle(*iter))
00653 {
00654 GameState::setActiveBattle(*iter);
00655 HUD::setSelectedCity(NULL);
00656 HUD::setSelectedUnit(NULL);
00657 break;
00658 }
00659 }
00660 }
00661
00662 if (input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL))
00663 {
00664 if (input_isKeyPressed(KeyCodes::key_0)) setSelectedUnits(KeyCodes::key_0);
00665 else if (input_isKeyPressed(KeyCodes::key_1)) setSelectedUnits(KeyCodes::key_1);
00666 else if (input_isKeyPressed(KeyCodes::key_2)) setSelectedUnits(KeyCodes::key_2);
00667 else if (input_isKeyPressed(KeyCodes::key_3)) setSelectedUnits(KeyCodes::key_3);
00668 else if (input_isKeyPressed(KeyCodes::key_4)) setSelectedUnits(KeyCodes::key_4);
00669 else if (input_isKeyPressed(KeyCodes::key_5)) setSelectedUnits(KeyCodes::key_5);
00670 else if (input_isKeyPressed(KeyCodes::key_6)) setSelectedUnits(KeyCodes::key_6);
00671 else if (input_isKeyPressed(KeyCodes::key_7)) setSelectedUnits(KeyCodes::key_7);
00672 else if (input_isKeyPressed(KeyCodes::key_8)) setSelectedUnits(KeyCodes::key_8);
00673 else if (input_isKeyPressed(KeyCodes::key_9)) setSelectedUnits(KeyCodes::key_9);
00674 } else
00675 {
00676 if (input_isKeyPressed(KeyCodes::key_0)) getSelectedUnits(KeyCodes::key_0);
00677 else if (input_isKeyPressed(KeyCodes::key_1)) getSelectedUnits(KeyCodes::key_1);
00678 else if (input_isKeyPressed(KeyCodes::key_2)) getSelectedUnits(KeyCodes::key_2);
00679 else if (input_isKeyPressed(KeyCodes::key_3)) getSelectedUnits(KeyCodes::key_3);
00680 else if (input_isKeyPressed(KeyCodes::key_4)) getSelectedUnits(KeyCodes::key_4);
00681 else if (input_isKeyPressed(KeyCodes::key_5)) getSelectedUnits(KeyCodes::key_5);
00682 else if (input_isKeyPressed(KeyCodes::key_6)) getSelectedUnits(KeyCodes::key_6);
00683 else if (input_isKeyPressed(KeyCodes::key_7)) getSelectedUnits(KeyCodes::key_7);
00684 else if (input_isKeyPressed(KeyCodes::key_8)) getSelectedUnits(KeyCodes::key_8);
00685 else if (input_isKeyPressed(KeyCodes::key_9)) getSelectedUnits(KeyCodes::key_9);
00686 }
00687
00689
00690
00691 }
00692
00694 void processInput(void)
00695 {
00696 if(GameState::activeBattle()) GameState::activeBattle()->input();
00697 else processOverheadInput();
00698 }
00699
00701 void updateUnits(void)
00702 {
00703 for(UnitIter iter = units.begin(); iter != units.end(); ++iter) (*iter)->move();
00704 }
00705
00707 void updateCities(void)
00708 {
00709 for(CityIter iter = cities.begin(); iter != cities.end(); ++iter) {
00710 (*iter)->update();
00711 }
00712 }
00713
00715 void deleteBattleEntry(BattleIter iter)
00716 {
00717 BattleEntry* tmp(*iter);
00718 battles.erase(iter);
00719 delete tmp;
00720 }
00721
00723 void updateBattleEntries(void)
00724 {
00725 bool done = false;
00726 for(BattleIter iter = battles.begin(); iter != battles.end() && !done; ++iter)
00727 {
00728 (*iter)->update();
00729 if((*iter)->isBattleFinished() )
00730 {
00731 if( *iter == GameState::activeBattle() ) GameState::setActiveBattle(0);
00732
00733
00734
00735 for(vector<Int3Tuple>::iterator unitIter = (*iter)->teamAGroups.begin(); unitIter != (*iter)->teamAGroups.end(); ++unitIter)
00736 {
00737 switch (unitIter->a)
00738 {
00739 case UnitTypes::LIGHT_TANK:
00740 GameState::addMilitaryUnit(new LightTank(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00741 GameState::findPlayer((*iter)->getTeamAColor()), unitIter->b));
00742 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00743 break;
00744 case UnitTypes::HEAVY_TANK:
00745 GameState::addMilitaryUnit(new HeavyTank(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00746 GameState::findPlayer((*iter)->getTeamAColor()), unitIter->b ));
00747 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00748 break;
00749 case UnitTypes::LAUNCHER:
00750 GameState::addMilitaryUnit(new RocketLauncher(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00751 GameState::findPlayer((*iter)->getTeamAColor()), unitIter->b));
00752 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00753 break;
00754 case UnitTypes::ARTILLERY:
00755 GameState::addMilitaryUnit(new Artillery(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00756 GameState::findPlayer((*iter)->getTeamAColor()), unitIter->b ));
00757 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00758 break;
00759 case UnitTypes::JET:
00760 {
00761 City* c = GameState::getCity(unitIter->c);
00762 if (c->color() == (*iter)->getTeamAColor())
00763 {
00764 GameState::addMilitaryUnit(new Jet(c->position(),
00765 GameState::findPlayer((*iter)->getTeamAColor()), unitIter->b, unitIter->c));
00766 }
00767 break;
00768 }
00769 default:
00770 sys_console() << "ERROR!!!" << " Programming Error: invalid unit!" << endl;
00771 }
00772 }
00773
00774 for(vector<Int3Tuple>::iterator unitIter = (*iter)->teamBGroups.begin(); unitIter != (*iter)->teamBGroups.end(); ++unitIter)
00775 {
00776 switch (unitIter->a)
00777 {
00778 case UnitTypes::LIGHT_TANK:
00779 GameState::addMilitaryUnit(new LightTank(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00780 GameState::findPlayer((*iter)->getTeamBColor()), unitIter->b));
00781 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00782 break;
00783 case UnitTypes::HEAVY_TANK:
00784 GameState::addMilitaryUnit(new HeavyTank(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00785 GameState::findPlayer((*iter)->getTeamBColor()), unitIter->b ));
00786 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00787 break;
00788 case UnitTypes::LAUNCHER:
00789 GameState::addMilitaryUnit(new RocketLauncher(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00790 GameState::findPlayer((*iter)->getTeamBColor()), unitIter->b));
00791 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00792 break;
00793 case UnitTypes::ARTILLERY:
00794 GameState::addMilitaryUnit(new Artillery(Vec3D((*iter)->getBattleLocation().x,(*iter)->getBattleLocation().y,0.0f),
00795 GameState::findPlayer((*iter)->getTeamBColor()), unitIter->b ));
00796 (*GameState::units().rbegin())->setShortcutKey(unitIter->c);
00797 break;
00798 case UnitTypes::JET:
00799 {
00800 City* c = GameState::getCity(unitIter->c);
00801 if (c->color() == (*iter)->getTeamBColor())
00802 {
00803 GameState::addMilitaryUnit(new Jet(c->position(),
00804 GameState::findPlayer((*iter)->getTeamBColor()), unitIter->b, unitIter->c));
00805 }
00806 break;
00807 }
00808 default:
00809 sys_console() << "ERROR!!!" << " Programming Error: invalid unit!" << endl;
00810 }
00811 }
00812
00813 deleteBattleEntry(iter);
00814 done = true;
00815 }
00816 }
00817
00818 }
00819
00821 void updatePlayers()
00822 {
00823 for(PlayerIter iter=players.begin(); iter != players.end(); ++iter) (*iter)->update();
00824 }
00825
00827 void deletePlayer(PlayerIter iter)
00828 {
00829 Player* tmp(*iter);
00830 players.erase(iter);
00831 delete tmp;
00832 }
00833
00834
00835
00836 vector<MilitaryUnit*> getSurroundingUnits(MilitaryUnit* unit)
00837 {
00838 vector<MilitaryUnit*> result;
00839 result.push_back(unit);
00840 int numGrounds = 1;
00841 int numJets = 0;
00842 for(UnitIter unitIter(GameState::units().begin()); unitIter != GameState::units().end(); ++unitIter)
00843 {
00844 if (unit->color() != (*unitIter)->color() || unit == *unitIter) continue;
00845 if((*unitIter)->unitType()==UnitTypes::JET )
00846 {
00847 if( math_distPlanar3D(unit->position(), (*unitIter)->position()) >= 300.0f ) continue;
00848 if( numJets >= 4 ) continue;
00849 numJets++;
00850 result.push_back(*unitIter);
00851 }
00852 else
00853 {
00854 if( math_distPlanar3D(unit->position(), (*unitIter)->position()) >= 100.0f ) continue;
00855 if( numGrounds >= 8 ) continue;
00856 numGrounds++;
00857 result.push_back(*unitIter);
00858 }
00859 }
00860 return result;
00861 }
00862
00866 void doCollisionDetection(void)
00867 {
00868 bool done = false;
00869 for(UnitIter iter(units.begin()); iter != units.end() && !done; ++iter)
00870 {
00871
00872 for(UnitIter secondIter(iter+1); secondIter < units.end() && !done; ++secondIter)
00873 {
00874 assert(iter != secondIter && "Programming Error");
00875 if ((*iter)->fightingCollision(*secondIter) && (*iter)->color() != (*secondIter)->color()
00876 && (*iter)->unitType()!=UnitTypes::JET && (*secondIter)->unitType()!=UnitTypes::JET )
00877 {
00878 vector<MilitaryUnit*> teamA(getSurroundingUnits(*iter));
00879 vector<MilitaryUnit*> teamB(getSurroundingUnits(*secondIter));
00880 battles.push_back(new BattleEntry( (*teamA.begin())->color(), (*teamB.begin())->color(),
00881 Vec2D(((*teamA.begin())->position().x+(*teamB.begin())->position().x)/2,
00882 ((*teamA.begin())->position().y+(*teamB.begin())->position().y)/2) ));
00883 for(UnitIter unitIter(teamA.begin()); unitIter != teamA.end(); ++unitIter)
00884 {
00885 int cityID = 0;
00886 if( (*unitIter)->unitType()==UnitTypes::JET ) cityID = ((Jet*)(*unitIter))->getCityID();
00887 else cityID = (*unitIter)->shortcutKey();
00888 (*battles.rbegin())->teamAGroups.push_back( Int3Tuple( (*unitIter)->unitType(), (*unitIter)->armySize(), cityID ) );
00889 deleteMilitaryUnit(*unitIter);
00890 }
00891 for(UnitIter unitIter(teamB.begin()); unitIter != teamB.end(); ++unitIter)
00892 {
00893 int cityID = 0;
00894 if( (*unitIter)->unitType()==UnitTypes::JET ) cityID = ((Jet*)(*unitIter))->getCityID();
00895 else cityID = (*unitIter)->shortcutKey();
00896 (*battles.rbegin())->teamBGroups.push_back( Int3Tuple( (*unitIter)->unitType(), (*unitIter)->armySize(), cityID ) );
00897 deleteMilitaryUnit(*unitIter);
00898 }
00899 selectedUnits.clear();
00900 HUD::clearSelections();
00901
00902 if( (*battles.rbegin())->isFoughtBy(GameState::consolePlayer()->color()))
00903 {
00904 if (GameState::activeBattle() == 0) GameState::setActiveBattle( *battles.rbegin() );
00905 else
00906 {
00907 stringstream sstr;
00908 sstr << "You just entered another battle with ";
00909 if ( (*battles.rbegin())->getTeamAColor() != GameState::consolePlayer()->color())
00910 {
00911 sstr << Helper::playerColorToPlayerName((*battles.rbegin())->getTeamAColor());
00912 } else sstr << Helper::playerColorToPlayerName((*battles.rbegin())->getTeamBColor());
00913 GameState::messagesReceived().addMessage(sstr.str());
00914 static counter = 5;
00915 if (--counter > 0) GameState::messagesReceived().addMessage("Press space to go to this battle");
00916 Sound::play(Sound::MSG_ANOTHER_BATTLE_IS_HAPPENING, 1.0f);
00917 }
00918 }
00919 done = true;
00920 }
00921 }
00922
00923 for(CityIter cityIter(cities.begin()); cityIter < cities.end() && !done; ++cityIter)
00924 {
00925 if((*cityIter)->color() != (*iter)->color() && (*cityIter)->collision(*iter) && (*iter)->unitType() != UnitTypes::JET)
00926 {
00927 (*cityIter)->changeOwner( (*iter)->owner(), true );
00928 done = true;
00929 }
00930 }
00931 }
00932 }
00933
00936 void doAI()
00937 {
00938
00939 }
00940
00944 void loadMap(string &file)
00945 {
00946 ifstream inFile(file.data());
00947 if(!inFile) throw Error(string("Map not found: ")+file);
00948
00949 while(!inFile.eof())
00950 {
00951 string line;
00952 getline(inFile, line);
00953 if( line.find(Map::TOK_COMMENT) != string::npos ) { }
00954 else if( line.find(Map::TOK_MAP_DIMS) != string::npos)
00955 {
00956 Map::WorldMap wm = Map::createWorldMap(line.substr(Map::TOK_MAP_DIMS.size()));
00957 GameState::setWorldMap(wm);
00958 HUD::setWorldMap(wm);
00959 }
00960 else if( line.find(Map::TOK_CREATE_UNIT) != string::npos )
00961 GameState::addMilitaryUnit(Map::createUnit(line.substr(Map::TOK_CREATE_UNIT.size())));
00962 else if( line.find(Map::TOK_CREATE_CITY) != string::npos )
00963 GameState::addCity(Map::createCity(line.substr(Map::TOK_CREATE_CITY.size())));
00964 }
00965 }
00966
00967 string& stripComments(string& str)
00968 {
00969 size_t start;
00970 size_t end;
00971 while( (start = str.find("//")) != string::npos )
00972 {
00973 end = str.find("\n", start)+1;
00974 str.erase(start, end-start);
00975 }
00976 return str;
00977 }
00978
00979 void initData()
00980 {
00981 ifstream fileIn("data.txt");
00982 if(!fileIn) throw Error("Cannot open data file: data.txt");
00983
00984 ostringstream fileDump;
00985
00986 fileDump << fileIn.rdbuf();
00987 string file = stripComments(fileDump.str());
00988
00989 size_t start = file.find(EconData::TOK_BEGIN_DATA)+EconData::TOK_BEGIN_DATA.size();
00990 size_t len = file.find(EconData::TOK_END_DATA) - start;
00991 EconData::getObj().initData(istringstream(file.substr(start, len)));
00992
00993 start = file.find(BattleUnitData::TOK_BEGIN_DATA)+BattleUnitData::TOK_BEGIN_DATA.size();
00994 len = file.find(BattleUnitData::TOK_END_DATA) - start;
00995 BattleUnitData::getObj().initData(istringstream(file.substr(start, len)));
00996 }
00997
00998 void initHUD()
00999 {
01000 ifstream fileIn("HUD.txt");
01001 if(!fileIn) throw Error("Cannot open HUD init file: HUD.txt");
01002 ostringstream fileDump;
01003
01004 fileDump << fileIn.rdbuf();
01005 string file = stripComments(fileDump.str());
01006 HUD::init(istringstream(file));
01007 }
01008
01010 void overhead_init()
01011 {
01012 GameConfig gc("config.txt");
01013
01014 sys_console() << "atan(1,0): " << atan2f(1.0f, 0.0f) << endl;
01015 sys_console() << "atan(0,1): " << atan2f(0.0f, 1.0f) << endl;
01016 sys_console() << "atan(-1,0): " << atan2f(-1.0f, 0.0f) << endl;
01017 sys_console() << "atan(0,-1): " << atan2f(0.0f, -1.0f) << endl;
01018
01019 initData();
01020 initHUD();
01021
01022 loadMap(gc.mapFileName);
01023
01024 creditTimer = -1;
01025 youWin = youLose = false;
01026 showConfirmQuitMenu = false;
01027
01028 City* pPlayerCity = 0;
01029
01030 Vec3D colors[8] = {Colors::red, Colors::blue, Colors::green, Colors::yellow,
01031 Colors::cyan, Colors::white, Colors::black, Colors::magenta};
01032
01033 int consolePlayerNum = net_getPlayerNumber();
01034 if( consolePlayerNum == -1 )
01035 {
01036
01037 Player* p = new Player(Colors::blue, gc.initPlayerBalance, units, cities);
01038 GameState::setConsolePlayer(p);
01039 players.push_back(p);
01040 HUD::setPlayer(p);
01041 pPlayerCity = cities[0];
01042
01043 cities[0]->changeOwner(p);
01044
01045 p = new Player(Colors::red, gc.initPlayerBalance, units, cities);
01046 players.push_back(p);
01047 cities[1]->changeOwner(p);
01048 p = new Player(Colors::green, gc.initPlayerBalance, units, cities);
01049 players.push_back(p);
01050 cities[2]->changeOwner(p);
01051 GameState::setControlMode(GOD);
01052 GameState::messagesReceived().addMessage("God Mode Turned On");
01053 }
01054 else
01055 {
01056
01057 vector<string> &names = net_getAllPlayers();
01058 players.resize( names.size() );
01059 for(size_t i = 0; i < names.size(); ++i)
01060 {
01061 if(i == consolePlayerNum )
01062 {
01063 Player* p = new Player(colors[consolePlayerNum], gc.initPlayerBalance, units, cities);
01064 GameState::setConsolePlayer(p);
01065 players[consolePlayerNum] = p;
01066 HUD::setPlayer(p);
01067 pPlayerCity = cities[i];
01068 }
01069 else
01070 {
01071 int playerNum = net_getPlayerNumUsingName(names[i]);
01072 Vec3D playerColor( colors[playerNum] );
01073 players[playerNum] = new Player(playerColor, gc.initPlayerBalance, units, cities);
01074 }
01075 }
01076 for(size_t i = 0; i < names.size(); ++i)
01077 GameState::cities()[i]->changeOwner(players[i]);
01078
01079 for( UINT i=0; i<GameState::cities().size(); i++ )
01080 {
01081 if( GameState::cities()[i]->owner() )
01082 {
01083 Vec3D c = GameState::cities()[i]->owner()->color();
01084 sys_console() << "City #" << i << " " << c.x << " " << c.y << " " << c.z << endl;
01085 }
01086 }
01087
01088 }
01089
01090 selectedUnits.clear();
01091
01092 Sound::playMusic(Sound::SMPL_SONG_WAR_WORLDS);
01093
01094 camHeight = 100.0f;
01095
01096 GameState::camTarget().x = pPlayerCity->position().x;
01097 GameState::camTarget().y = pPlayerCity->position().y;
01098 dragging = false;
01099
01100 transitionTimeRemaining = -1;
01101 prevBattle = NULL;
01102
01103 unitMaintenance.setHelpString("Unit Maintenance Cost:\n 0-14 100% Income\n15-24 50% Income\n25+ 10% Income");
01104 GameState::availableRFM().resize(5);
01105
01106 playersNBattleListMode = MODE_PLAYERS_LIST;
01107 }
01108
01110 void overhead_shutdown()
01111 {
01112
01113
01114 while(!units.empty()) deleteMilitaryUnit(*units.begin());
01115 while(!cities.empty()) deleteCity(cities.begin());
01116 while(!battles.empty()) deleteBattleEntry(battles.begin());
01117 delete Globals::artWork;
01118 while(!players.empty()) deletePlayer(players.begin());
01119
01120 Sound::shutdown();
01121 EconData::getObj().shutdown();
01122 BattleUnitData::getObj().shutdown();
01123 HUD::shutdown();
01124 }
01125
01129 void overhead_update()
01130 {
01131 if (currGameTick % 100 == 0)
01132 {
01133 sys_console() << "currGameTick:" << currGameTick << endl;
01134 }
01135
01136
01137 updateCredit();
01138
01139
01140 if( input_isKeyPressed(KeyCodes::key_ESCAPE) ) showConfirmQuitMenu = !showConfirmQuitMenu;
01141 if( showConfirmQuitMenu && input_isMouseLBClicked() )
01142 {
01143 Vec2D mousePos( input_getMouseX(), input_getMouseY() );
01144 Box yes( 0.320f, 0.305f, 0.480f, 0.368f );
01145 Box no ( 0.514f, 0.305f, 0.654f, 0.368f );
01146 if( yes.isContain(mousePos) ) sys_terminate();
01147 if( no .isContain(mousePos) ) showConfirmQuitMenu = false;
01148 }
01149
01150 if (input_isKeyPressed(KeyCodes::key_P)) printAllMilitaryUnits();
01151 if (input_isKeyPressed(KeyCodes::key_Q)) tutorial.stopTutorial();
01152 if (input_isKeyPressed(KeyCodes::key_R))
01153 {
01154 sendMessageToPrintARandomNumberToTheConsole();
01155 }
01156 if (input_isKeyPressed(KeyCodes::key_RETURN) && chatBoxOn)
01157 {
01158 if (*chatBox.getString().begin() == '/')
01159 {
01160 processCommand(chatBox.getString());
01161 } else if( chatBox.getString().length() > 0 )
01162 {
01163 stringstream sstr;
01164 sstr << COMMAND_TEXT_MESSAGE << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG << " "
01165 << net_getPlayerName() << " says \"" << chatBox.getString() << "\"";
01166 net_send(sstr.str());
01167 }
01168 chatBox.clear();
01169 }
01170 receiveNetworkData();
01171 static int waitingPrintout(0);
01172 const int WAITING_MESSAGE_TRIGGER_POINT(30);
01173 if (!hasNetworkDataForCurrentTickBeenReceived())
01174 {
01175 if (waitingPrintout++ == WAITING_MESSAGE_TRIGGER_POINT)
01176 {
01177 stringstream sstr;
01178 sstr << "Waiting for other player, current game time is " << currGameTick;
01179 GameState::messagesReceived().addMessage(sstr.str());
01180 }
01181 return;
01182 } else if (waitingPrintout > WAITING_MESSAGE_TRIGGER_POINT)
01183 {
01184 GameState::messagesReceived().addMessage("Waiting complete, resuming game");
01185 }
01186 waitingPrintout = 0;
01187
01188 ++currGameTick;
01189
01190 Overhead::tutorial.update();
01191 tutorial.intro();
01192 HUD::update();
01193 processNetworkData();
01194 processInput();
01195 doAI();
01196 doTutorial();
01197 updateUnits();
01198 updateCities();
01199 updateBattleEntries();
01200 updatePlayers();
01201 doCollisionDetection();
01202 if (!chatBoxOn && GameState::activeBattle() != 0 && input_isKeyPressed(KeyCodes::key_SPACE))
01203 {
01204 for(vector<BattleEntry*>::reverse_iterator iter = battles.rbegin(); iter != battles.rend(); ++iter)
01205 {
01206 if ((*iter)->isFoughtBy(GameState::consolePlayer()->color()))
01207 {
01208 GameState::setActiveBattle(*battles.rbegin());
01209 GameState::messagesReceived().addMessage("Just changed to newest battle");
01210 break;
01211 }
01212 }
01213 }
01214 if (chatBoxOn && !input_isKeyPressed(KeyCodes::key_LCONTROL) && !input_isKeyPressed(KeyCodes::key_RCONTROL))
01215 {
01216 chatBox.input();
01217 }
01218 if (input_isKeyPressed(KeyCodes::key_RETURN)) chatBoxOn = !chatBoxOn;
01219 if (currGameTick % Globals::NETWORK_SYNC_RATE == 0)
01220 {
01221 stringstream sstr;
01222 sstr << COMMAND_SYNC << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG;
01223 net_send(sstr.str());
01224 }
01225 const int OUT_OF_SYNC_INTERNAL_CHECK_FREQ(60 * 30);
01226 if (currGameTick % OUT_OF_SYNC_INTERNAL_CHECK_FREQ == 0 && net_amIServer())
01227 {
01228 askForRandomNumbers();
01229 }
01230 const int PRINT_OUT_OF_SYNC_DEBUG_INFO_INTERNAL_CHECK(60 * 300);
01231 if (currGameTick % PRINT_OUT_OF_SYNC_DEBUG_INFO_INTERNAL_CHECK == 0 && net_amIServer())
01232 {
01233 sendMessageToPrintARandomNumberToTheConsole();
01234 printAllMilitaryUnits();
01235 }
01236 if (currGameTick % MESSAGE_DISPLAY_LENGTH == 0)
01237 {
01238 doVictoryTest();
01239 }
01240
01241 if( GameState::activeBattle()!=prevBattle )
01242 {
01243 if( transitionTimeRemaining==-1 )
01244 {
01245 transitionTimeRemaining = TRANSITION_TIME;
01246 }
01247 else if( transitionTimeRemaining==0 )
01248 {
01249 transitionTimeRemaining = -1;
01250 prevBattle = GameState::activeBattle();
01251 }
01252 else
01253 {
01254 transitionTimeRemaining--;
01255 }
01256 }
01257
01258
01259 if( GameState::activeBattle() )
01260 {
01261 Vec3D newTarget( GameState::activeBattle()->getBattleLocation().x,
01262 GameState::activeBattle()->getBattleLocation().y,
01263 0.0f );
01264 GameState::camTarget() = GameState::camTarget()*0.9f + newTarget*0.1f;
01265 }
01266
01267
01268 for( int i=0; i<UnitTypes::COUNT; i++ ) GameState::availableRFM()[i] = 0;
01269 if( GameState::activeBattle() )
01270 {
01271 Vec2D battlePos = GameState::activeBattle()->getBattleLocation();
01272 for( UnitIter iter(GameState::units().begin()); iter!=GameState::units().end(); iter++ )
01273 if( (*iter)->color()==GameState::consolePlayer()->color() )
01274 {
01275 Vec2D unitPos( (*iter)->position().x, (*iter)->position().y );
01276 if( math_dist2D(battlePos,unitPos) <= 100.0f )
01277 GameState::availableRFM()[ (*iter)->unitType() ]++;
01278 }
01279 }
01280 static bool maxMoneyMessage = false;
01281 if (!maxMoneyMessage && (currGameTick % 200))
01282 {
01283 if (GameState::consolePlayer()->bank().balance() == MAX_MONEY)
01284 {
01285 maxMoneyMessage = true;
01286 GameState::messagesReceived().addMessage("$10,000 max money limit reached");
01287 }
01288 }
01289 }
01290
01292 void overheadRender()
01293 {
01294 for(DrawableIter iter = drawableObjects.begin(); iter != drawableObjects.end(); ++iter) (*iter)->draw();
01295 for(vector<MilitaryUnit*>::iterator iter = selectedUnits.begin(); iter != selectedUnits.end(); ++iter)
01296 {
01297 (*iter)->drawBox();
01298 }
01299 if (selectedCity) selectedCity->drawSelectBox();
01300
01301 terrain_render( artWork->worldMap, artWork->terrainTexLow, artWork->terrainTexHigh, artWork->terrainTexNormal );
01302
01303 bool found = false;
01304 Vec2D foundMiddle;
01305 FLOAT foundDist;
01306 Vec2D foundFrom;
01307 Vec2D foundTo;
01308 for(UnitIter iter(units.begin()); iter != units.end(); ++iter)
01309 {
01310 for(UnitIter secondIter(iter+1); secondIter < units.end(); ++secondIter)
01311 {
01312 assert(iter != secondIter && "Programming Error");
01313 if ((*iter)->nearEachOther(*secondIter) && (*iter)->color() != (*secondIter)->color())
01314 {
01315 Vec2D from(math_translateWorldToScreen((*iter)->position()));
01316 Vec2D to(math_translateWorldToScreen((*secondIter)->position()));
01317 Vec2D middle((from.x + to.x) / 2, (from.y + to.y) / 2);
01318 FLOAT dist(math_dist3D((*iter)->position(),(*secondIter)->position()));
01319 if (!found || dist < foundDist)
01320 {
01321 found = true;
01322 foundDist = dist;
01323 foundMiddle = middle;
01324 foundFrom = from;
01325 foundTo = to;
01326 }
01327 }
01328 }
01329 }
01330 if (found)
01331 {
01332 mesh_render(Globals::artWork->thinCircle, math_translateScreenToWorldPlane(foundMiddle, BATTLE_CIRCLE_HEIGHT),
01333 Vec3D(BATTLE_RADIUS,BATTLE_RADIUS,1.0f), Vec3D(0,0,0), artWork->colorRed);
01334 overlay_line(foundFrom, foundTo, Colors::red, BlendModes::NONE, 1.0f, 0, 1);
01335 tutorial.battleCircle();
01336 }
01337
01338 for(vector<BattleEntry*>::iterator iter(GameState::battles().begin()); iter != GameState::battles().end(); ++iter)
01339 {
01340 if ((*iter)->isFoughtBy(GameState::consolePlayer()->color()))
01341 {
01342 mesh_render(Globals::artWork->thinCircle, Vec3D((*iter)->getBattleLocation().x, (*iter)->getBattleLocation().y,
01343 BATTLE_CIRCLE_HEIGHT), Vec3D(BATTLE_RADIUS,BATTLE_RADIUS,1.0f), Vec3D(0,0,0), artWork->colorRed);
01344 } else
01345 {
01346 mesh_render(Globals::artWork->thinCircle, Vec3D((*iter)->getBattleLocation().x, (*iter)->getBattleLocation().y,
01347 BATTLE_CIRCLE_HEIGHT), Vec3D(BATTLE_RADIUS,BATTLE_RADIUS,1.0f), Vec3D(0,0,0), artWork->colorBlue);
01348 }
01349 if (sys_localRandInt() % 5 == 0)
01350 {
01351 FLOAT dist(sys_localRandFloat() * BATTLE_RADIUS / 2.5f);
01352 FLOAT angle(sys_localRandFloat() * 2.0f * 3.1415f);
01353 FLOAT height((sys_localRandFloat() * 0.5f + 0.5f) * BATTLE_CIRCLE_HEIGHT);
01354 FLOAT x((*iter)->getBattleLocation().x + dist * cosf(angle));
01355 FLOAT y((*iter)->getBattleLocation().y + dist * sinf(angle));
01356 Vec3D location(Vec3D(x, y, height));
01357 int type(sys_localRandInt() % 3);
01358 int MAX_LENGTH(50);
01359 battleCircleAnimation.push_back( BattleSprite(location , MAX_LENGTH, type));
01360 }
01361 Vec2D location(math_translateWorldToScreen(Vec3D((*iter)->getBattleLocation().x - BATTLE_RADIUS / 3.0f,
01362 (*iter)->getBattleLocation().y - BATTLE_RADIUS / 4.0f, BATTLE_CIRCLE_HEIGHT)));
01363 FLOAT scale(0.8f);
01364 Helper::printPlayerNameToScreen((*iter)->getTeamAColor(), location, scale);
01365 overlay_text() << " vs." << endl;
01366 overlay_textOut(location + Vec2D(0, 0.015f), scale , Colors::yellow);
01367 Helper::printPlayerNameToScreen((*iter)->getTeamBColor(), location + Vec2D(0, 0.03f), scale);
01368 }
01369 updateParticleList(battleCircleAnimation);
01370 renderParticleList(battleCircleAnimation);
01371
01372 for(vector<MilitaryUnit*>::iterator iter(selectedUnits.begin()); iter != selectedUnits.end(); ++iter)
01373 {
01374 if ((*iter)->isMoving())
01375 {
01376 Vec2D goal(math_translateWorldToScreen((*iter)->goalPosition()));
01377 overlay_line(math_translateWorldToScreen((*iter)->position()), goal,
01378 Colors::green);
01379 overlay_point(goal, 1.0f, Colors::red);
01380 }
01381 }
01382
01383 int totalUnits(Helper::totalUnitsForPlayer(GameState::consolePlayer()->color()));
01384 Vec3D unitTextColor;
01385 if (totalUnits < 15) unitTextColor = Colors::green;
01386 else if (totalUnits < 25) unitTextColor = Colors::yellow;
01387 else unitTextColor = Colors::red;
01388 overlay_text() << "Units: " << totalUnits;
01389 overlay_textOut(Vec2D(0.65f,0.81f), 1.0f, unitTextColor);
01390 unitMaintenance.drawHelpString();
01391
01392
01393 overlay_image( artWork->playersNBattlesListTex, Vec2D(0.1f,0.02f), Vec2D(0.2f,0.04f),
01394 BlendModes::NONE, 1.0f, 6 );
01395 if( playersNBattleListMode==MODE_PLAYERS_LIST ) printPlayerList();
01396
01397 Icon list1( Vec2D(0,0), Vec2D(0.07f,0.04f), NULL );
01398
01399 Icon list3( Vec2D(0.161f,0), Vec2D(0.20f,0.04f), NULL );
01400 list1.setHelpString( "List all players (Colored)\nand their total strength\nHot Key[F1]" );
01401
01402 list3.setHelpString( "Closes this Window\nHot Key[F2]" );
01403 Vec2D mousePos( input_getMouseX(), input_getMouseY() );
01404 if( list1.contains(mousePos) ) list1.drawOutline( Colors::yellow );
01405
01406 if( list3.contains(mousePos) ) list3.drawOutline( Colors::yellow );
01407 list1.drawHelpString();
01408
01409 list3.drawHelpString();
01410
01411
01412
01413 FLOAT x = input_getMouseX(), y = input_getMouseY();
01414 overlay_image( Globals::artWork->mouse, Vec2D(x+0.025f,y+0.025f), Vec2D(0.05f,0.05f), BlendModes::KEY, 1.0f, MOUSE_RENDER_PRIORITY );
01415
01416
01417 if( dragging ) overlay_rect( dragCorner, Vec2D(x,y), false, Colors::green );
01418 }
01419
01421 void renderThreatMap()
01422 {
01423
01424
01425
01426
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467 }
01468
01473 void overhead_render()
01474 {
01475 #if 0
01476 if (currGameTick > 1 && currGameTick <= 8800) sys_fastForwardUpdate(120);
01477 #endif
01478
01479 if( creditTimer>0 ) renderCredit();
01480
01481
01482 if( showConfirmQuitMenu )
01483 {
01484 overlay_image( artWork->confirmQuit, Vec2D(0.5f,0.3f), Vec2D(0.5f,0.2f), BlendModes::NONE, 1.0f, 8 );
01485 Vec2D mousePos( input_getMouseX(), input_getMouseY() );
01486 Box yes( 0.320f, 0.305f, 0.480f, 0.368f );
01487 Box no ( 0.514f, 0.305f, 0.654f, 0.368f );
01488 if( yes.isContain(mousePos) ) overlay_rect( Vec2D(yes.left,yes.top), Vec2D(yes.right,yes.bottom), false, Colors::yellow, BlendModes::NONE, 1.0f, 8 );
01489 if( no .isContain(mousePos) ) overlay_rect( Vec2D(no .left,no .top), Vec2D(no .right,no .bottom), false, Colors::yellow, BlendModes::NONE, 1.0f, 8 );
01490 }
01491
01492
01493 if( youWin && creditTimer < 300 )
01494 overlay_image( artWork->youWinTex, Vec2D(0.5f,0.5f), Vec2D(0.9f,0.25f), BlendModes::KEY, 1.0f, 7 );
01495 if( youLose && creditTimer < 300 )
01496 overlay_image( artWork->youLoseTex, Vec2D(0.5f,0.5f), Vec2D(0.7f,0.25f), BlendModes::KEY, 1.0f, 7 );
01497
01498 if( transitionTimeRemaining!=-1 )
01499 {
01500 float trans = transitionTimeRemaining*1.0f/TRANSITION_TIME;
01501
01502 if( prevBattle==NULL )
01503 {
01504 overheadRender();
01505 Vec3D camTarget( GameState::camTarget() );
01506 Vec3D camPos( camTarget+Vec3D(0.0f,60.0f+camHeight*0.4f,20.0f+camHeight) );
01507 camera_set( camTarget+(camPos-camTarget)*(trans*0.9f+0.1f), camTarget, 0 );
01508 }
01509 else if( GameState::activeBattle()==NULL )
01510 {
01511 overheadRender();
01512 Vec3D camTarget( GameState::camTarget() );
01513 Vec3D camPos( camTarget+Vec3D(0.0f,60.0f+camHeight*0.4f,20.0f+camHeight) );
01514 camera_set( camTarget+(camPos-camTarget)*((1.0f-trans)*0.9f+0.1f), camTarget, 0 );
01515 }
01516 else
01517 {
01518 }
01519 }
01520 else
01521 {
01522 if(GameState::activeBattle()) GameState::activeBattle()->render();
01523 else overheadRender();
01524 }
01525
01526 if( showThreatMap ) renderThreatMap();
01527 GameState::messagesReceived().print();
01528 if (chatBoxOn)
01529 {
01530 overlay_text() << chatBox.getString();
01531 const Vec2D TEXT_BOX_LOCATION(0.205f,0.77f);
01532 const float TEXT_BOX_TEXT_SIZE(1.0f);
01533 const Vec3D TEXT_BOX_COLOR(Colors::green);
01534 const int TEXT_BOX_CURSOR_SPEED(30);
01535 if ((currGameTick / TEXT_BOX_CURSOR_SPEED) % 2 == 0) overlay_text() << '_';
01536 overlay_textOut(TEXT_BOX_LOCATION, TEXT_BOX_TEXT_SIZE, TEXT_BOX_COLOR);
01537 }
01538 HUD::render();
01539 }
01540
01541 }