gameTacMap.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /*************************************************************************************************\
  2. gameTacMap.cpp : Implementation of the gameTacMap component.
  3. //---------------------------------------------------------------------------//
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. //===========================================================================//
  6. \*************************************************************************************************/
  7. #include "gameTacMap.h"
  8. #include "team.h"
  9. #include "comndr.h"
  10. #include "objMgr.h"
  11. #include "cellip.h"
  12. #include "gameCam.h"
  13. #include "Objective.h"
  14. #include "mission.h"
  15. #include <windows.h>
  16. #include "..\resource.h"
  17. extern unsigned char godMode;
  18. extern bool useLeftRightMouseProfile;
  19. #define SQUARE_BLIP 0
  20. #define DOT_BLIP 1
  21. #define TRIANGLE_BLIP 2
  22. const float GameTacMap::s_blinkLength = .5f;
  23. float GameTacMap::s_lastBlinkTime = 0.f;
  24. extern bool ShowMovers;
  25. GameTacMap::GameTacMap()
  26. {
  27. top = 0;
  28. left = 0;
  29. right = 0;
  30. bottom = 0;
  31. buildingPoints = NULL;
  32. buildingCount = 0;
  33. navMarkerCount = 0;
  34. curNavMarker = -1;
  35. objectiveAnimationId = -1;
  36. objectiveFlashTime = 0.0f;
  37. objectiveNumFlashes = 0;
  38. }
  39. void GameTacMap::init( unsigned char* bitmapData, int dataSize )
  40. {
  41. EllipseElement::init();
  42. TGAFileHeader* pHeader = (TGAFileHeader*)bitmapData;
  43. bmpWidth = pHeader->width;
  44. bmpHeight = pHeader->height;
  45. textureHandle = gos_NewTextureFromMemory(gos_Texture_Solid,".tga",bitmapData,dataSize,0);
  46. char path[256];
  47. strcpy( path, artPath );
  48. strcat( path, "viewingrect.tga" );
  49. viewRectHandle = mcTextureManager->loadTexture(path, gos_Texture_Alpha, 0 );
  50. strcpy( path, artPath );
  51. strcat( path, "blip.tga" );
  52. blipHandle = mcTextureManager->loadTexture( path, gos_Texture_Alpha, 0 );
  53. }
  54. void GameTacMap::update()
  55. {
  56. Stuff::Vector2DOf<long> screen;
  57. screen.x = userInput->getMouseX();
  58. screen.y = userInput->getMouseY();
  59. float width = right - left;
  60. float height = bottom - top;
  61. if ( !inRegion(screen.x, screen.y) )
  62. return;
  63. ControlGui::instance->setRolloverHelpText( IDS_TACMAP_HELP );
  64. if ( userInput->isLeftClick() )
  65. {
  66. screen.x -= left;
  67. screen.y -= top;
  68. Stuff::Vector3D world;
  69. tacMapToWorld( screen, width, height, world );
  70. if (MissionInterfaceManager::instance()->getControlGui()->isAddingAirstrike() &&
  71. MissionInterfaceManager::instance()->getControlGui()->isButtonPressed( ControlGui::SENSOR_PROBE ))
  72. MissionInterfaceManager::instance()->doMove(world);
  73. else
  74. {
  75. eye->setPosition( world, false );
  76. ((GameCamera*)(eye))->setTarget( 0 );
  77. }
  78. }
  79. else if ( userInput->isRightClick() && useLeftRightMouseProfile )
  80. {
  81. screen.x -= left;
  82. screen.y -= top;
  83. Stuff::Vector3D world;
  84. tacMapToWorld( screen, width, height, world );
  85. MissionInterfaceManager::instance()->doMove(world);
  86. }
  87. }
  88. bool GameTacMap::animate (long objectiveId, long nFlashes)
  89. {
  90. if (objectiveAnimationId == -1)
  91. {
  92. objectiveAnimationId = objectiveId - 1;
  93. objectiveFlashTime = 0.0f;
  94. objectiveNumFlashes = nFlashes;
  95. return true;
  96. }
  97. return false;
  98. }
  99. void GameTacMap::render()
  100. {
  101. if (turn < 2) //Terrain not setup yet. Left,Right,Top,Bottom are poopy!
  102. return;
  103. gos_VERTEX corners[5];
  104. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero );
  105. gos_SetRenderState( gos_State_Specular,FALSE );
  106. gos_SetRenderState( gos_State_AlphaTest, FALSE );
  107. gos_SetRenderState( gos_State_Filter, gos_FilterNone );
  108. gos_SetRenderState( gos_State_ZWrite, 0 );
  109. gos_SetRenderState( gos_State_ZCompare, 0 );
  110. gos_SetRenderState( gos_State_Texture, textureHandle );
  111. for ( int i = 0; i < 4; ++i )
  112. {
  113. corners[i].rhw = 1.0f;
  114. corners[i].argb = 0xffffffff;
  115. corners[i].frgb = 0;
  116. corners[i].z = 0.0f;
  117. }
  118. corners[0].x = corners[2].x = left;
  119. corners[1].x = corners[3].x = right;
  120. corners[3].y = corners[2].y = bottom;
  121. corners[0].y = corners[1].y = top;
  122. corners[0].u = 2.f/(float)bmpWidth;
  123. corners[3].u = 128.f/(float)bmpWidth;
  124. corners[2].u = 2.f/(float)bmpWidth;
  125. corners[1].u = 128.f/(float)bmpWidth;
  126. corners[0].v = 2.f/(float)bmpWidth;
  127. corners[3].v = 128.f/(float)bmpHeight;
  128. corners[2].v = 128.f/(float)bmpHeight;
  129. corners[1].v = 2.f/(float)bmpWidth;
  130. gos_DrawTriangles( corners, 3 );
  131. gos_DrawTriangles( &corners[1], 3 );
  132. Stuff::Vector2DOf<long> screen;
  133. Stuff::Vector4D nScreen;
  134. Stuff::Vector3D world;
  135. //-----------------------------------------------------------
  136. // Render the objective markers
  137. long count = 0;
  138. for ( EList< CObjective*, CObjective* >::EIterator iter = Team::home->objectives.Begin();
  139. !iter.IsDone(); iter++ )
  140. {
  141. //We are there. Start flashing.
  142. if ((objectiveAnimationId == count) && objectiveNumFlashes)
  143. {
  144. objectiveFlashTime += frameLength;
  145. if ( objectiveFlashTime > .5f )
  146. {
  147. objectiveFlashTime = 0.0f;
  148. objectiveNumFlashes--;
  149. }
  150. else if ( objectiveFlashTime > 0.25f)
  151. {
  152. (*iter)->RenderMarkers(this, 0);
  153. }
  154. if (objectiveNumFlashes == 0)
  155. {
  156. //Flashing is done. We now return you to your regularly scheduled program.
  157. objectiveAnimationId = 0;
  158. }
  159. }
  160. else
  161. {
  162. (*iter)->RenderMarkers(this, 0);
  163. }
  164. count++;
  165. }
  166. // this is the little viewing rect
  167. // Routine that InverseProjects is slightly less accurate but an order of magnitude faster.
  168. // Can make more accurate later at very little expense to performance.
  169. // Easy to fix with camera later. -fs
  170. screen.x = 1;
  171. screen.y = 1;
  172. nScreen.x = nScreen.y = 1.0f;
  173. nScreen.z = nScreen.w = 0.0f;
  174. eye->inverseProjectZ( nScreen, world );
  175. worldToTacMap( world, corners[0] );
  176. screen.y = Environment.screenHeight - 1;
  177. nScreen.y = (Environment.screenHeight * 0.6667f) - 1;
  178. nScreen.z = nScreen.w = 0.0f;
  179. eye->inverseProjectZ( nScreen, world );
  180. worldToTacMap( world, corners[1] );
  181. screen.x = Environment.screenWidth - 1;
  182. nScreen.x = Environment.screenWidth - 1;
  183. nScreen.z = nScreen.w = 0.0f;
  184. eye->inverseProjectZ( nScreen, world );
  185. worldToTacMap( world, corners[2] );
  186. screen.y = 1;
  187. nScreen.y = 1;
  188. nScreen.z = nScreen.w = 0.0f;
  189. eye->inverseProjectZ( nScreen, world );
  190. worldToTacMap( world, corners[3] );
  191. corners[0].argb = 0xffffffff;
  192. corners[1].argb = 0xffffffff;
  193. corners[2].argb = 0xffffffff;
  194. corners[3].argb = 0xffffffff;
  195. corners[0].u = corners[1].u = 0.078125f;
  196. corners[3].u = corners[2].u = .99875f;
  197. corners[0].v = corners[3].v = 0.078125f;
  198. corners[1].v = corners[2].v = .99875f;
  199. corners[4] = corners[0];
  200. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha);
  201. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  202. gos_SetRenderState( gos_State_MonoEnable, 0);
  203. gos_SetRenderState( gos_State_Perspective, 0);
  204. gos_SetRenderState( gos_State_Clipping, 2);
  205. gos_SetRenderState( gos_State_AlphaTest, 0);
  206. gos_SetRenderState( gos_State_Specular, 0);
  207. gos_SetRenderState( gos_State_Dither, 1);
  208. gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate);
  209. gos_SetRenderState( gos_State_Filter, gos_FilterBiLinear);
  210. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  211. gos_SetRenderState( gos_State_ZCompare, 0);
  212. gos_SetRenderState( gos_State_ZWrite, 0);
  213. DWORD gosTextureHandle = mcTextureManager->get_gosTextureHandle(viewRectHandle);
  214. gos_SetRenderState( gos_State_Texture, gosTextureHandle );
  215. gos_DrawQuads( &corners[0], 4 );
  216. unsigned long colors[MAX_MOVERS];
  217. unsigned long ringColors[MAX_MOVERS];
  218. Stuff::Vector3D positions[MAX_MOVERS];
  219. unsigned long ranges[MAX_MOVERS];
  220. bool selected[MAX_MOVERS];
  221. count = 0;
  222. //------------------------------------------------------------
  223. // draw non-movers, must do separate check for vehicles, I'm not sure they
  224. // have sensors
  225. for ( i = 0; i < MAX_TEAMS; ++i )
  226. {
  227. TeamSensorSystem* pSys = SensorManager->getTeamSensor( i );
  228. if ( pSys )
  229. {
  230. for ( int j = 0; j < pSys->numSensors; ++j )
  231. {
  232. SensorSystem* pSensor = pSys->sensors[j];
  233. if ( !pSensor )
  234. continue;
  235. if ( pSensor->owner->isDestroyed() || pSensor->owner->isDisabled() || pSensor->owner->getStatus() == OBJECT_STATUS_SHUTDOWN )
  236. continue;
  237. if ( pSensor->getRange() < 1.1 || pSensor->broken)
  238. continue;
  239. if (!pSensor->owner->getTeam())
  240. continue;
  241. ObjectClass objClass = pSensor->owner->getObjectClass();
  242. unsigned long colorBlip = pSensor->owner->getSelected() ? 0xff4bff4b : 0xff00cc00;
  243. unsigned long colorRing = 0xff00cc00;
  244. if ( pSensor->owner->getTeam()->isNeutral( Team::home ) )
  245. {
  246. colorBlip = pSensor->owner->getSelected() ? 0xff4c4cff : 0xff0000ff;
  247. colorRing = 0xff0000ff;
  248. }
  249. else if ( pSensor->owner->getTeam()->isEnemy( Team::home ) ) // enemy
  250. {
  251. {
  252. colorBlip = pSensor->owner->getSelected() ? 0xffff3f3f : 0xffff0000;
  253. colorRing = 0xffff0000;
  254. }
  255. }
  256. if ( objClass != BATTLEMECH && objClass != GROUNDVEHICLE)
  257. {
  258. if ( objClass == ARTILLERY )
  259. {
  260. // blink
  261. s_lastBlinkTime += frameLength;
  262. if ( s_lastBlinkTime > s_blinkLength )
  263. {
  264. colorBlip = 0;
  265. colorRing = 0;
  266. s_lastBlinkTime = 0.f;
  267. }
  268. }
  269. colors[count] = colorBlip;
  270. ringColors[count] = colorRing;
  271. ranges[count] = pSensor->getRange();
  272. selected[count] = 0;
  273. positions[count] = pSensor->owner->getPosition();
  274. count++;
  275. }
  276. }
  277. }
  278. }
  279. unsigned long colorBlip, colorRing;
  280. //-----------------------------------------------------
  281. // draw the movers
  282. for (i=0;i<(ObjectManager->numMovers);i++)
  283. {
  284. MoverPtr mover = ObjectManager->getMover(i);
  285. if (mover && mover->getExists() && !(mover->isDestroyed() || mover->isDisabled()))
  286. {
  287. SensorSystem* pSensor = mover->getSensorSystem();
  288. float range = pSensor ? pSensor->getRange() : 0;
  289. long contactStatus = mover->getContactStatus(Team::home->getId(), true);
  290. if (mover->getTeamId() == Team::home->id)
  291. {
  292. if (mover->getCommanderId() == Commander::home->getId())
  293. {
  294. if (mover->isOnGUI())
  295. {
  296. colorBlip = mover->getSelected() ? 0xff4bff4b : 0xff00cc00;
  297. mover->getStatus() == OBJECT_STATUS_SHUTDOWN ? colorRing = 0 : colorRing = 0xff00cc00;
  298. }
  299. else
  300. continue;
  301. }
  302. else
  303. {
  304. if (mover->isOnGUI() && land->IsGameSelectTerrainPosition(mover->getPosition()) && mover->pathLocks)
  305. {
  306. colorBlip = mover->getSelected() ? 0xff4b4bff : 0xff0000cc;
  307. mover->getStatus() == OBJECT_STATUS_SHUTDOWN ? colorRing = 0 : colorRing = 0xff0000cc;
  308. }
  309. else
  310. continue;
  311. }
  312. }
  313. else if (ShowMovers || (MPlayer && MPlayer->allUnitsDestroyed[MPlayer->commanderID]) || ((mover->getTeamId() != Team::home->id)
  314. && ( contactStatus != CONTACT_NONE )
  315. && (mover->getStatus() != OBJECT_STATUS_SHUTDOWN)
  316. && (!mover->hasNullSignature())
  317. && (mover->getEcmRange() <= 0.0f) ) ) //Do not draw ECM mechs!!)
  318. {
  319. //Not on our side. Draw by contact status
  320. colorBlip = mover->getSelected() ? 0xffff3f3f : 0xffff0000;
  321. colorRing = 0xffff0000;
  322. }
  323. else
  324. continue;
  325. colors[count] = colorBlip;
  326. ringColors[count] = colorRing;
  327. ranges[count] = range;
  328. selected[count] = mover->getSelected();
  329. positions[count] = mover->getPosition();
  330. count++;
  331. }
  332. }
  333. for ( i = 0; i < count; i++ )
  334. {
  335. drawSensor( positions[i], ranges[i], ringColors[i] );
  336. }
  337. bool bSel = 0; // draw unselected first
  338. for ( int j = 0; j < 2; j++ )
  339. {
  340. for ( int i = 0; i < count; i++ )
  341. {
  342. if ( selected[i] == bSel )
  343. {
  344. drawBlip( positions[i], colors[i], DOT_BLIP );
  345. }
  346. }
  347. bSel = 1;
  348. }
  349. }
  350. void GameTacMap::worldToTacMap( Stuff::Vector3D& world, gos_VERTEX& tac )
  351. {
  352. TacMap::worldToTacMap( world, left, top, right - left, bottom - top, tac );
  353. }
  354. void GameTacMap::initBuildings( unsigned char* data, int size )
  355. {
  356. if ( data )
  357. {
  358. long* pData = (long*)data;
  359. buildingCount = *pData++;
  360. if (buildingCount)
  361. {
  362. buildingPoints = new gos_VERTEX[buildingCount];
  363. gos_VERTEX* pTmp = buildingPoints;
  364. for ( int i = 0; i < buildingCount; ++i, pTmp++)
  365. {
  366. pTmp->x = *pData++ + left;
  367. pTmp->y = *pData++ + top;
  368. pTmp->z = 0;
  369. pTmp->argb = BUILDING_COLOR;
  370. pTmp->frgb = 0;
  371. pTmp->rhw = .5;
  372. pTmp->u = 0.f;
  373. pTmp->v = 0.f;
  374. }
  375. }
  376. }
  377. }
  378. void GameTacMap::drawSensor( const Stuff::Vector3D& pos, float radius, long color )
  379. {
  380. if ( color == 0 )
  381. return;
  382. gos_VERTEX sqare[4];
  383. if ( radius > 1 )
  384. radius += land->metersPerCell * 6.f; // a little fudge
  385. radius *= ((float)(right - left))/(land->metersPerCell * land->realVerticesMapSide * 3.f);
  386. for ( int i = 0; i < 4; ++i )
  387. {
  388. sqare[i].z = 0;
  389. sqare[i].rhw = .5;
  390. sqare[i].argb = color;
  391. sqare[i].frgb = 0;
  392. }
  393. worldToTacMap( (Stuff::Vector3D&)pos, sqare[0] );
  394. sqare[1].x = sqare[0].x;
  395. sqare[1].y = sqare[0].y + 1;
  396. sqare[2].x = sqare[0].x + 1;
  397. sqare[2].y = sqare[0].y;
  398. sqare[3].x = sqare[0].x + 1;
  399. sqare[3].y = sqare[0].y + 1;
  400. // need to draw that round thing
  401. Stuff::Vector2DOf< long > center;
  402. Stuff::Vector2DOf< long > radii;
  403. center.x = float2long(sqare[1].x);
  404. center.y = float2long(sqare[1].y);
  405. radii.x = 2.0f * float2long(radius+.5);
  406. radii.y = 2.0f * float2long(radius+.5);
  407. EllipseElement circle( center, radii, color, 0 );
  408. GUI_RECT rect = { left, top, right, bottom };
  409. circle.setClip( rect );
  410. circle.draw();
  411. }
  412. void GameTacMap::drawBlip( const Stuff::Vector3D& pos, long color, int type )
  413. {
  414. if ( color == 0 )
  415. return;
  416. gos_VERTEX triangle[4];
  417. gos_SetRenderState( gos_State_AlphaTest, 1);
  418. gos_SetRenderState( gos_State_Specular, 0);
  419. gos_SetRenderState( gos_State_Dither, 1);
  420. gos_SetRenderState( gos_State_Filter, gos_FilterBiLinear);
  421. gos_SetRenderState( gos_State_ZCompare, 0);
  422. gos_SetRenderState( gos_State_ZWrite, 0);
  423. unsigned long gosID = mcTextureManager->get_gosTextureHandle( blipHandle );
  424. gos_SetRenderState( gos_State_Texture, gosID );
  425. for ( int i = 0; i < 4; ++i )
  426. {
  427. triangle[i].z = 0;
  428. triangle[i].rhw = .5;
  429. triangle[i].argb = color;
  430. triangle[i].frgb = 0;
  431. triangle[i].u = 0.f;
  432. triangle[i].v = 0.f;
  433. }
  434. worldToTacMap( (Stuff::Vector3D&)pos, triangle[0] );
  435. triangle[0].x -= 2.f;
  436. triangle[1].x = triangle[0].x;
  437. triangle[2].x = triangle[3].x = triangle[0].x + 4.1f;
  438. triangle[0].y -= 2.f;
  439. triangle[3].y = triangle[0].y;
  440. triangle[1].y = triangle[2].y = triangle[0].y + 4.1f;
  441. triangle[2].u = triangle[3].u = .250001f;
  442. triangle[1].v = triangle[2].v = .250001f;
  443. gos_DrawQuads( triangle, 4 );
  444. }
  445. void GameTacMap::setPos( const GUI_RECT& newPos )
  446. {
  447. left = newPos.left;
  448. right = newPos.right;
  449. top = newPos.top;
  450. bottom = newPos.bottom;
  451. }
  452. //*************************************************************************************************
  453. // end of file ( TacMap.cpp )
  454. //*************************************************************************************************
  455. // end of file ( gameTacMap.cpp )