00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "HUD.h"
00023 #include "GameState.h"
00024 #include "Globals.h"
00025 #include "EconData.h"
00026 #include "Map.h"
00027 #include "HelperFunctions.h"
00028 #include "Sound.h"
00029
00030 using namespace NetworkMessages;
00031 using namespace Globals;
00032
00033 const Vec3D HUD::COLOR_INACTIVE_BATTLE(0.792f, 0.741f, 0.768f);
00034 const Vec3D HUD::COLOR_CITY_OUTLINE(0.83f, 0.88f, 0.69f);
00035
00036 void HUD::init(istream& in)
00037 {
00038 HUD& h = HUD::getObj();
00039
00040 in >> h.m_startX;
00041 in >> h.m_startY;
00042 in >> h.m_endX;
00043 in >> h.m_endY;
00044
00045 float delta;
00046
00047 in >> h.m_mapBorderX1;
00048 h.m_mapBorderX1 += h.m_startX;
00049 in >> h.m_mapBorderY1;
00050 h.m_mapBorderY1 += h.m_startY;
00051 in >> delta;
00052 h.m_mapBorderX2 = h.m_mapBorderX1+delta;
00053 in >> delta;
00054 h.m_mapBorderY2 = h.m_mapBorderY1+delta;
00055
00056 in >> delta;
00057 h.m_mapDims[0].x = h.m_mapBorderX1+delta;
00058 h.m_mapDims[0].y = h.m_mapBorderY1+delta;
00059 h.m_mapDims[1].x = h.m_mapBorderX2-delta;
00060 h.m_mapDims[1].y = h.m_mapBorderY2-delta;
00061 h.m_miniMapBounds.setBounds(h.m_mapDims[0], h.m_mapDims[1]);
00062 in >> h.m_mapCityOutlineSize >> h.m_mapCitySize;
00063 in >> h.m_mapUnitSize;
00064
00065
00066 in >> h.m_infoBorderX1;
00067 h.m_infoBorderX1 += h.m_startX;
00068 in >> h.m_infoBorderY1;
00069 h.m_infoBorderY1 += h.m_startY;
00070 in >> delta;
00071 h.m_infoBorderX2 = h.m_infoBorderX1+delta;
00072 in >> delta;
00073 h.m_infoBorderY2 = h.m_infoBorderY1+delta;
00074
00075
00076 in >> delta;
00077 h.m_infoPortraitCenter.x = h.m_infoBorderX1 + delta;
00078 in >> delta;
00079 h.m_infoPortraitCenter.y = h.m_infoBorderY1 + delta;
00080 in >> h.m_infoPortraitSize.x >> h.m_infoPortraitSize.y;
00081
00082
00083 in >> h.m_buildQIconSize.x >> h.m_buildQIconSize.y;
00084 float cX, cY, offset;
00085
00086 in >> cX >> cY >> offset;
00087 cX += h.m_infoBorderX1;
00088 cY += h.m_infoBorderY1;
00089 for(int i=0; i < 3; ++i)
00090 {
00091 for(int j=0; j < 3; ++j)
00092 {
00093 int index = i*3+j;
00094 h.m_buildQIconCoords[index].x = cX + j*offset;
00095 h.m_buildQIconCoords[index].y = cY + i*offset;
00096 }
00097 }
00098
00099 in >> delta;
00100 h.m_buildQTimerCoords.x = h.m_infoBorderX1 + delta;
00101 in >> delta;
00102 h.m_buildQTimerCoords.y = h.m_infoBorderY1 + delta;
00103
00104 in >> h.m_buildQTimerTextSize;
00105
00106 string color;
00107 in >> color;
00108 h.m_buildQTimerTextColor = Map::getColorVec3D(color);
00109
00110
00111
00112 in >> h.m_moneyBorderX1;
00113 h.m_moneyBorderX1 += h.m_startX;
00114 in >> h.m_moneyBorderY1;
00115 h.m_moneyBorderY1 += h.m_startY;
00116 in >> delta;
00117 h.m_moneyBorderX2 = h.m_moneyBorderX1+delta;
00118 in >> delta;
00119 h.m_moneyBorderY2 = h.m_moneyBorderY1+delta;
00120 in >> h.m_moneyTextX;
00121 h.m_moneyTextX += h.m_startX;
00122 in >> h.m_moneyTextY;
00123 h.m_moneyTextY += h.m_startY;
00124 in >> h.m_moneyTextSize;
00125 in >> color;
00126 h.m_moneyTextColor = Map::getColorVec3D(color);
00127
00128
00129 in >> h.m_actionsBorderStart.x >> h.m_actionsBorderStart.y;
00130 h.m_actionsBorderStart.x += h.m_startX;
00131 h.m_actionsBorderStart.y += h.m_startY;
00132 in >> h.m_actionsBorderEnd.x >> h.m_actionsBorderEnd.y;
00133 h.m_actionsBorderEnd.x += h.m_startX;
00134 h.m_actionsBorderEnd.y += h.m_startY;
00135
00136
00137 in >> h.m_mapBorderStart.x >> h.m_mapBorderStart.y;
00138 h.m_mapBorderStart.x += h.m_startX;
00139 h.m_mapBorderStart.y += h.m_startY;
00140 in >> h.m_mapBorderEnd.x >> h.m_mapBorderEnd.y;
00141 h.m_mapBorderEnd.x += h.m_startX;
00142 h.m_mapBorderEnd.y += h.m_startY;
00143
00144
00145 in >> h.m_infoBorderStart.x >> h.m_infoBorderStart.y;
00146 h.m_infoBorderStart.x += h.m_startX;
00147 h.m_infoBorderStart.y += h.m_startY;
00148 in >> h.m_infoBorderEnd.x >> h.m_infoBorderEnd.y;
00149 h.m_infoBorderEnd.x += (h.m_infoBorderStart.x);
00150 h.m_infoBorderEnd.y += (h.m_infoBorderStart.y);
00151
00152
00153 h.m_buildIcons.reserve(ICON_COUNT);
00154 h.m_buildIcons[0] = &h.m_iconBuildLT;
00155 h.m_buildIcons[1] = &h.m_iconBuildHT;
00156 h.m_buildIcons[2] = &h.m_iconBuildRL;
00157 h.m_buildIcons[3] = &h.m_iconBuildAR;
00158 h.m_buildIcons[4] = &h.m_iconBuildJT;
00159
00160
00161 float width, height;
00162 in >> width >> height;
00163
00164 in >> h.m_iconTextXOffset >> h.m_iconTextYOffset >> h.m_iconTextSize;
00165
00166 in >> color;
00167 h.m_iconTextColor = Map::getColorVec3D(color);
00168
00169 float x,y;
00170 in >> x >> y;
00171 h.m_iconBuildLT.setBounds( Vec2D(x - width/2,
00172 y - height/2),
00173 Vec2D(x + width/2,
00174 y + height/2));
00175 h.m_iconBuildLT.setImage(Globals::artWork->portraitLT);
00176
00177 in >> x >> y;
00178 h.m_iconBuildHT.setBounds( Vec2D(x - width/2,
00179 y - height/2),
00180 Vec2D(x + width/2,
00181 y + height/2));
00182 h.m_iconBuildHT.setImage(Globals::artWork->portraitHT);
00183
00184 in >> x >> y;
00185 h.m_iconBuildRL.setBounds( Vec2D(x - width/2,
00186 y - height/2),
00187 Vec2D(x + width/2,
00188 y + height/2));
00189 h.m_iconBuildRL.setImage(Globals::artWork->portraitLA);
00190
00191 in >> x >> y;
00192 h.m_iconBuildAR.setBounds( Vec2D(x - width/2,
00193 y - height/2),
00194 Vec2D(x + width/2,
00195 y + height/2));
00196 h.m_iconBuildAR.setImage(Globals::artWork->portraitAR);
00197
00198 in >> x >> y;
00199 h.m_iconBuildJT.setBounds( Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00200 h.m_iconBuildJT.setImage(Globals::artWork->portraitJE);
00201
00202 in >> x >> y;
00203 h.m_iconOverhead.setBounds(Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00204
00205 in >> x >> y;
00206 h.m_iconCallRFM.setBounds(Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00207
00208 in >> h.m_panelCallRFMCoord.x >> h.m_panelCallRFMCoord.y;
00209 in >> h.m_panelCallRFMSize.x >> h.m_panelCallRFMSize.y;
00210
00211
00212 FLOAT callW,callH;
00213 in >> x >> y >> callW >> callH;
00214 callW /= 5;
00215 for( int i=0; i<5; i++ )
00216 {
00217 Vec2D UL( x+callW*i, y);
00218 Vec2D LR( x+callW*i+callW, y+callH );
00219 h.m_iconCallUnitType.push_back( Icon(UL,LR,NULL) );
00220 }
00221
00222 in >> h.cammRFMTextPos.x >> h.cammRFMTextPos.y;
00223
00224 in >> x >> y;
00225 h.m_iconJetGuard.setBounds(Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00226 in >> x >> y;
00227 h.m_iconJetBomb.setBounds(Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00228 in >> x >> y;
00229 h.m_iconStop.setBounds(Vec2D(x - width/2, y - height/2), Vec2D(x + width/2, y + height/2));
00230
00231
00232 in >> h.m_econInfoTextX;
00233 in >> h.m_econInfoTextY;
00234
00235 in >> x >> y;
00236 const FLOAT econHeight = 0.07f;
00237 h.m_iconUpgradeEcon.setBounds(Vec2D(x - width/2, y - econHeight/2), Vec2D(x + width/2, y + econHeight/2));
00238
00239 h.m_iconOverhead.setImage(Globals::artWork->switchToOverhead);
00240 h.m_iconCallRFM.setImage(Globals::artWork->callRFMIconTex);
00241 h.m_iconJetGuard.setImage(Globals::artWork->butJetGuard);
00242 h.m_iconJetBomb.setImage(Globals::artWork->butJetBomb);
00243 h.m_iconStop.setImage(Globals::artWork->butStop);
00244
00245 h.m_pSelectedCity = 0;
00246 h.m_pSelectedUnit = 0;
00247 h.m_selectedGroupType = -1;
00248
00249 h.m_iconUpgradeEcon.setImage( Globals::artWork->upgradeEconTex );
00250 h.m_portraits[UnitTypes::LIGHT_TANK] = Globals::artWork->portraitLT;
00251 h.m_portraits[UnitTypes::HEAVY_TANK] = Globals::artWork->portraitHT;
00252 h.m_portraits[UnitTypes::LAUNCHER] = Globals::artWork->portraitLA;
00253 h.m_portraits[UnitTypes::ARTILLERY] = Globals::artWork->portraitAR;
00254 h.m_portraits[UnitTypes::JET] = Globals::artWork->portraitJE;
00255
00256 h.m_blinkOn = false;
00257 h.m_blinkCount = 0;
00258
00259 h.m_showCallRFMPanel = false;
00260
00261
00262 h.m_iconBuildLT.setHelpString("Build Light Tank Battalion\nFast and can shoot in any direction\nHot Key[L]");
00263 h.m_iconBuildHT.setHelpString("Build Heavy Tank Battalion\nSlow but very heavily armored\nHot Key[H]");
00264 h.m_iconBuildRL.setHelpString("Build Rocket Launcher Battalion\nLaunch medium-range rockets\nInflict massive damage to an area\nHot Key[R]");
00265 h.m_iconBuildAR.setHelpString("Build Artillery Battalion\nCan bombard from long range\nHot Key[A]");
00266 h.m_iconBuildJT.setHelpString("Build Jet Squadrom\nCan bomb ground targets or\nshoot down enemy jets\nHot Key[J]");
00267 h.m_iconUpgradeEcon.setHelpString("Upgrade City's Economic Level\nIncreased the city's income\n-rate in the long term");
00268 h.m_iconOverhead.setHelpString("Go back to the overhead map\nHot Key [Ctrl+Up]");
00269 h.m_iconCallRFM.setHelpString("Call in reinforcement (if any)");
00270 h.m_iconJetGuard.setHelpString("Right-Click on Empty Ground\nJets will guard the area\nand shoot down incoming enemy jets");
00271 h.m_iconJetBomb.setHelpString("Right-Click on Enemy Target\nJets will drop non-guided bombs");
00272 h.m_iconStop.setHelpString("Stop this battalion at current\nposition and direction\nHot Key [S]");
00273 h.m_iconCallUnitType[0].setHelpString("Call in more Light Tanks");
00274 h.m_iconCallUnitType[1].setHelpString("Call in more Heavy Tanks");
00275 h.m_iconCallUnitType[2].setHelpString("Call in more Rocket Launchers");
00276 h.m_iconCallUnitType[3].setHelpString("Call in more Artilleries");
00277 h.m_iconCallUnitType[4].setHelpString("Call in more Jets");
00278 }
00279
00280 Vec2D HUD::translateMiniMapToWorld(const Vec2D& mmPos)
00281 {
00282 Vec2D pos;
00283 pos.x = mmPos.x - m_miniMapBounds.bounds()[0].x;
00284 pos.y = mmPos.y - m_miniMapBounds.bounds()[0].y;
00285
00286 pos.x *= 1/m_miniMapScale.x;
00287 pos.y *= 1/m_miniMapScale.y;
00288
00289 pos.x += m_map.bounds.bounds()[0].x;
00290 pos.y += m_map.bounds.bounds()[0].y;
00291 return pos;
00292
00293 }
00294
00295 Vec3D HUD::translateMiniMapToWorld3D(const Vec2D& mmPos)
00296 {
00297 Vec3D pos;
00298 Vec2D pos2D = translateMiniMapToWorld(mmPos);
00299 pos.x = pos2D.x;
00300 pos.y = pos2D.y;
00301 pos.z = 0.0f;
00302 return pos;
00303 }
00304
00305 Vec2D HUD::translateWorldToMiniMap(const Vec2D& wPos)
00306 {
00307 Vec2D pos;
00308 pos.x = wPos.x - m_map.bounds.bounds()[0].x;
00309 pos.y = wPos.y - m_map.bounds.bounds()[0].y;
00310
00311 pos.x *= m_miniMapScale.x;
00312 pos.y *= m_miniMapScale.y;
00313
00314 pos.x += m_mapDims[0].x;
00315 pos.y += m_mapDims[0].y;
00316 return pos;
00317 }
00318
00319
00320 Vec2D HUD::translateWorldToMiniMap(const Vec3D& wPos)
00321 {
00322 return translateWorldToMiniMap(Vec2D(wPos.x, wPos.y));
00323 }
00324
00325 bool HUD::processMiniMapInput(const Vec2D& mouse)
00326 {
00327 if(m_miniMapBounds.contains(mouse) )
00328 {
00329 if( input_isMouseLBClicked() )
00330 {
00331
00332 if( input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL) )
00333 {
00334 switchToOverhead();
00335
00336 Vec2D pos = translateMiniMapToWorld(mouse);
00337 GameState::camTarget().x = pos.x;
00338 GameState::camTarget().y = pos.y;
00339 return true;
00340 }
00341
00342 for(BattleIter iter=GameState::battles().begin(); iter != GameState::battles().end(); ++iter)
00343 {
00344
00345 if( (*iter)->isFoughtBy(m_pPlayer->color()) )
00346 {
00347 Vec2D pos = translateWorldToMiniMap( (*iter)->getBattleLocation() );
00348 Rect r(Vec2D(pos.x-0.01f, pos.y-0.01f), Vec2D(pos.x+0.01f, pos.y+0.01f));
00349
00350 if( r.contains(mouse) )
00351 {
00352 GameState::setActiveBattle( *iter );
00353 setSelectedCity(0);
00354 setSelectedUnit(0);
00355 setSelectedGroupType(-1);
00356 return true;
00357 }
00358 }
00359
00360 }
00361
00362 Vec2D pos = translateMiniMapToWorld(mouse);
00363 GameState::camTarget().x = pos.x;
00364 GameState::camTarget().y = pos.y;
00365
00366 return true;
00367 }
00368 else if( input_isMouseRBClicked() )
00369 {
00370
00371 Vec3D goalPos = translateMiniMapToWorld3D(mouse);
00372
00373 if( GameState::worldMap().bounds.contains(Vec2D(goalPos.x, goalPos.y)) )
00374 {
00375 for(vector<MilitaryUnit*>::iterator iter = GameState::selectedUnits().begin(); iter != GameState::selectedUnits().end(); ++iter)
00376 {
00377 stringstream sstr;
00378 sstr << COMMAND_OVERHEAD << " " << COMMIT_TIME << " " << Globals::currGameTick + NETWORK_GAME_TICK_LAG << " " << COMMAND_GOAL << " "
00379 << (*iter)->uniqueID() << " " << Helper::serialize(goalPos);
00380 net_send(sstr.str());
00381
00382 }
00383 if(GameState::selectedUnits().size() > 0) Sound::playRandomSound(Sound::CLASS_ACK);
00384 return true;
00385 }
00386 }
00387 }
00388 return false;
00389 }
00390
00391 bool HUD::isButtonStopClicked()
00392 {
00393 HUD& h = HUD::getObj();
00394 Vec2D mouse2D( input_getMouseX(), input_getMouseY() );
00395 return input_isMouseLBClicked() && h.m_iconStop.contains(mouse2D);
00396 }
00397
00398 bool HUD::isButtonCallRFMUnitTypeClicked( int unitType )
00399 {
00400 HUD& h = HUD::getObj();
00401 Vec2D mouse2D( input_getMouseX(), input_getMouseY() );
00402 if( !h.m_showCallRFMPanel ) return false;
00403 return input_isMouseLBClicked() && h.m_iconCallUnitType[unitType].contains(mouse2D);
00404 }
00405
00406 namespace Overhead {
00408 void deleteMilitaryUnit(MilitaryUnit* unit);
00409 }
00410
00411 void sendReinforcement( int unitType )
00412 {
00413 HUD& h = HUD::getObj();
00414 if( !GameState::activeBattle() ) return;
00415 Vec2D battlePos( GameState::activeBattle()->getBattleLocation() );
00416 Vec3D playerCol( GameState::consolePlayer()->color() );
00417 for( UnitIter iter(GameState::units().begin()); iter!=GameState::units().end(); iter++ )
00418 if( (*iter)->color()==playerCol )
00419 if( (*iter)->unitType()==unitType )
00420 {
00421 Vec2D unitPos( (*iter)->position().x, (*iter)->position().y );
00422 if( math_dist2D(battlePos,unitPos) <= 100.0f )
00423 {
00424 stringstream sstr;
00425 if( unitType==UnitTypes::JET )
00426 {
00427 sstr << COMMAND_SEND_JET_REINFORCEMENT << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG
00428 << " " << GameState::activeBattle()->uniqueID() << " " << (*iter)->uniqueID();
00429 } else
00430 {
00431 sstr << COMMAND_SEND_UNIT_REINFORCEMENT << " " << COMMIT_TIME << " " << currGameTick + NETWORK_GAME_TICK_LAG
00432 << " " << GameState::activeBattle()->uniqueID() << " " << (*iter)->uniqueID();
00433 }
00434 net_send(sstr.str());
00435 return;
00436 }
00437 }
00438 }
00439
00440 bool HUD::processOverheadInput()
00441 {
00442 HUD& h = HUD::getObj();
00443
00444
00445 bool ctrl_down(input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL));
00446 if(input_isKeyDown(KeyCodes::key_ADD) && !ctrl_down)
00447 Sound::increaseSongVol();
00448 if(input_isKeyDown(KeyCodes::key_SUBTRACT) && !ctrl_down)
00449 Sound::decreaseSongVol();
00450 if(input_isKeyPressed(KeyCodes::key_ADD) && ctrl_down)
00451 Sound::increaseSFXVol();
00452 if(input_isKeyPressed(KeyCodes::key_SUBTRACT) && ctrl_down)
00453 Sound::decreaseSFXVol();
00454
00455
00456 Vec2D mouse2D( input_getMouseX(), input_getMouseY() );
00457
00458 if( h.processMiniMapInput(mouse2D) ) return true;
00459
00460
00461 if(h.m_pSelectedCity)
00462 {
00463 if(input_isMouseLBClicked() && h.m_iconBuildLT.contains(mouse2D))
00464 {
00465 sendBuildMessage( COMMAND_BUILD_LIGHTTANK, h.m_pSelectedCity->uniqueID() );
00466 return true;
00467 }
00468 else if( input_isMouseLBClicked() && h.m_iconBuildHT.contains(mouse2D) )
00469 {
00470 sendBuildMessage( COMMAND_BUILD_HEAVYTANK, h.m_pSelectedCity->uniqueID());
00471 return true;
00472 }
00473 else if( input_isMouseLBClicked() && h.m_iconBuildRL.contains(mouse2D) )
00474 {
00475 sendBuildMessage( COMMAND_BUILD_ROCKET_LAUNCHER, h.m_pSelectedCity->uniqueID() );
00476 return true;
00477 }
00478 else if( input_isMouseLBClicked() && h.m_iconBuildAR.contains(mouse2D) )
00479 {
00480 sendBuildMessage( COMMAND_BUILD_ARTILLERY, h.m_pSelectedCity->uniqueID() );
00481 return true;
00482 }
00483 else if(input_isMouseLBClicked() && h.m_iconBuildJT.contains(mouse2D) )
00484 {
00485 sendBuildMessage( COMMAND_BUILD_JET, h.m_pSelectedCity->uniqueID() );
00486 return true;
00487 }
00488 else if(input_isMouseLBClicked() && h.m_iconUpgradeEcon.contains(mouse2D) )
00489 {
00490 sendBuildMessage( COMMAND_BUILD_ECON, h.m_pSelectedCity->uniqueID() );
00491 return true;
00492 }
00493 }
00494 else if( GameState::activeBattle() )
00495 {
00496
00497 if(input_isMouseLBClicked())
00498 {
00499 if( h.m_iconOverhead.contains(mouse2D) )
00500 {
00501 h.switchToOverhead();
00502 return true;
00503 }
00504
00505 if( h.m_iconCallRFM.contains(mouse2D) )
00506 {
00507 h.m_showCallRFMPanel = true;
00508 h.setSelectedCity(NULL);
00509 h.setSelectedGroupType(-1);
00510 h.setSelectedUnit(NULL);
00511 GameState::activeBattle()->clearUnitSelection();
00512 return true;
00513 }
00514
00515
00516 Vec3D &playerCol = (Vec3D) GameState::consolePlayer()->color();
00517 bool mayGround = GameState::activeBattle()->maySendGroundReinforcement( playerCol );
00518 bool mayAir = GameState::activeBattle()->maySendAirReinforcement( playerCol );
00519 bool allowed[5] = { mayGround, mayGround, mayGround, mayGround, mayAir };
00520 for( int i=0; i<UnitTypes::COUNT; i++ )
00521 if( isButtonCallRFMUnitTypeClicked(i) )
00522 {
00523 if( allowed[i] ) sendReinforcement(i);
00524 return true;
00525 }
00526
00527 if( h.m_selectedGroupType==UnitTypes::JET )
00528 {
00529 if( h.m_iconJetGuard.contains(mouse2D) ) return true;
00530 if( h.m_iconJetBomb.contains(mouse2D) ) return true;
00531 }
00532 }
00533 }
00534
00535
00536 if( GameState::battles().size() > 0 )
00537 {
00538 if( (input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL)) && input_isKeyPressed(KeyCodes::key_RIGHT) )
00539 {
00540 h.switchToNextBattle();
00541 return true;
00542 }
00543 else if ( (input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL)) && input_isKeyPressed(KeyCodes::key_LEFT) )
00544 {
00545 h.switchToPrevBattle();
00546 return true;
00547 }
00548 else if( (input_isKeyDown(KeyCodes::key_LCONTROL) || input_isKeyDown(KeyCodes::key_RCONTROL)) && input_isKeyPressed(KeyCodes::key_UP) )
00549 {
00550 h.switchToOverhead();
00551 return true;
00552 }
00553 }
00554 return false;
00555 }
00556
00557 void HUD::renderMiniMap()
00558 {
00559
00560 overlay_rect(m_mapDims[0], m_mapDims[1], true, Colors::gray, BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00561
00562
00563 for(CityIter iter=GameState::cities().begin(); iter != GameState::cities().end(); ++iter)
00564 {
00565 Vec2D pos = translateWorldToMiniMap( (*iter)->position() );
00566 overlay_point(pos, m_mapCityOutlineSize, COLOR_CITY_OUTLINE, BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00567 overlay_point(pos, m_mapCitySize, (*iter)->color(), BlendModes::NONE, 1.0f, 1+ICON_RENDER_PRIORITY);
00568 }
00569
00570 for(UnitIter iter=GameState::units().begin(); iter != GameState::units().end(); ++iter)
00571 {
00572
00573 Vec2D pos = translateWorldToMiniMap( (*iter)->position() );
00574 overlay_point(pos, m_mapUnitSize, (*iter)->color(), BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00575 }
00576
00577 for(BattleIter iter=GameState::battles().begin(); iter != GameState::battles().end(); ++iter)
00578 {
00579
00580 Vec2D pos = translateWorldToMiniMap( (*iter)->getBattleLocation() );
00581
00582
00583 if( (*iter)->isFoughtBy(m_pPlayer->color()) && m_blinkOn )
00584 {
00585 overlay_image(Globals::artWork->minimapBattleIcon, pos, Vec2D(0.03f,0.03f),
00586 BlendModes::KEY, 1.0f, MOUSE_RENDER_PRIORITY);
00587 }
00588 }
00589
00590 }
00591
00592 void HUD::update()
00593 {
00594 HUD& h = HUD::getObj();
00595
00596 if(h.m_blinkCount++ > BLINK_RATE)
00597 {
00598 h.m_blinkOn = !h.m_blinkOn;
00599 h.m_blinkCount = 0;
00600 }
00601 }
00602
00603
00604 void HUD::render()
00605 {
00606 HUD& h = HUD::getObj();
00607 Vec2D mouse2D( input_getMouseX(), input_getMouseY() );
00608
00609
00610 overlay_image(Globals::artWork->hud, Vec2D(0.5f,0.9f), Vec2D(1.0f, 0.2f), BlendModes::NONE, 1.0f, BG_RENDER_PRIORITY);
00611
00612
00613 overlay_rect(h.m_mapBorderStart, h.m_mapBorderEnd, false, h.m_pPlayer->color(), BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00614 overlay_rect(h.m_actionsBorderStart, h.m_actionsBorderEnd, false, h.m_pPlayer->color(), BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00615 overlay_rect(h.m_infoBorderStart, h.m_infoBorderEnd, false, h.m_pPlayer->color(), BlendModes::NONE, 1.0f, ICON_RENDER_PRIORITY);
00616
00617
00618 h.renderMiniMap();
00619
00620
00621 overlay_text() << "$" << h.m_pPlayer->bank().balance();
00622 overlay_textOut(Vec2D(h.m_moneyTextX, h.m_moneyTextY), h.m_moneyTextSize, h.m_moneyTextColor);
00623
00624 if(h.m_pSelectedCity)
00625 {
00626
00627 int econLevel = h.m_pSelectedCity->econLevel();
00628 int incomeRate = EconData::getObj().depositPerCity(econLevel) * 62 * 60 / EconData::getObj().depositInterval();
00629 overlay_text() << "Economics Level = " << econLevel << "\n";
00630 overlay_text() << "Generates $" << incomeRate << "/min";
00631 if( h.m_pSelectedCity->timeUntilFinishEconUpgrade()!=-1 )
00632 overlay_text() << "\nUpgrading : " << h.m_pSelectedCity->timeUntilFinishEconUpgrade();
00633
00634 overlay_textOut( Vec2D(h.m_econInfoTextX,h.m_econInfoTextY), 0.8f );
00635
00636
00637 h.m_iconUpgradeEcon.render();
00638 h.m_iconUpgradeEcon.drawHelpString();
00639 if( h.m_iconUpgradeEcon.contains(mouse2D) ) h.m_iconUpgradeEcon.drawOutline(Colors::yellow);
00640 int cost = EconData::getObj().econUpgradeCost( h.m_pSelectedCity->econLevel() );
00641 if( cost <= 10000 ) overlay_text() << "$" << cost;
00642 else overlay_text() << "MAX";
00643 overlay_textOut( h.m_iconUpgradeEcon.bounds()[0]+Vec2D(0.002f,0.004f), h.m_iconTextSize, h.m_iconTextColor );
00644
00645
00646 for(int i=0; i < ICON_COUNT; ++i)
00647 {
00648 h.m_buildIcons[i]->render();
00649 h.m_buildIcons[i]->drawHelpString();
00650
00651 overlay_text() << "$" << EconData::getObj().unitAmount(i);
00652 overlay_textOut(Vec2D(h.m_buildIcons[i]->bounds()[0].x + h.m_iconTextXOffset,
00653 h.m_buildIcons[i]->bounds()[0].y + h.m_iconTextYOffset),
00654 h.m_iconTextSize,
00655 h.m_iconTextColor);
00656 if( h.m_buildIcons[i]->contains(mouse2D) ) h.m_buildIcons[i]->drawOutline(Colors::yellow);
00657 }
00658
00659
00660 deque<int> q = h.m_pSelectedCity->trainees();
00661 int n=0;
00662 for(deque<int>::iterator it = q.begin(); it != q.end() && n < 9; ++it, ++n)
00663 overlay_image(h.m_buildIcons[*it]->image(),
00664 h.m_buildQIconCoords[n],
00665 h.m_buildQIconSize,
00666 BlendModes::NONE,
00667 1.0f,
00668 ICON_RENDER_PRIORITY);
00669
00670
00671 if( !q.empty() )
00672 {
00673 overlay_text() << static_cast<int>(h.m_pSelectedCity->trainingTimeLeft()/62);
00674 overlay_textOut(h.m_buildQTimerCoords, h.m_buildQTimerTextSize, h.m_buildQTimerTextColor);
00675 }
00676
00677
00678 }
00679 else if(h.m_pSelectedUnit)
00680 {
00681 overlay_image(h.m_portraits[h.m_pSelectedUnit->unitType()],
00682 h.m_infoPortraitCenter,
00683 h.m_infoPortraitSize,
00684 BlendModes::NONE,
00685 1.0f,
00686 ICON_RENDER_PRIORITY);
00687 }
00688 else if (h.m_selectedGroupType != -1)
00689 {
00690 overlay_image(h.m_portraits[h.m_selectedGroupType],
00691 h.m_infoPortraitCenter,
00692 h.m_infoPortraitSize,
00693 BlendModes::NONE,
00694 1.0f,
00695 ICON_RENDER_PRIORITY);
00696 }
00697
00698
00699 if( GameState::activeBattle() )
00700 {
00701 h.m_iconOverhead.render();
00702 h.m_iconCallRFM.render();
00703 h.m_iconOverhead.drawHelpString();
00704 h.m_iconCallRFM.drawHelpString();
00705 if( h.m_iconOverhead.contains(mouse2D) ) h.m_iconOverhead.drawOutline(Colors::yellow);
00706 if( h.m_iconCallRFM.contains(mouse2D) ) h.m_iconCallRFM.drawOutline(Colors::yellow );
00707
00708 if( h.m_showCallRFMPanel )
00709 {
00710 overlay_image( Globals::artWork->callRFMPanelTex, h.m_panelCallRFMCoord, h.m_panelCallRFMSize,
00711 BlendModes::NONE, 1.0f, 6 );
00712
00713 int totalCallable = 0;
00714 for( int i=0; i<5; i++ )
00715 {
00716 if( h.m_iconCallUnitType[i].contains(mouse2D) ) h.m_iconCallUnitType[i].drawOutline(Colors::yellow);
00717 h.m_iconCallUnitType[i].drawHelpString();
00718 totalCallable += GameState::availableRFM()[i];
00719
00720
00721 Vec2D pos( h.m_iconCallUnitType[i].bounds()[0] + h.m_iconCallUnitType[i].bounds()[1] );
00722 pos = pos * 0.5f + Vec2D( -0.002f, -0.001f );
00723 overlay_text() << GameState::availableRFM()[i];
00724 overlay_textOut( pos, 1.2f, Colors::yellow, NULL, 6 );
00725 }
00726
00727
00728 Vec3D &playerCol = (Vec3D)GameState::consolePlayer()->color();
00729 bool mayGround = GameState::activeBattle()->maySendGroundReinforcement( playerCol );
00730 bool mayAir = GameState::activeBattle()->maySendAirReinforcement( playerCol );
00731 if( totalCallable==0 )
00732 overlay_text() << "No nearby friendly forces";
00733 else if( !mayGround && !mayAir )
00734 overlay_text() << "Too many units in battle already";
00735 else if( !mayGround )
00736 overlay_text() << "Too many tanks\n in battle already";
00737 else if( !mayAir )
00738 overlay_text() << "Too many jets\nin battle already";
00739 else
00740 overlay_text() << totalCallable << " Battalions Standing by";
00741 overlay_textOut( h.cammRFMTextPos, 0.7f, Colors::red, NULL, 6 );
00742
00743
00744
00745 }
00746
00747
00748 if( h.m_selectedGroupType != -1 )
00749 {
00750 h.m_iconStop.render();
00751 h.m_iconStop.drawHelpString();
00752 if( h.m_iconStop.contains(mouse2D) ) h.m_iconStop.drawOutline(Colors::yellow);
00753 }
00754 if( h.m_selectedGroupType == UnitTypes::JET )
00755 {
00756 h.m_iconJetGuard.render();
00757 h.m_iconJetGuard.drawHelpString();
00758 if( h.m_iconJetGuard.contains(mouse2D) ) h.m_iconJetGuard.drawOutline(Colors::yellow);
00759 h.m_iconJetBomb.render();
00760 h.m_iconJetBomb.drawHelpString();
00761 if( h.m_iconJetBomb.contains(mouse2D) ) h.m_iconJetBomb.drawOutline(Colors::yellow);
00762 }
00763 }
00764 }
00765
00766
00767 void HUD::setWorldMap(Map::WorldMap& map)
00768 {
00769 HUD& h = HUD::getObj();
00770 h.m_map = map;
00771 h.m_miniMapScale.x = (h.m_mapDims[1].x - h.m_mapDims[0].x) / h.m_map.width;
00772 h.m_miniMapScale.y = (h.m_mapDims[1].y - h.m_mapDims[0].y) / h.m_map.height;
00773 }
00774
00775 void HUD::clearSelections()
00776 {
00777 HUD::getObj().m_selectedGroupType = -1;
00778 HUD::getObj().m_pSelectedCity = 0;
00779 HUD::getObj().m_pSelectedUnit = 0;
00780 }
00781
00782 void HUD::shutdown()
00783 {
00784 HUD::getObj().releaseObj();
00785 }
00786
00787
00788 void HUD::switchToNextBattle()
00789 {
00790 BattleIter currBattle;
00791
00792 if( GameState::activeBattle() )
00793 {
00794 for(BattleIter iter = GameState::battles().begin(); iter != GameState::battles().end(); ++iter)
00795 {
00796 if( (*iter) == GameState::activeBattle() )
00797 {
00798 currBattle = iter;
00799 break;
00800 }
00801 }
00802 }
00803 else
00804 {
00805 currBattle = GameState::battles().begin();
00806 }
00807
00808
00809
00810 for(BattleIter iter=currBattle+1; iter != GameState::battles().end(); ++iter)
00811 {
00812 if( (*iter)->isFoughtBy(m_pPlayer->color()) )
00813 {
00814 GameState::setActiveBattle(*iter);
00815 return;
00816 }
00817 }
00818
00819 for(BattleIter iter=GameState::battles().begin(); iter != currBattle; ++iter)
00820 {
00821 if( (*iter)->isFoughtBy(m_pPlayer->color()) )
00822 {
00823 GameState::setActiveBattle(*iter);
00824 return;
00825 }
00826 }
00827
00828 if( (*currBattle)->isFoughtBy(m_pPlayer->color()) )
00829 GameState::setActiveBattle(*currBattle);
00830 }
00831
00832 void HUD::switchToPrevBattle()
00833 {
00834 BattleIter currBattle;
00835
00836 if( GameState::activeBattle() )
00837 {
00838 for(BattleIter iter = GameState::battles().begin(); iter != GameState::battles().end(); ++iter)
00839 {
00840 if( (*iter) == GameState::activeBattle() )
00841 {
00842 currBattle = iter;
00843 break;
00844 }
00845 }
00846 }
00847 else
00848 {
00849 currBattle = GameState::battles().end()-1;
00850 }
00851
00852
00853
00854 for(BattleIter iter=currBattle-1; iter >= GameState::battles().begin(); --iter)
00855 {
00856 if( (*iter)->isFoughtBy(m_pPlayer->color()) )
00857 {
00858 GameState::setActiveBattle(*iter);
00859 return;
00860 }
00861 }
00862
00863 for(BattleIter iter=GameState::battles().end()-1; iter != currBattle; --iter)
00864 {
00865 if( (*iter)->isFoughtBy(m_pPlayer->color()) )
00866 {
00867 GameState::setActiveBattle(*iter);
00868 return;
00869 }
00870 }
00871
00872 if( (*currBattle)->isFoughtBy(m_pPlayer->color()) )
00873 GameState::setActiveBattle(*currBattle);
00874 }
00875
00876 void HUD::switchToOverhead()
00877 {
00878 GameState::setActiveBattle(0);
00879 setSelectedCity(0);
00880 setSelectedUnit(0);
00881 setSelectedGroupType(-1);
00882 }