MissionBriefingScreen.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. #define MISSIONBRIEFINGSCREEN_CPP
  2. //===========================================================================//
  3. // Copyright (C) Microsoft Corporation. All rights reserved. //
  4. //===========================================================================//
  5. #include "MissionBriefingScreen.h"
  6. #include "MechBayScreen.h"
  7. #include "LogisticsData.h"
  8. #include "IniFile.h"
  9. #include "Packet.h"
  10. #include "..\resource.h"
  11. #include "Objective.h"
  12. #include "Multplyr.h"
  13. #include "ChatWindow.h"
  14. #include "gameSound.h"
  15. #define MAP_INDEX 32
  16. #define BUTTON_TEXT 34
  17. #define VIDEO_SCREEN 33
  18. #define RP_INDEX 1
  19. #define MN_MSG_PLAY 80
  20. #define MN_MSG_STOP 82
  21. #define MN_MSG_PAUSE 81
  22. MissionBriefingScreen::MissionBriefingScreen( )
  23. {
  24. status = RUNNING;
  25. LogisticsScreen::helpTextArrayID = 4;
  26. for ( int i = 0; i < MAX_OBJECTIVES; i++ )
  27. objectiveButtons[i] = NULL;
  28. }
  29. MissionBriefingScreen::~MissionBriefingScreen()
  30. {
  31. for ( int i = 0; i < MAX_OBJECTIVES; i++ )
  32. {
  33. if (objectiveButtons[i])
  34. {
  35. delete objectiveButtons[i];
  36. objectiveButtons[i] = NULL;
  37. }
  38. }
  39. missionListBox.destroy(); //NO Default destructor for aListBox. Just call destroy.
  40. }
  41. //-------------------------------------------------------------------------------------------------
  42. void MissionBriefingScreen::init( FitIniFile* file )
  43. {
  44. LogisticsScreen::init( *file, "Static", "Text", "Rect", "Button" );
  45. for ( int i= 0; i < buttonCount; i++ )
  46. buttons[i].setMessageOnRelease();
  47. missionListBox.init( rects[1].left(), rects[1].top(),
  48. rects[1].width(), rects[1].height() );
  49. missionListBox.setPressFX( -1 );
  50. missionListBox.setHighlightFX( -1 );
  51. missionListBox.setDisabledFX( -1 );
  52. getButton( MN_MSG_PLAY )->showGUIWindow( 0 );
  53. getButton( MN_MSG_STOP )->showGUIWindow( 0 );
  54. getButton( MN_MSG_PAUSE )->showGUIWindow( 0 );
  55. camera.init( statics[VIDEO_SCREEN].left(), statics[VIDEO_SCREEN].top(),
  56. statics[VIDEO_SCREEN].right(), statics[VIDEO_SCREEN].bottom() );
  57. }
  58. void MissionBriefingScreen::render(int xOffset, int yOffset )
  59. {
  60. missionListBox.move(xOffset, yOffset );
  61. missionListBox.render();
  62. missionListBox.move( -xOffset, -yOffset);
  63. camera.render();
  64. LogisticsScreen::render( xOffset, yOffset );
  65. for ( int i = 0; i < MAX_OBJECTIVES; i++ )
  66. {
  67. if ( objectiveButtons[i] )
  68. objectiveButtons[i]->render(xOffset, yOffset);
  69. }
  70. if ( !MPlayer )
  71. dropZoneButton.render(xOffset, yOffset);
  72. if ( MPlayer && ChatWindow::instance() )
  73. ChatWindow::instance()->render(xOffset, yOffset);
  74. }
  75. void MissionBriefingScreen::update()
  76. {
  77. if ( MPlayer || LogisticsData::instance->isSingleMission() )
  78. {
  79. getButton( MB_MSG_PREV )->disable( true );
  80. }
  81. else
  82. getButton( MB_MSG_PREV )->disable( false );
  83. int oldSel = missionListBox.GetSelectedItem();
  84. missionListBox.update();
  85. if ( userInput->isLeftClick() )
  86. {
  87. bClicked = true;
  88. for ( int i = 0; i < MAX_OBJECTIVES; i++ )
  89. {
  90. if ( objectiveButtons[i] &&
  91. objectiveButtons[i]->pointInside( userInput->getMouseX(), userInput->getMouseY () ) )
  92. {
  93. // find the item that has this objective
  94. for ( int j = 0; j < missionListBox.GetItemCount(); j++ )
  95. {
  96. if ( missionListBox.GetItem( j )->getID() == i )
  97. {
  98. missionListBox.SelectItem( j );
  99. break;
  100. }
  101. }
  102. }
  103. }
  104. }
  105. runTime += frameLength;
  106. long selItem = missionListBox.GetSelectedItem( );
  107. int ID = -1;
  108. if ( selItem != -1 )
  109. ID = missionListBox.GetItem( selItem )->getID();
  110. if ( selItem != -1 && oldSel != selItem )
  111. {
  112. bClicked = true;
  113. // set old selections back to white
  114. for ( int i= 0; i < missionListBox.GetItemCount(); i++ )
  115. {
  116. if ( missionListBox.GetItem( i )->getID() != -1 )
  117. {
  118. missionListBox.GetItem( i )->setColor( 0xffffffff );
  119. if ( objectiveButtons[missionListBox.GetItem( i )->getID()] )
  120. objectiveButtons[missionListBox.GetItem( i )->getID()]->setColor( 0xffffffff );
  121. }
  122. }
  123. if ( ID != -1 )
  124. {
  125. if ( objectiveModels[ID].Length() )
  126. {
  127. camera.setObject( objectiveModels[ID], modelTypes[ID], modelColors[ID][0],
  128. modelColors[ID][1], modelColors[ID][2] );
  129. camera.setScale( modelScales[ID] );
  130. soundSystem->playDigitalSample( LOG_VIDEOBUTTONS );
  131. statics[35].showGUIWindow( 0 );
  132. }
  133. else
  134. {
  135. camera.setObject( NULL, -1 );
  136. statics[35].showGUIWindow( true );
  137. }
  138. missionListBox.GetItem( selItem )->setColor( 0xffff0000 );
  139. if ( objectiveButtons[ID] )
  140. objectiveButtons[ID]->setColor( 0xffff0000 );
  141. }
  142. }
  143. if ( !bClicked && runTime > 3.0 ) // every second switch selection until user clicks
  144. {
  145. runTime = 0;
  146. // turn old sel back into white
  147. if ( selItem != -1 && ID != -1 )
  148. {
  149. missionListBox.GetItem( selItem )->setColor( 0xffffffff );
  150. if ( objectiveButtons[ID] )
  151. objectiveButtons[ID]->setColor( 0xffffffff );
  152. }
  153. selItem++;
  154. // wrap if necessary
  155. if ( selItem >= missionListBox.GetItemCount() )
  156. selItem = 0;
  157. // find next viable item
  158. while( true )
  159. {
  160. if ( selItem >= missionListBox.GetItemCount() )
  161. {
  162. selItem = -1;
  163. break;
  164. }
  165. else if ( missionListBox.GetItem(selItem)->getID() == -1 )
  166. selItem++;
  167. else
  168. break;
  169. }
  170. missionListBox.SelectItem( selItem );
  171. if ( selItem != -1 )
  172. {
  173. int ID = missionListBox.GetItem(selItem)->getID();
  174. if ( ID != -1 )
  175. {
  176. missionListBox.GetItem( selItem )->setColor( 0xffff0000 );
  177. if ( objectiveButtons[ID] )
  178. objectiveButtons[ID]->setColor( 0xffff0000 );
  179. camera.setObject( objectiveModels[ID], modelTypes[ID], modelColors[ID][0],
  180. modelColors[ID][1], modelColors[ID][2]);
  181. camera.setScale( modelScales[ID] );
  182. if ( objectiveModels[ID].Length() )
  183. statics[35].showGUIWindow( 0 );
  184. else
  185. statics[35].showGUIWindow( 1 );
  186. }
  187. else
  188. {
  189. camera.setObject( NULL, -1 );
  190. statics[35].showGUIWindow( 1 );
  191. }
  192. }
  193. }
  194. camera.update();
  195. if ( !MPlayer || !ChatWindow::instance()->pointInside(userInput->getMouseX(), userInput->getMouseY()) )
  196. LogisticsScreen::update();
  197. if ( MPlayer && ChatWindow::instance() )
  198. {
  199. if ( ChatWindow::instance()->pointInside(userInput->getMouseX(), userInput->getMouseY()) )
  200. textObjects[helpTextArrayID].setText( "" );
  201. ChatWindow::instance()->update();
  202. }
  203. }
  204. long MissionBriefingScreen::getMissionTGA( const char* missionName )
  205. {
  206. if ( !missionName )
  207. return 0;
  208. // do I need to open the file? I guess so, if this proves too slow,
  209. // it could be done when a stage is completed
  210. FullPathFileName path;
  211. path.init( missionPath, missionName, ".pak" );
  212. if ( 1 == fileExists( path ) )
  213. {
  214. // big hack here for some reason we can open files while they're being transferred.
  215. HANDLE hFile = CreateFile( path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
  216. int error = GetLastError();
  217. if ( hFile == INVALID_HANDLE_VALUE )
  218. return 0;
  219. CloseHandle( hFile );
  220. }
  221. // read the tga out of the pak file
  222. PacketFile file;
  223. if ( NO_ERR == file.open( path ) ) // in case file has just been created
  224. {
  225. if ( file.getNumPackets() > 3 )
  226. {
  227. file.seekPacket(3);
  228. long size = file.getPacketSize( );
  229. BYTE* mem = new BYTE[size];
  230. file.readPacket( 3, mem );
  231. TGAFileHeader* pHeader = (TGAFileHeader*)mem;
  232. long bmpWidth = pHeader->width;
  233. long bmpHeight = pHeader->height;
  234. flipTopToBottom( (BYTE*)(pHeader + 1), pHeader->pixel_depth, bmpWidth, bmpHeight );
  235. // set up the texture
  236. long tmpMapTextureHandle = mcTextureManager->textureFromMemory( (unsigned long*)(pHeader+1), gos_Texture_Solid, 0, bmpWidth );
  237. delete mem;
  238. return tmpMapTextureHandle;
  239. }
  240. }
  241. return 0;
  242. }
  243. void MissionBriefingScreen::begin()
  244. {
  245. missionListBox.removeAllItems( true );
  246. runTime = 0;
  247. bClicked = 0;
  248. statics[VIDEO_SCREEN].setColor( 0 );
  249. memset( objectiveButtons, 0, sizeof ( aObject* ) * MAX_OBJECTIVES );
  250. // need to set up all pertinent mission info
  251. EString missionName = LogisticsData::instance->getCurrentMission();
  252. long tmpMapTextureHandle = getMissionTGA( missionName );
  253. statics[MAP_INDEX].setTexture( tmpMapTextureHandle );
  254. statics[MAP_INDEX].setUVs( 0, 127, 127, 0 );
  255. statics[MAP_INDEX].setColor( 0xffffffff );
  256. // need to get all the objectives and stuff
  257. FullPathFileName fitPath;
  258. fitPath.init( missionPath, missionName, ".fit" );
  259. FitIniFile fitFile;
  260. fitFile.open( fitPath );
  261. // put initial divider in list box
  262. addItem(IDS_MN_DIVIDER, 0xff005392, -1);
  263. fitFile.seekBlock( "MissionSettings" );
  264. long result = fitFile.seekBlock( "MissionSettings" );
  265. Assert( result == NO_ERR, 0, "Coudln't find the mission settings block in the mission file" );
  266. bool bRes;
  267. result = fitFile.readIdBoolean( "MissionNameUseResourceString", bRes );
  268. Assert( result == NO_ERR, 0, "couldn't find the MissionNameUseResourceString" );
  269. if ( bRes )
  270. {
  271. unsigned long ulRes;
  272. result = fitFile.readIdULong( "MissionNameResourceStringID", ulRes );
  273. Assert( result == NO_ERR, 0, "couldn't find the MissionNameResourceStringID" );
  274. addItem(ulRes, 0xff005392, -1);
  275. }
  276. else
  277. {
  278. char missionName[256];
  279. fitFile.readIdString( "MissionName", missionName, 255 );
  280. addLBItem( missionName, 0xff005392, -1 );
  281. }
  282. addItem(IDS_MN_DIVIDER, 0xff005392, -1);
  283. addItem( IDS_MN_MISSION_OBJECTIVES, 0xff005392, -1 );
  284. addItem(IDS_MN_DIVIDER, 0xff005392, -1);
  285. // put in primary objectives
  286. fitFile.seekBlock( "Team0Objectives" );
  287. unsigned long objectiveCount;
  288. fitFile.readIdULong( "NumObjectives", objectiveCount );
  289. bool bHasSecondary = 0;
  290. int count = 0;
  291. fitFile.seekBlock( "Terrain" );
  292. float terrainExtentX;
  293. float terrainExtentY;
  294. fitFile.readIdFloat( "TerrainMinX", terrainExtentX );
  295. if ( !terrainExtentX )
  296. terrainExtentX = 120 * 128;
  297. fitFile.readIdFloat( "TerrainMinY", terrainExtentY );
  298. if ( !terrainExtentY )
  299. terrainExtentY = 120 * 128;
  300. CObjectives Objectives(0/*alignment*/);
  301. /*Note that ObjectManager is probably NULL as these objectives are read, so it's not
  302. cool to call any of the Status() functions of this instance of objectives (access violation
  303. may ensue).*/
  304. Objectives.Read(&fitFile);
  305. gosASSERT( Objectives.Count() < MAX_OBJECTIVES );
  306. int buttonCount = 0;
  307. for ( int j = 1; j < 3; j++ )
  308. {
  309. CObjectives::EIterator it = Objectives.Begin();
  310. buttonCount = 0;
  311. for ( int i = 0; i < Objectives.Count(); i++, it++ )
  312. {
  313. CObjective *pObjective = (*it);
  314. if ( (!pObjective->IsHiddenTrigger()) && (pObjective->IsActive()) )
  315. {
  316. if ( pObjective->Priority() == j )
  317. {
  318. addObjectiveButton( pObjective->MarkerX(), pObjective->MarkerY(), buttonCount,pObjective->Priority(), fabs(terrainExtentX),
  319. fabs(terrainExtentY), pObjective->DisplayMarker());
  320. if ( j == 0 )
  321. {
  322. bHasSecondary = true;
  323. if ( i == 0 )
  324. addItem( IDS_MN_DIVIDER, 0xff005392, -1 );
  325. }
  326. addLBItem( (pObjective->LocalizedDescription()).Data(), 0xffffffff, count );
  327. objectiveModels[count] = (pObjective->ModelName()).Data();
  328. modelTypes[count] = pObjective->ModelType();
  329. modelColors[count][0] = pObjective->ModelBaseColor();
  330. modelColors[count][1] = pObjective->ModelHighlightColor();
  331. modelColors[count][2] = pObjective->ModelHighlightColor2();
  332. modelScales[count] = pObjective->ModelScale();
  333. count++;
  334. buttonCount++;
  335. }
  336. }
  337. }
  338. }
  339. addItem( IDS_MN_DIVIDER, 0xff005392, -1 );
  340. fitFile.seekBlock( "MissionSettings" );
  341. char blurb[4096];
  342. result = fitFile.readIdString("Blurb", blurb, 4095 );
  343. bool tmpBool = false;
  344. result = fitFile.readIdBoolean("BlurbUseResourceString", tmpBool);
  345. if (NO_ERR == result && tmpBool )
  346. {
  347. unsigned long tmpInt = 0;
  348. result = fitFile.readIdULong("BlurbResourceStringID", tmpInt);
  349. if (NO_ERR == result)
  350. {
  351. cLoadString( tmpInt, blurb, 2047 );
  352. }
  353. }
  354. addLBItem( blurb, 0xff005392, -1 );
  355. int RP = LogisticsData::instance->getCBills();
  356. char text[32];
  357. sprintf( text, "%ld ", RP );
  358. textObjects[RP_INDEX].setText( text );
  359. // need to find a drop zone, because our designers were never convinced to place
  360. // 'em explicitly, we need to do it for them
  361. int i = 1;
  362. while( true )
  363. {
  364. char blockName[32];
  365. sprintf( blockName, "Part%ld", i );
  366. i++;
  367. if ( NO_ERR != fitFile.seekBlock( blockName ) )
  368. break;
  369. bool bPlayer = 0;
  370. fitFile.readIdBoolean( "PlayerPart", bPlayer );
  371. if ( bPlayer )
  372. {
  373. float fX;
  374. float fY;
  375. fitFile.readIdFloat( "PositionX", fX );
  376. fitFile.readIdFloat( "PositionY", fY );
  377. setupDropZone( fX, fY, fabs(terrainExtentX), fabs(terrainExtentY) );
  378. break;
  379. }
  380. }
  381. statics[BUTTON_TEXT].showGUIWindow( 0 );
  382. status = RUNNING;
  383. }
  384. void MissionBriefingScreen::setupDropZone( float fX, float fY, float mapWidth, float mapHeight )
  385. {
  386. dropZoneButton = statics[BUTTON_TEXT];
  387. float bmpX = statics[MAP_INDEX].width();
  388. float bmpY = statics[MAP_INDEX].height();
  389. // in terms of map, this is where the button goes
  390. float xLoc = fX/mapWidth * bmpX/2.f;
  391. float yLoc = -fY/mapHeight * bmpY/2.f;
  392. // offset by the map...
  393. xLoc += statics[MAP_INDEX].globalX() + bmpX/2.f;
  394. yLoc += statics[MAP_INDEX].globalY() + bmpY/2.f;
  395. dropZoneButton.resize( 18, 18 );
  396. dropZoneButton.setUVs( 100, 100, 118, 118);
  397. dropZoneButton.moveTo( xLoc, yLoc );
  398. dropZoneButton.showGUIWindow( true );
  399. }
  400. void MissionBriefingScreen::addObjectiveButton( float fX, float fY, int count, int priority,
  401. float mapWidth, float mapHeight, bool display )
  402. {
  403. float lineOffset = 0;
  404. if ( priority == 1 )
  405. {
  406. count += 12;
  407. }
  408. float bmpX = statics[MAP_INDEX].width();
  409. float bmpY = statics[MAP_INDEX].height();
  410. // in terms of map, this is where the button goes
  411. float xLoc = fX/mapWidth * bmpX/2.f;
  412. float yLoc = -fY/mapHeight * bmpY/2.f;
  413. // offset by the map...
  414. xLoc += statics[MAP_INDEX].globalX() + bmpX/2.f;
  415. yLoc += statics[MAP_INDEX].globalY() + bmpY/2.f;
  416. aObject* pButtonText = new aObject;
  417. *pButtonText = statics[BUTTON_TEXT];
  418. if (display)
  419. pButtonText->showGUIWindow( true );
  420. else
  421. pButtonText->showGUIWindow( false );
  422. // need to reset the uv's based on count....
  423. float textWidth = pButtonText->width();
  424. float textHeight = pButtonText->height();
  425. lineOffset *= textHeight;
  426. int itemsPerLine = 128/textWidth;
  427. int iIndex = count % itemsPerLine;
  428. int jIndex = count / itemsPerLine;
  429. pButtonText->setUVs( iIndex * textWidth, jIndex * textHeight + lineOffset,
  430. (iIndex+1) * textWidth, (jIndex+1) * textHeight + lineOffset );
  431. pButtonText->moveTo( xLoc, yLoc );
  432. for ( int i = 0; i < MAX_OBJECTIVES; i++ )
  433. {
  434. if ( !objectiveButtons[i])
  435. {
  436. objectiveButtons[i] = pButtonText;
  437. break;
  438. }
  439. }
  440. //If there are too many objectives, don't leave the RAM lying around!
  441. if (i >= MAX_OBJECTIVES)
  442. {
  443. delete pButtonText;
  444. pButtonText = NULL;
  445. }
  446. }
  447. /*int MissionBriefingScreen::addLBItem( FitIniFile& file, const char* itemName, unsigned long color, int ID)
  448. {
  449. char buffer[1024];
  450. file.readIdString( itemName, buffer, 1023 );
  451. return addLBItem( buffer, color, ID);
  452. }*/
  453. int MissionBriefingScreen::addLBItem( const char* text, unsigned long color, int ID)
  454. {
  455. aTextListItem* pEntry = new aTextListItem( IDS_MN_LB_FONT );
  456. pEntry->setID( ID );
  457. pEntry->resize( missionListBox.width() - missionListBox.getScrollBarWidth() - 10,
  458. pEntry->height() );
  459. pEntry->setText( text );
  460. pEntry->setColor( color );
  461. pEntry->sizeToText();
  462. pEntry->forceToTop(true);
  463. return missionListBox.AddItem( pEntry );
  464. }
  465. int MissionBriefingScreen::addItem( int ID, unsigned long color, int LBid)
  466. {
  467. aTextListItem* pEntry = new aTextListItem( IDS_MN_LB_FONT );
  468. pEntry->setID( LBid );
  469. pEntry->resize( missionListBox.width() - missionListBox.getScrollBarWidth() - 10,
  470. pEntry->height() );
  471. pEntry->setText( ID );
  472. pEntry->setColor( color );
  473. return missionListBox.AddItem( pEntry );
  474. }
  475. void MissionBriefingScreen::end()
  476. {
  477. // statics[MAP_INDEX].setTexture( (long)0 );
  478. // statics[MAP_INDEX].setColor( 0 );
  479. camera.setMech( NULL );
  480. }
  481. int MissionBriefingScreen::handleMessage( unsigned long msg, unsigned long who )
  482. {
  483. switch( who )
  484. {
  485. case MB_MSG_NEXT:
  486. status = NEXT;
  487. break;
  488. case MB_MSG_PREV:
  489. status = PREVIOUS;
  490. break;
  491. case MN_MSG_PLAY:
  492. break;
  493. case MN_MSG_STOP:
  494. break;
  495. case MN_MSG_PAUSE:
  496. break;
  497. case MB_MSG_MAINMENU:
  498. status = MAINMENU;
  499. break;
  500. }
  501. return 0;
  502. }
  503. //*************************************************************************************************
  504. // end of file ( MissionBriefingScreen.cpp )