MechBayScreen.cpp 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /*************************************************************************************************\
  2. MechBayScreen.cpp : Implementation of the MechBayScreen component.
  3. //---------------------------------------------------------------------------//
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. //===========================================================================//
  6. \*************************************************************************************************/
  7. #include "MechBayScreen.h"
  8. #include "LogisticsMech.h"
  9. #include "LogisticsData.h"
  10. #include "LogisticsMechIcon.h"
  11. #include "..\resource.h"
  12. #include "SimpleCamera.h"
  13. #include "windows.h"
  14. #include "gameSound.h"
  15. #include "multPlyr.h"
  16. #include "ChatWindow.h"
  17. #include "Prefs.h"
  18. MechBayScreen* MechBayScreen::s_instance = NULL;
  19. MechBayScreen::MechBayScreen() : mechListBox( 1, 0 )
  20. {
  21. pCurMech = NULL;
  22. pIcons = NULL;
  23. status = LogisticsScreen::RUNNING;
  24. s_instance = this;
  25. forceGroupCount = 0;
  26. mechCamera = new SimpleCamera;
  27. addWeightAmount = 0;
  28. removeWeightAmount = 0;
  29. pDragMech = 0;
  30. dragLeft = 0;
  31. helpTextArrayID = 13;
  32. }
  33. MechBayScreen::~MechBayScreen()
  34. {
  35. if ( mechCamera )
  36. delete mechCamera;
  37. if ( pIcons )
  38. delete[] pIcons;
  39. mechListBox.destroy();
  40. }
  41. void MechBayScreen::init(FitIniFile* file)
  42. {
  43. // init button, texts, statics, rects
  44. LogisticsScreen::init( *file, "MechBayStatic", "MechBayTextEntry", "MechBayRect", "MechBayButton" );
  45. // initialize the list box
  46. mechListBox.init();
  47. mechListBox.setHelpID( IDS_HELP_MECHSTORAGE );
  48. loadoutListBox.init( rects[3].left(), rects[3].top(), rects[3].width(), rects[3].height() );
  49. // fill the mech list box
  50. ((aObject*)&mechListBox)->init( rects[0].left(), rects[0].top(), rects[0].width(), rects[0].height() );
  51. // initialize little icons
  52. FitIniFile iconFile;
  53. char path[256];
  54. strcpy( path, artPath );
  55. strcat( path, "mcl_gn_deploymentteams.fit" );
  56. strlwr( path );
  57. if ( NO_ERR != iconFile.open( path ) )
  58. {
  59. gosASSERT( "couldn't open the MCL_GN_DevploymentTeams file" );
  60. return;
  61. }
  62. LogisticsMechIcon::init(iconFile);
  63. pIcons = new LogisticsMechIcon[ICON_COUNT];
  64. int count = 0;
  65. long x = 0;
  66. long y = 0;
  67. for ( int j = 0; j < ICON_COUNT_Y; j++ )
  68. {
  69. for ( int i = 0; i < ICON_COUNT_X; i++ )
  70. {
  71. pIcons[count].setMech( 0 );
  72. pIcons[count].move( x, y );
  73. x+= pIcons[count].width();
  74. x+=4;
  75. count++;
  76. }
  77. y+= pIcons[i].height();
  78. y += 5;
  79. x = 0;
  80. }
  81. mechListBox.drawCBills( 0 );
  82. mechListBox.setScrollBarOrange();
  83. // initialize the attribute meeters
  84. attributeMeters[0].init( file, "AttributeMeter0" );
  85. attributeMeters[1].init( file, "AttributeMeter1" );
  86. attributeMeters[2].init( file, "AttributeMeter2" );
  87. dropWeightMeter.init( file, "DropWeightMeter" );
  88. file->readIdLong( "RayCenterX", weightCenterX );
  89. file->readIdLong( "RayCenterY", weightCenterY );
  90. file->readIdLong( "RayStartColor ", weightStartColor );
  91. file->readIdLong( "RayEndColor ", weightEndColor );
  92. file->seekBlock( "weightAddAnimation" );
  93. addWeightAnim.init( file, "" );
  94. file->seekBlock( "weightRemoveAnimation" );
  95. removeWeightAnim.init( file, "" );
  96. file->seekBlock( "FRectAnim" );
  97. mechCamera->init( rects[1].left(), rects[1].top(), rects[2].right(), rects[1].bottom() );
  98. for ( int i= 0; i < buttonCount; i++ )
  99. buttons[i].setMessageOnRelease();
  100. textObjects[7].setText( "" );
  101. textObjects[8].setText( "" );
  102. textObjects[9].setText( "" );
  103. textObjects[10].setText( "" );
  104. textObjects[11].setText( "" );
  105. textObjects[12].setText( "" );
  106. textObjects[14].setText( "" );
  107. for ( i = 0; i < 3; i++ )
  108. {
  109. attributeMeters[i].setValue(0);
  110. }
  111. setMech( NULL, 0 );
  112. }
  113. void MechBayScreen::begin()
  114. {
  115. status = RUNNING;
  116. pDragMech = NULL;
  117. mechListBox.removeAllItems( true );
  118. reinitMechs();
  119. int mechCount[256];
  120. memset( mechCount, 0, sizeof ( int ) * 256 );
  121. bool bCurMechIsValid = 0;
  122. // initialize both the inventory and icon lists
  123. EList< LogisticsMech*, LogisticsMech* > mechList;
  124. LogisticsData::instance->getInventory( mechList );
  125. for ( EList< LogisticsMech*, LogisticsMech* >::EIterator iter = mechList.Begin();
  126. !iter.IsDone(); iter++ )
  127. {
  128. if ( *iter == pCurMech )
  129. bCurMechIsValid = true;
  130. if ( !(*iter)->getForceGroup() )
  131. {
  132. bool bFound = 0;
  133. for ( int i = 0; i < mechListBox.GetItemCount(); i++ )
  134. {
  135. if ( ((MechListBoxItem*)mechListBox.GetItem(i))->getMech()->getVariant()
  136. == (*iter)->getVariant() )
  137. bFound = true;
  138. }
  139. if ( !bFound )
  140. {
  141. MechListBoxItem* item = new MechListBoxItem( (*iter), 1 );
  142. mechListBox.AddItem( item );
  143. }
  144. }
  145. }
  146. // reset the old mech to NULL to make sure everything gets set
  147. mechListBox.drawCBills( 0 );
  148. mechListBox.setOrange( true );
  149. if ( !pCurMech || !bCurMechIsValid )
  150. {
  151. if ( !selectFirstFGItem() )
  152. {
  153. if ( !selectFirstViableLBMech() )
  154. setMech( NULL );
  155. }
  156. }
  157. else
  158. {
  159. LogisticsMech* pMech = pCurMech;
  160. setMech( NULL ); // need to make sure the guy is still running
  161. setMech( pMech );
  162. bool bFound = 0;
  163. for ( int i = 0; i < mechListBox.GetItemCount(); i++ )
  164. {
  165. MechListBoxItem* pItem = (MechListBoxItem*)mechListBox.GetItem( i );
  166. if ( pItem && pItem->getMech() == pCurMech )
  167. {
  168. mechListBox.SelectItem( i );
  169. bFound = true;
  170. }
  171. }
  172. if ( !bFound )
  173. {
  174. for ( int i = 0; i < ICON_COUNT; i++ )
  175. {
  176. if ( pIcons[i].getMech() == pMech )
  177. {
  178. pIcons[i].select( true );
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. }
  185. void MechBayScreen::render(int xOffset, int yOffset)
  186. {
  187. mechListBox.move( xOffset, yOffset );
  188. mechListBox.render();
  189. mechListBox.move( -xOffset, -yOffset );
  190. loadoutListBox.move( xOffset, yOffset );
  191. loadoutListBox.render();
  192. loadoutListBox.move( -xOffset, -yOffset );
  193. if ( !xOffset && !yOffset && pCurMech)
  194. mechCamera->render();
  195. for ( int i = 0; i < 3; i++ )
  196. {
  197. attributeMeters[i].render(xOffset, yOffset);
  198. }
  199. drawWeightMeter(xOffset, yOffset);
  200. LogisticsScreen::render(xOffset, yOffset);
  201. for ( i = 0; i < ICON_COUNT; i++ )
  202. {
  203. pIcons[i].render( xOffset, yOffset );
  204. }
  205. if ( MPlayer && ChatWindow::instance() )
  206. ChatWindow::instance()->render(xOffset, yOffset);
  207. if ( pDragMech )
  208. dragIcon.render();
  209. }
  210. void MechBayScreen::drawWeightMeter(long xOffset, long yOffset)
  211. {
  212. // there are 20 rays, each 9 degrees
  213. // they should be 50 pixels long
  214. float currentDropWeight = LogisticsData::instance->getCurrentDropWeight();
  215. float maxDropWeight = LogisticsData::instance->getMaxDropWeight();
  216. long numAddBars = 0;
  217. long numRemoveBars = 0;
  218. long addColor = 0;
  219. long removeColor = 0;
  220. long numberOfBars = 20;
  221. if ( maxDropWeight != 0 )
  222. {
  223. float percent = currentDropWeight/maxDropWeight;
  224. percent *= 20.f;
  225. numberOfBars = percent + .5;
  226. }
  227. if ( addWeightAnim.isAnimating() && !addWeightAnim.isDone() )
  228. {
  229. addColor = addWeightAnim.getColor();
  230. float percent = (currentDropWeight - addWeightAmount) / maxDropWeight;
  231. percent *= 20.f;
  232. numAddBars = percent + .5;
  233. numAddBars = numberOfBars - numAddBars;
  234. }
  235. if ( removeWeightAnim.isAnimating() && !removeWeightAnim.isDone() )
  236. {
  237. addColor = removeWeightAnim.getColor();
  238. float percent = removeWeightAmount / maxDropWeight;
  239. percent *= 20.f;
  240. numRemoveBars = percent + .5;
  241. }
  242. gos_VERTEX v[3];
  243. for ( int i = 0; i <3; i++ )
  244. {
  245. v[i].u = 0.f;
  246. v[i].v = 0.f;
  247. v[i].rhw = .5;
  248. v[i].z = 0.f;
  249. v[i].argb = 0;
  250. v[i].frgb = 0;
  251. v[i].x = weightCenterX + xOffset;
  252. v[i].y = weightCenterY + yOffset;
  253. }
  254. float curArc = 180.f;
  255. float curX = 50.f * cos( DEGREES_TO_RADS * curArc );
  256. float curY = 50.f * sin( DEGREES_TO_RADS * curArc );
  257. for ( i= 0; i < numberOfBars + numRemoveBars; i++ )
  258. {
  259. v[1].x = curX + weightCenterX + xOffset;
  260. v[1].y = curY + weightCenterY + yOffset;
  261. curArc += 9.f;
  262. curX = 50.f * cos( DEGREES_TO_RADS * curArc );
  263. curY = 50.f * sin( DEGREES_TO_RADS * curArc );
  264. v[2].x = curX + weightCenterX + xOffset;
  265. v[2].y = curY + weightCenterY + yOffset;
  266. if ( i >= numberOfBars - numAddBars )
  267. v[0].argb = v[1].argb = v[2].argb = addColor;
  268. else if ( i >= numberOfBars )
  269. v[0].argb = v[1].argb = v[2].argb = removeColor;
  270. else
  271. v[0].argb = v[1].argb = v[2].argb = interpolateColor( weightStartColor, weightEndColor, i * .05 );
  272. gos_DrawTriangles( v, 3 );
  273. }
  274. dropWeightMeter.render(xOffset, yOffset);
  275. }
  276. void MechBayScreen::update()
  277. {
  278. mechListBox.disableItemsThatCanNotGoInFG();
  279. if ( !pIcons[0].getMech() )
  280. getButton( MB_MSG_REMOVE )->disable( true );
  281. // update current text
  282. char str[64];
  283. // RP
  284. sprintf( str, "%ld ", LogisticsData::instance->getCBills() );
  285. textObjects[1].setText( str );
  286. long mouseX = userInput->getMouseX();
  287. long mouseY = userInput->getMouseY();
  288. if ( userInput->isLeftClick() && dropWeightMeter.pointInside( mouseX, mouseY ) )
  289. {
  290. soundSystem->playDigitalSample( LOG_WRONGBUTTON );
  291. }
  292. // current drop weight
  293. char tmpStr[128];
  294. cLoadString( IDS_MB_WEIGHT, tmpStr, 63 );
  295. long currentDropWeight = LogisticsData::instance->getCurrentDropWeight();
  296. long maxDropWeight = LogisticsData::instance->getMaxDropWeight();
  297. sprintf( str, tmpStr, currentDropWeight, maxDropWeight );
  298. textObjects[6].setText( str );
  299. // update drag and drop
  300. // must be done before Icon's are updated, or we can get out of sync
  301. if ( pDragMech )
  302. {
  303. dragIcon.moveTo( userInput->getMouseX() - dragIcon.width() / 2,
  304. userInput->getMouseY() - dragIcon.height() / 2 );
  305. bool bLeft = 0;
  306. bool bRight = 0;
  307. GUI_RECT testRect;
  308. testRect.left = mechListBox.globalX();
  309. testRect.right = mechListBox.globalX() + mechListBox.width();
  310. testRect.top = mechListBox.globalY();
  311. testRect.bottom = mechListBox.globalY() + mechListBox.height();
  312. if ( dragIcon.rectIntersect( testRect ) )
  313. {
  314. // set the focus
  315. } bRight = true;
  316. testRect.left = pIcons[0].globalX();
  317. testRect.right = pIcons[ICON_COUNT - 1].globalX() + pIcons[0].width();
  318. testRect.top = pIcons[0].globalY();
  319. testRect.bottom = pIcons[ICON_COUNT-1].globalY() + pIcons[0].height();
  320. if ( dragIcon.rectIntersect( testRect ) )
  321. {
  322. bLeft = true;
  323. }
  324. else
  325. bLeft = 0;
  326. if ( userInput->leftMouseReleased() || userInput->isLeftDoubleClick() )
  327. {
  328. if ( dragLeft )
  329. {
  330. if ( bLeft )
  331. {
  332. LogisticsData::instance->removeMechFromForceGroup( pDragMech, false );
  333. LogisticsData::instance->addMechToForceGroup( pDragMech, forceGroupCount+1 );
  334. forceGroupCount++;
  335. reinitMechs();
  336. }
  337. else
  338. {
  339. if ( 0 == LogisticsData::instance->getVariantsInInventory( pDragMech->getVariant(), 0 ) )
  340. {
  341. MechListBoxItem* item = new MechListBoxItem( pDragMech, 0 );
  342. int index = mechListBox.AddItem( item );
  343. mechListBox.SelectItem( index );
  344. }
  345. LogisticsData::instance->removeMechFromForceGroup( pDragMech, true );
  346. forceGroupCount--;
  347. reinitMechs();
  348. removeWeightAmount = pDragMech->getMaxWeight();
  349. removeWeightAnim.begin();
  350. addWeightAnim.end();
  351. }
  352. }
  353. else
  354. {
  355. if ( bLeft )
  356. {
  357. reinitMechs();
  358. addWeightAmount = pDragMech->getMaxWeight();
  359. addWeightAnim.begin();
  360. removeWeightAnim.end();
  361. }
  362. else
  363. {
  364. if ( 0 == LogisticsData::instance->getVariantsInInventory( pDragMech->getVariant(), 0 ) )
  365. {
  366. MechListBoxItem* item = new MechListBoxItem( pDragMech, 0 );
  367. int index = mechListBox.AddItem( item );
  368. mechListBox.SelectItem( index );
  369. }
  370. LogisticsData::instance->removeMechFromForceGroup( pDragMech, true );
  371. reinitMechs();
  372. }
  373. }
  374. pDragMech = 0;
  375. }
  376. }
  377. // update icon selection
  378. int newSel = -1;
  379. int oldSel = -1;
  380. int removeMech = -1;
  381. for ( int i = 0; i < ICON_COUNT; i++ )
  382. {
  383. pIcons[i].update();
  384. if ( pIcons[i].justSelected() )
  385. newSel = i;
  386. else if ( pIcons[i].isSelected() )
  387. oldSel = i;
  388. bool bInside = pIcons[i].pointInside( userInput->getMouseX(), userInput->getMouseY() );
  389. if ( bInside && userInput->isLeftDoubleClick() && pIcons[i].getMech() )
  390. {
  391. removeMech = i;
  392. }
  393. else if ( userInput->isLeftDrag()
  394. && pIcons[i].pointInside( userInput->getMouseDragX(), userInput->getMouseDragY() ) )
  395. {
  396. beginDrag( pIcons[i].getMech() );
  397. }
  398. }
  399. if ( newSel != -1 )
  400. {
  401. if ( oldSel != -1 )
  402. pIcons[oldSel].select( 0 );
  403. mechListBox.SelectItem( -1 );
  404. }
  405. if ( removeMech != -1 )
  406. {
  407. removeSelectedMech();
  408. }
  409. if ( !MPlayer || !ChatWindow::instance()->pointInside(userInput->getMouseX(), userInput->getMouseY()) )
  410. LogisticsScreen::update();
  411. if ( newSel == -1 && oldSel == -1 )
  412. {
  413. // disable the remove button
  414. getButton( MB_MSG_REMOVE )->disable(1);
  415. }
  416. else
  417. getButton( MB_MSG_REMOVE )->disable(0);
  418. // update list box,
  419. oldSel = mechListBox.GetSelectedItem();
  420. mechListBox.update();
  421. newSel = mechListBox.GetSelectedItem( );
  422. // did anything change?
  423. if ( oldSel != newSel && newSel != -1)
  424. {
  425. unselectDeploymentTeam();
  426. }
  427. // component list box
  428. loadoutListBox.update();
  429. addWeightAnim.update();
  430. removeWeightAnim.update();
  431. LogisticsMech* pTmp = mechListBox.getCurrentMech();
  432. if ( !pTmp )
  433. {
  434. pTmp = getFGSelMech();
  435. }
  436. if ( pTmp )
  437. setMech( pTmp, 0);
  438. // update buttons!
  439. if ( newSel == -1 || !LogisticsData::instance->canAddMechToForceGroup( mechListBox.getCurrentMech() ) )
  440. {
  441. // disable the add button
  442. getButton( MB_MSG_ADD )->disable(1);
  443. }
  444. else
  445. getButton( MB_MSG_ADD )->disable(0);
  446. if ( MPlayer && ( !MPlayer->missionSettings.variants || !pCurMech ) )
  447. {
  448. getButton( MB_MSG_CHANGE_LOADOUT )->disable( true );
  449. }
  450. else if ( LogisticsData::instance->skipPurchasing() )
  451. {
  452. getButton( MB_MSG_CHANGE_LOADOUT )->disable( true );
  453. getButton( MB_MSG_BUY )->disable( true );
  454. }
  455. else
  456. {
  457. getButton( MB_MSG_CHANGE_LOADOUT )->disable( false );
  458. getButton( MB_MSG_BUY )->disable( false );
  459. if ( !pCurMech )
  460. getButton( MB_MSG_CHANGE_LOADOUT )->disable( true );
  461. else
  462. {
  463. getButton( MB_MSG_CHANGE_LOADOUT )->disable( false );
  464. mechCamera->update();
  465. }
  466. }
  467. if ( MPlayer && ChatWindow::instance() )
  468. ChatWindow::instance()->update();
  469. }
  470. int MechBayScreen::handleMessage( unsigned long message, unsigned long who )
  471. {
  472. if ( status != RUNNING )
  473. return 0;
  474. switch( who )
  475. {
  476. case MB_MSG_NEXT:
  477. status = NEXT;
  478. break;
  479. case MB_MSG_PREV:
  480. status = PREVIOUS;
  481. break;
  482. case MB_MSG_ADD:
  483. addSelectedMech();
  484. soundSystem->playDigitalSample( LOG_SELECT );
  485. break;
  486. case MB_MSG_REMOVE:
  487. removeSelectedMech();
  488. break;
  489. case MB_MSG_BUY:
  490. status = UP;
  491. break;
  492. case MB_MSG_CHANGE_LOADOUT:
  493. status = DOWN;
  494. if ( pCurMech )
  495. {
  496. LogisticsData::instance->setMechToModify( pCurMech );
  497. }
  498. break;
  499. case MB_MSG_BUY_SELL:
  500. break;
  501. case MB_MSG_MAINMENU:
  502. status = MAINMENU;
  503. break;
  504. }
  505. return 0;
  506. }
  507. void MechBayScreen::addSelectedMech()
  508. {
  509. if ( mechListBox.getCurrentMech() )
  510. {
  511. if ( !LogisticsData::instance->canAddMechToForceGroup( mechListBox.getCurrentMech() ) )
  512. return;
  513. if ( NO_ERR != LogisticsData::instance->addMechToForceGroup( mechListBox.getCurrentMech(),
  514. forceGroupCount + 1 ) )
  515. {
  516. // its already in the force group, add probably called 2x'2
  517. return;
  518. }
  519. if ( forceGroupCount > 11 )
  520. return;
  521. unselectDeploymentTeam();
  522. forceGroupCount++;
  523. reinitMechs();
  524. addWeightAmount = pCurMech->getMaxWeight();
  525. addWeightAnim.begin();
  526. removeWeightAnim.end();
  527. bool bFound = 0;
  528. for ( int i = 0; i < mechListBox.GetItemCount(); i++ )
  529. {
  530. if ( LogisticsData::instance->canAddMechToForceGroup(
  531. ((MechListBoxItem*)mechListBox.GetItem( i ))->getMech() ) )
  532. {
  533. bFound = true;
  534. }
  535. }
  536. if ( !bFound ) // select first thing in FG
  537. {
  538. selectFirstFGItem();
  539. mechListBox.SelectItem( -1 );
  540. }
  541. }
  542. }
  543. void MechBayScreen::removeSelectedMech()
  544. {
  545. for ( int i = 0; i < ICON_COUNT; i++ )
  546. {
  547. if ( pIcons[i].isSelected() )
  548. {
  549. LogisticsMech* pMech = pIcons[i].getMech();
  550. if ( !pMech )
  551. return;
  552. if ( 0 == LogisticsData::instance->getVariantsInInventory( pMech->getVariant(), 0 ) )
  553. {
  554. MechListBoxItem* item = new MechListBoxItem( pMech, 0 );
  555. mechListBox.AddItem( item );
  556. }
  557. LogisticsData::instance->removeMechFromForceGroup( pMech, true );
  558. forceGroupCount--;
  559. removeWeightAmount = pMech->getMaxWeight();
  560. removeWeightAnim.begin();
  561. addWeightAnim.end();
  562. if ( i >= forceGroupCount )
  563. {
  564. if ( !selectFirstFGItem() )
  565. {
  566. selectFirstViableLBMech();
  567. }
  568. }
  569. else
  570. pIcons[i].select( true );
  571. break;
  572. }
  573. }
  574. for ( ; i < ICON_COUNT - 1; i++ )
  575. {
  576. LogisticsData::instance->removeMechFromForceGroup(pIcons[i+1].getMech(), false);
  577. LogisticsData::instance->addMechToForceGroup(pIcons[i+1].getMech(), i+1);
  578. }
  579. reinitMechs();
  580. if ( !forceGroupCount )
  581. selectFirstViableLBMech();
  582. }
  583. void MechBayScreen::end()
  584. {
  585. mechCamera->setMech( NULL );
  586. }
  587. void MechBayScreen::setMech( LogisticsMech* pMech, bool bCommandFromLB )
  588. {
  589. if ( pMech == pCurMech || status != RUNNING)
  590. return;
  591. pCurMech = pMech;
  592. if ( pMech )
  593. {
  594. loadoutListBox.setMech( pMech->getVariant() );
  595. EString fileName = pMech->getFileName();
  596. int index = fileName.Find( '.' );
  597. fileName = fileName.Left( index );
  598. index = fileName.ReverseFind( '\\' );
  599. fileName = fileName.Right( fileName.Length() - index - 1 );
  600. mechCamera->setMech( fileName, prefs.baseColor, prefs.highlightColor, prefs.highlightColor );
  601. mechCamera->setScale( pMech->getVariant()->getChassis()->getScale() );
  602. }
  603. else
  604. loadoutListBox.setMech( 0 );
  605. if ( bCommandFromLB ) // clicked on a disabled mech
  606. {
  607. unselectDeploymentTeam();
  608. mechListBox.SelectItem( -1 );
  609. }
  610. if ( pCurMech )
  611. {
  612. char tmpStr[256];
  613. // update current text
  614. char str[64];
  615. // weight
  616. cLoadString( IDS_MB_MECH_WEIGHT, tmpStr, 63 );
  617. sprintf( str, tmpStr, pCurMech->getMaxWeight(), (const char*)pCurMech->getMechClass() );
  618. textObjects[7].setText( str );
  619. // firing range
  620. long tmpColor;
  621. textObjects[14].setText( pCurMech->getVariant()->getOptimalRangeString( tmpColor ) );
  622. textObjects[14].setColor( tmpColor );
  623. // armor
  624. int armor = pCurMech->getArmor();
  625. sprintf( str, "%ld", armor );
  626. textObjects[8].setText( str );
  627. attributeMeters[0].setValue( armor/MAX_ARMOR_RANGE );
  628. // speed
  629. int speed = pCurMech->getDisplaySpeed();
  630. sprintf( str, "%ld", speed );
  631. textObjects[9].setText( str );
  632. attributeMeters[1].setValue( pCurMech->getSpeed()/MAX_SPEED_RANGE );
  633. // jump
  634. int jumpRange = pCurMech->getJumpRange();
  635. sprintf( str, "%ld", jumpRange * 25 );
  636. textObjects[10].setText( str );
  637. attributeMeters[2].setValue( jumpRange * 25 / MAX_JUMP_RANGE );
  638. textObjects[11].setText( pCurMech->getChassisName() );
  639. textObjects[12].setText( pCurMech->getName() );
  640. }
  641. else
  642. {
  643. textObjects[7].setText( "" );
  644. textObjects[8].setText( "" );
  645. textObjects[9].setText( "" );
  646. textObjects[10].setText( "" );
  647. textObjects[11].setText( "" );
  648. textObjects[12].setText( "" );
  649. textObjects[14].setText( "" );
  650. for ( int i = 0; i < 3; i++ )
  651. {
  652. attributeMeters[i].setValue(0);
  653. }
  654. }
  655. }
  656. void MechBayScreen::beginDrag( LogisticsMech* pMech )
  657. {
  658. if ( pDragMech || status != RUNNING )
  659. return;
  660. if ( !pMech )
  661. return;
  662. // need to set the uv's of the mech icon
  663. MechListBox::initIcon( pMech, dragIcon );
  664. dragIcon.moveTo( userInput->getMouseX() - dragIcon.width() / 2,
  665. userInput->getMouseY() - dragIcon.height() / 2 );
  666. pDragMech = pMech;
  667. // figure out where the mech came from
  668. if ( mechListBox.pointInside( userInput->getMouseDragX(), userInput->getMouseDragY() ) )
  669. {
  670. if ( pMech->getForceGroup() )
  671. {
  672. pMech = LogisticsData::instance->getMechWithoutForceGroup( pMech );
  673. }
  674. pDragMech = pMech;
  675. if ( !LogisticsData::instance->canAddMechToForceGroup( pMech ) )
  676. {
  677. pDragMech = 0;
  678. return;
  679. }
  680. LogisticsData::instance->addMechToForceGroup( pMech, forceGroupCount+1 );
  681. dragLeft = 0;
  682. }
  683. else
  684. {
  685. for ( int i = 0; i < ICON_COUNT; i++ )
  686. {
  687. if ( pIcons[i].pointInside( userInput->getMouseDragX(), userInput->getMouseDragY() ) )
  688. {
  689. forceGroupCount--;
  690. // select the next one
  691. if ( i == forceGroupCount && forceGroupCount )
  692. {
  693. pIcons[i].select( 0 );
  694. pIcons[0].select( true );
  695. }
  696. else if ( !forceGroupCount)
  697. pIcons[i].select( 0 );
  698. for ( ; i < ICON_COUNT - 1; i++ )
  699. {
  700. LogisticsData::instance->removeMechFromForceGroup( pIcons[i+1].getMech(), false );
  701. LogisticsData::instance->addMechToForceGroup( pIcons[i+1].getMech(), i+1 );
  702. pIcons[i].setMech( pIcons[i+1].getMech() );
  703. pIcons[i].setPilot( pIcons[i+1].getPilot() );
  704. }
  705. if ( i < ICON_COUNT )
  706. {
  707. pIcons[i].setMech( NULL );
  708. pIcons[i].setPilot( NULL );
  709. }
  710. break;
  711. }
  712. }
  713. dragLeft = 1;
  714. }
  715. }
  716. void MechBayScreen::reinitMechs()
  717. {
  718. int count = 0;
  719. int maxUnits = 12;
  720. if ( MPlayer )
  721. {
  722. long playerCount;
  723. MPlayer->getPlayers( playerCount );
  724. if ( playerCount )
  725. maxUnits = MAX_MULTIPLAYER_MECHS_IN_LOGISTICS/playerCount;
  726. if ( maxUnits > 12 )
  727. maxUnits = 12;
  728. }
  729. for ( int j = 0; j < ICON_COUNT_Y; j++ )
  730. {
  731. for ( int i = 0; i < ICON_COUNT_X; i++ )
  732. {
  733. pIcons[count].setMech( 0 );
  734. if ( count >= maxUnits )
  735. pIcons[count].disable( true );
  736. else
  737. pIcons[count].disable( 0 );
  738. count++;
  739. }
  740. }
  741. forceGroupCount = 0;
  742. // initialize both the inventory and icon lists
  743. EList< LogisticsMech*, LogisticsMech* > mechList;
  744. LogisticsData::instance->getInventory( mechList );
  745. for ( EList< LogisticsMech*, LogisticsMech* >::EIterator iter = mechList.Begin();
  746. !iter.IsDone(); iter++ )
  747. {
  748. if ( (*iter)->getForceGroup() )
  749. {
  750. long FG = (*iter)->getForceGroup();
  751. if ( FG <= maxUnits )
  752. {
  753. pIcons[FG-1].setMech( (*iter) );
  754. pIcons[FG-1].setPilot( (*iter)->getPilot() );
  755. forceGroupCount++;
  756. }
  757. else
  758. (*iter)->setForceGroup( 0 );
  759. }
  760. }
  761. }
  762. void MechBayScreen::unselectDeploymentTeam()
  763. {
  764. int count = 0;
  765. for ( int j = 0; j < ICON_COUNT_Y; j++ )
  766. {
  767. for ( int i = 0; i < ICON_COUNT_X; i++ )
  768. {
  769. pIcons[count].select( 0 );
  770. count++;
  771. }
  772. }
  773. }
  774. bool MechBayScreen::selectFirstFGItem()
  775. {
  776. bool bRetVal = false;
  777. for ( int i = 0; i < ICON_COUNT_X * ICON_COUNT_Y; i++ )
  778. {
  779. if ( pIcons[i].getMech() && !bRetVal )
  780. {
  781. pIcons[i].select( true );
  782. bRetVal = true;
  783. }
  784. else
  785. pIcons[i].select( false );
  786. }
  787. return bRetVal;
  788. }
  789. bool MechBayScreen::selectFirstViableLBMech()
  790. {
  791. for ( int i = 0; i < mechListBox.GetItemCount(); i++ )
  792. {
  793. if ( mechListBox.GetItem( i )->getState() != aListItem::DISABLED )
  794. {
  795. mechListBox.SelectItem( i );
  796. return true;
  797. }
  798. }
  799. return 0;
  800. }
  801. LogisticsMech* MechBayScreen::getFGSelMech()
  802. {
  803. for ( int i = 0; i < ICON_COUNT_X * ICON_COUNT_Y; i++ )
  804. {
  805. if ( pIcons[i].getMech() && pIcons[i].isSelected() )
  806. return pIcons[i].getMech();
  807. }
  808. return NULL;
  809. }