LogisticsVariant.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. #define LOGISTICSVARIANT_CPP
  2. /*************************************************************************************************\
  3. LogisticsVariant.cpp : Implementation of the LogisticsVariant component.
  4. //---------------------------------------------------------------------------//
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. //===========================================================================//
  7. \*************************************************************************************************/
  8. #include "LogisticsVariant.h"
  9. #include "mclib.h"
  10. #include "LogisticsData.h"
  11. #include "..\resource.h"
  12. #include "cmponent.h"
  13. #include "LogisticsErrors.h"
  14. int LogisticsChassis::weightClasses[5] = { 0, 35, 55, 75, 100};
  15. /*[0- 34 Light
  16. 35-55 Medium
  17. 56-75 Heavy
  18. 76-100 Assualt
  19. */
  20. LogisticsChassis::LogisticsChassis()
  21. {
  22. appearance = 0;
  23. chassisNameID = 0;
  24. baseCost = 0;
  25. maxWeight = 0;
  26. refCount = 0;
  27. canHaveActiveProbe =
  28. canHaveAdvSensor =
  29. canHaveExtendedSensor =
  30. canHaveECM =
  31. canHaveGlobalSensor =
  32. canHaveOptics =
  33. canHaveJumpJets = 0;
  34. }
  35. int LogisticsChassis::init( CSVFile* file, int chassisID )
  36. {
  37. ID = chassisID;
  38. char buffer[256];
  39. fileName = file->getFilename();
  40. fileName.MakeLower();
  41. long result = file->readLong( 11, 5, baseCost );
  42. gosASSERT( result == NO_ERR );
  43. result = file->readLong( 5, 2, chassisNameID );
  44. gosASSERT( result == NO_ERR );
  45. result = file->readFloat( 3, 5, maxWeight );
  46. gosASSERT( result == NO_ERR );
  47. result = file->readLong( 12, 5, maxArmor );
  48. gosASSERT( result == NO_ERR );
  49. result = file->readLong( 8,2, helpID );
  50. gosASSERT( result == NO_ERR );
  51. result = file->readLong( 6, 2, encyclopediaID );
  52. gosASSERT( result == NO_ERR );
  53. file->readLong( 12, 2, iconPictureIndex );
  54. gosASSERT( result == NO_ERR );
  55. houseID;
  56. result = file->readLong( 4, 2, houseID );
  57. ID |= ((houseID << 8) & 0x0000ff00);
  58. gosASSERT( result == NO_ERR );
  59. for ( int row = 9; row < 12; ++row )
  60. {
  61. result = file->readString( row, 2, buffer, 256 );
  62. gosASSERT( result == NO_ERR );
  63. iconFileNames[row - 9] = buffer;
  64. }
  65. result = file->readBoolean( 3, 8, canHaveAdvSensor );
  66. gosASSERT( result == NO_ERR );
  67. result = file->readBoolean(4, 8, canHaveOptics );
  68. gosASSERT( result == NO_ERR );
  69. result = file->readBoolean( 5, 8, canHaveGlobalSensor );
  70. gosASSERT( result == NO_ERR );
  71. result = file->readBoolean( 6, 8, canHaveECM );
  72. gosASSERT( result == NO_ERR );
  73. result = file->readBoolean( 7, 8, canHaveActiveProbe );
  74. gosASSERT( result == NO_ERR );
  75. result = file->readBoolean( 8,8, canHaveJumpJets );
  76. gosASSERT( result == NO_ERR );
  77. result = file->readBoolean( 9,8, canHaveExtendedSensor );
  78. gosASSERT( result == NO_ERR );
  79. result = file->readFloat( 7, 5, speed );
  80. gosASSERT( result == NO_ERR );
  81. result = file->readLong( 4, 5, maxHeat );
  82. gosASSERT( result == NO_ERR );
  83. result = file->readLong( 6, 5, baseArmor );
  84. gosASSERT( result == NO_ERR );
  85. result = file->readLong( 13, 2, componentAreaWidth );
  86. gosASSERT( result == NO_ERR );
  87. result = file->readLong( 14, 2, componentAreaHeight );
  88. gosASSERT( result == NO_ERR );
  89. int ID = IDS_VERY_LIGHT;
  90. for ( int i = 4; i > -1; --i )
  91. {
  92. if ( maxWeight > weightClasses[i] )
  93. {
  94. ID = IDS_VERY_LIGHT + i + 1;
  95. break;
  96. }
  97. }
  98. char tmpWeightClass[256];
  99. cLoadString( ID, tmpWeightClass, 256 );
  100. mechClass = tmpWeightClass;
  101. return 0;
  102. }
  103. int LogisticsChassis::getArmorClass() const
  104. {
  105. if (baseArmor < 96)
  106. return IDS_ARMOR0;
  107. else if (baseArmor < 113)
  108. return IDS_ARMOR1;
  109. else if (baseArmor < 195)
  110. return IDS_ARMOR2;
  111. else if (baseArmor < 304)
  112. return IDS_ARMOR3;
  113. else
  114. return IDS_ARMOR4;
  115. }
  116. int LogisticsChassis::getDisplaySpeed() const
  117. {
  118. switch( (long)speed )
  119. {
  120. case 5:
  121. return 17;
  122. break;
  123. case 10:
  124. return 34;
  125. break;
  126. case 15:
  127. return 54;
  128. break;
  129. case 19:
  130. return 65;
  131. break;
  132. case 23:
  133. return 86;
  134. break;
  135. case 27:
  136. return 97;
  137. break;
  138. case 31:
  139. return 119;
  140. break;
  141. case 35:
  142. return 130;
  143. break;
  144. }
  145. return -1;
  146. }
  147. int LogisticsChassis::getSensorID() const
  148. {
  149. if ( canHaveAdvSensor )
  150. return 15;
  151. else if ( canHaveExtendedSensor )
  152. return 14;
  153. else if ( canHaveGlobalSensor )
  154. return 17;
  155. else
  156. return -1;
  157. return -1;
  158. }
  159. int LogisticsChassis::getECM() const
  160. {
  161. if ( canHaveECM )
  162. return 38;
  163. return -1;
  164. }
  165. LogisticsVariant::LogisticsVariant()
  166. {
  167. componentCount = 0;
  168. ID = -1;
  169. chassis = 0;
  170. availableToUser = 0;
  171. memset( components, 0, sizeof( components ) );
  172. bDesignerMech = 0;
  173. bHidden = 0;
  174. fileID = 0;
  175. }
  176. LogisticsVariant::LogisticsVariant( const LogisticsChassis* pChassis , bool Designer)
  177. {
  178. chassis = const_cast<LogisticsChassis*>(pChassis);
  179. availableToUser = 1;
  180. componentCount = 0;
  181. ID = (pChassis->refCount << 16) | pChassis->ID;
  182. chassis->refCount++;
  183. bDesignerMech = Designer;
  184. bHidden = 0;
  185. fileID = 0;
  186. }
  187. LogisticsVariant::~LogisticsVariant()
  188. {
  189. chassis->refCount--;
  190. if ( chassis->refCount == 0 )
  191. delete chassis;
  192. chassis = NULL;
  193. }
  194. LogisticsVariant::LogisticsVariant( const LogisticsVariant& src )
  195. {
  196. chassis = src.chassis;
  197. availableToUser = src.availableToUser;
  198. componentCount = src.componentCount;
  199. for ( int i = 0; i < componentCount; ++i )
  200. {
  201. components[i] = src.components[i];
  202. }
  203. variantName = src.variantName;
  204. ID = (chassis->refCount << 16) | chassis->ID;
  205. chassis->refCount++;
  206. bDesignerMech = 0;
  207. bHidden= 0;
  208. fileID = src.fileID;
  209. }
  210. LogisticsVariant& LogisticsVariant::operator=( const LogisticsVariant& src )
  211. {
  212. if ( &src != this )
  213. {
  214. chassis = src.chassis;
  215. availableToUser = src.availableToUser;
  216. componentCount = src.componentCount;
  217. for ( int i = 0; i < componentCount; ++i )
  218. {
  219. components[i] = src.components[i];
  220. }
  221. variantName = src.variantName;
  222. ID = (chassis->refCount << 16) | chassis->ID;
  223. chassis->refCount++;
  224. bDesignerMech = 0;
  225. fileID = src.fileID;
  226. }
  227. return *this;
  228. }
  229. bool LogisticsVariant::operator==( const LogisticsVariant& src )
  230. {
  231. if ( chassis->chassisNameID != src.chassis->chassisNameID )
  232. return 0;
  233. if ( availableToUser != src.availableToUser )
  234. return 0;
  235. if ( componentCount != src.componentCount )
  236. return 0;
  237. for ( int i = 0; i < componentCount; ++i )
  238. {
  239. if ( components[i].component->getID() != src.components[i].component->getID() )
  240. {
  241. return 0;
  242. }
  243. }
  244. // if ( variantName != src.variantName )
  245. // return 0;
  246. return 1;
  247. }
  248. int LogisticsVariant::init( CSVFile* file, LogisticsChassis* pChassis, int Variant )
  249. {
  250. bDesignerMech = true;
  251. int offset = 97 * Variant;
  252. fileID = Variant;
  253. gosASSERT( pChassis );
  254. chassis = pChassis;
  255. ID = (pChassis->refCount << 16) | pChassis->ID;\
  256. pChassis->refCount++;
  257. file->readBoolean( 21 + offset, 4, bHidden );
  258. char buffer[256];
  259. if ( NO_ERR == file->readString( 23 + offset, 2, buffer, 256 ) )
  260. {
  261. variantName = buffer;
  262. }
  263. LogisticsComponent* pComps[128];
  264. long xLocs[128];
  265. long yLocs[128];
  266. memset( pComps, 0, sizeof( LogisticsComponent* ) * 128 );
  267. long componentCount = 0;
  268. for ( int i =26; i < 97; i++ )
  269. {
  270. long componentID;
  271. if ( NO_ERR == file->readLong( offset + i, 5, componentID ) && componentID != 0xff )
  272. {
  273. LogisticsComponent* pComp = LogisticsData::instance->getComponent(componentID );
  274. if ( pComp )
  275. {
  276. file->readLong( offset + i, 4, yLocs[componentCount] );
  277. file->readLong( offset + i, 3, xLocs[componentCount] );
  278. pComps[componentCount++] = pComp;
  279. }
  280. }
  281. }
  282. for ( int j = 4; j > 0; j-- )
  283. {
  284. for ( int k = 3; k >0; k-- )
  285. {
  286. for ( i = 0; i < componentCount; i++ )
  287. {
  288. LogisticsComponent*
  289. pComponent = pComps[i];
  290. if ( pComponent&& pComponent->getComponentWidth() == k
  291. && pComponent->getComponentHeight() == j )
  292. {
  293. if ( !addComponent( pComps[i]->getID(), xLocs[i], yLocs[i] ) )
  294. {
  295. char errorString[256];
  296. sprintf( errorString, "Couldn't add component with id %ld",
  297. pComponent->getID() );
  298. }
  299. }
  300. }
  301. }
  302. }
  303. return 0;
  304. }
  305. bool LogisticsVariant::addComponent( int idFromFitFile, long& x, long& y )
  306. {
  307. LogisticsComponent*
  308. pComponent = LogisticsData::instance->getComponent( idFromFitFile );
  309. if ( !pComponent )
  310. {
  311. // Assert( 0, idFromFitFile, "couldn't find the component in the fit file\n" );
  312. delete pComponent;
  313. return false;
  314. }
  315. if ( pComponent->getType() == COMPONENT_FORM_JUMPJET )
  316. {
  317. components[componentCount].location = LEGS;
  318. x = y = -2;
  319. }
  320. else if ( pComponent->getType() == COMPONENT_FORM_ECM || pComponent->getType() == COMPONENT_FORM_SENSOR )
  321. {
  322. components[componentCount].location = HEAD;
  323. x = y = -3;
  324. }
  325. else
  326. {
  327. // need to see if this thing will fit
  328. long componentWidth = pComponent->getComponentWidth();
  329. long componentHeight = pComponent->getComponentHeight();
  330. if ( x == -1 && y == -1 )
  331. {
  332. for ( int j = 0; j < chassis->componentAreaHeight && x == -1; j++ )
  333. {
  334. for ( int i = 0; i < chassis->componentAreaWidth && x == -1; i++ )
  335. {
  336. bool bAdd = true;
  337. for ( int l = 0; l < componentHeight; ++l )
  338. {
  339. for ( int k =0; k < componentWidth; ++k )
  340. {
  341. if ( getComponentAtLocation( i +k, j + l )
  342. || ( i + k >= chassis->componentAreaWidth )
  343. || ( j +l >= chassis->componentAreaHeight ) )
  344. {
  345. bAdd = false;
  346. break;
  347. break;
  348. }
  349. }
  350. }
  351. if ( bAdd )
  352. {
  353. x = i;
  354. y = j;
  355. }
  356. }
  357. }
  358. }
  359. if ( x == -1 && y == -1 )
  360. return 0;
  361. if ( x > -1 )
  362. {
  363. for ( int i =0; i < componentWidth; ++i )
  364. {
  365. for ( int j = 0; j < componentHeight; ++j )
  366. {
  367. if ( getComponentAtLocation( x +i, y + j ) )
  368. {
  369. char errorString[1024];
  370. sprintf( errorString, "couldn't add component %s to variant %s because another object was in the specified location",
  371. pComponent->getName(), this->getName() );
  372. // Assert( 0, 0, errorString );
  373. return false;
  374. }
  375. }
  376. }
  377. }
  378. components[componentCount].location = CHEST;
  379. }
  380. components[componentCount].component = pComponent;
  381. components[componentCount].xCoord = x;
  382. components[componentCount].yCoord = y;
  383. componentCount++;
  384. return true;
  385. }
  386. int LogisticsVariant::getCost( ) const
  387. {
  388. int cost = chassis->baseCost;
  389. for ( int i = 0; i < componentCount; ++i )
  390. {
  391. cost += components[i].component->getCost();
  392. }
  393. return cost;
  394. }
  395. int LogisticsVariant::getWeight() const
  396. {
  397. //Yup. 20% of base weight Plus 7 tons is used by armor and misc components which we do not explicitly track.
  398. float baseWeight = (chassis->maxWeight * .20) + 7.0;
  399. for ( int i = 0; i < componentCount; ++i )
  400. {
  401. baseWeight += components[i].component->getWeight();
  402. }
  403. return baseWeight;
  404. }
  405. const EString& LogisticsVariant::getMechClass() const
  406. {
  407. return chassis->mechClass;
  408. }
  409. int LogisticsVariant::getMaxJumpRange() const
  410. {
  411. return 5;
  412. }
  413. // BOGUS, this is entirely made up. There is no real spec for jumpranges yet
  414. int LogisticsVariant::getJumpRange() const
  415. {
  416. int jumpJetCount = 0;
  417. for ( int i = 0; i < componentCount; ++i )
  418. {
  419. if ( components[i].component->getType() == COMPONENT_FORM_JUMPJET )
  420. jumpJetCount++;
  421. }
  422. if ( jumpJetCount )
  423. return 5;
  424. return 0;
  425. }
  426. int LogisticsVariant::getHeat() const
  427. {
  428. int retVal = 0;
  429. for ( int i = 0; i < componentCount; ++i )
  430. {
  431. retVal += components[i].component->getHeat();
  432. }
  433. return retVal;
  434. }
  435. // BOGUS -- range isn't really the right thing to add...
  436. int LogisticsVariant::getArmor( ) const
  437. {
  438. int retArmor = chassis->baseArmor;
  439. for ( int i = 0; i < componentCount; ++i )
  440. {
  441. if ( components[i].component->getType() == COMPONENT_FORM_BULK )
  442. {
  443. retArmor += 32;
  444. }
  445. }
  446. return retArmor;
  447. }
  448. int LogisticsVariant::getSpeed() const
  449. {
  450. return chassis->speed;
  451. }
  452. int LogisticsVariant::getDisplaySpeed() const
  453. {
  454. return chassis->getDisplaySpeed();
  455. }
  456. int LogisticsVariant::getMaxHeat() const
  457. {
  458. int heat = 0;
  459. for ( int i = 0; i < componentCount; i++ )
  460. {
  461. if ( components[i].component->getType() == COMPONENT_FORM_HEATSINK )
  462. {
  463. heat += components[i].component->getDamage();
  464. }
  465. }
  466. return heat + chassis->maxHeat;
  467. }
  468. // if you pass in -1's for x and y, we'll figure out where it can go, and return where it went
  469. int LogisticsVariant::canAddComponent( LogisticsComponent* pComponent, long& x, long& y ) const
  470. {
  471. /* weight no longer matters
  472. int weight = getWeight();
  473. if ( weight + pComponent->getWeight() > chassis->maxWeight )
  474. return COMPONENT_TOO_HEAVY;*/
  475. if ( getHeat() + pComponent->getHeat() > getMaxHeat() )
  476. return COMPONENT_TOO_HOT;
  477. if ( pComponent->getType() == COMPONENT_FORM_JUMPJET )
  478. {
  479. if ( !chassis->canHaveJumpJets )
  480. return JUMPJETS_NOT_ALLOWED;
  481. else if ( hasJumpJets() )
  482. return ONLY_ONE_JUMPJET_ALLOWED;
  483. else if ( ( x!= -1 && x != -2)
  484. || ( y != -1 && y != -2 ) )
  485. return COMPONENT_SLOT_FULL;
  486. return 0;
  487. }
  488. else if ( x == -2 && y == -2 ) // trying to put something illegal in jump jet slot
  489. return COMPONENT_SLOT_FULL;
  490. if ( x!= -1 && y != -1 )
  491. {
  492. for ( int i = 0; i < pComponent->getComponentWidth(); i++ )
  493. {
  494. for ( int j = 0; j < pComponent->getComponentHeight(); j++ )
  495. {
  496. if ( getComponentAtLocation( x + i, y + j)
  497. || x + i >= chassis->componentAreaWidth
  498. || j + y >= chassis->componentAreaHeight )
  499. return COMPONENT_SLOT_FULL;
  500. }
  501. }
  502. }
  503. else
  504. {
  505. for ( int j = 0; j < chassis->componentAreaHeight && x == -1; j++ )
  506. {
  507. for ( int i = 0; i < chassis->componentAreaWidth && x == -1; i++ )
  508. {
  509. if ( !getComponentAtLocation( i, j ) )
  510. {
  511. bool bAdd = true;
  512. for ( int l = 0; l < pComponent->getComponentHeight(); ++l )
  513. {
  514. for ( int k =0; k < pComponent->getComponentWidth(); ++k )
  515. {
  516. if ( getComponentAtLocation( i +k, j + l )
  517. || ( i + k >= chassis->componentAreaWidth )
  518. || ( j +l >= chassis->componentAreaHeight ) )
  519. {
  520. bAdd = false;
  521. break;
  522. break;
  523. }
  524. }
  525. }
  526. if ( bAdd )
  527. {
  528. x = i;
  529. y = j;
  530. }
  531. }
  532. }
  533. }
  534. if ( x == -1 || y == -1 )
  535. {
  536. return ADD_COMPONENT_FAILED;
  537. }
  538. }
  539. if ( pComponent->getType() == COMPONENT_FORM_BULK )
  540. {
  541. if ( getArmor() + 32 > getMaxArmor() )
  542. return NO_MORE_ARMOR;
  543. }
  544. if ( pComponent->getType() == COMPONENT_FORM_SENSOR )
  545. {
  546. if ( !chassis->canHaveAdvSensor )
  547. return SENSORS_NOT_ALLOWED;
  548. else if ( hasSensor() )
  549. return ONLY_ONE_SENSOR_ALLOWED;
  550. }
  551. if ( pComponent->getType() == COMPONENT_FORM_ECM )
  552. {
  553. if ( !chassis->canHaveECM )
  554. return ECM_NOT_ALLOWED;
  555. else if ( hasECM() )
  556. return ONLY_ONE_ECM_ALLOWED;
  557. }
  558. return 0;
  559. }
  560. const LogisticsChassis::ComponentInfo* LogisticsVariant::getComponentAtLocation( long x, long y ) const
  561. {
  562. if ( x == -1 && y == -1 )
  563. return NULL;
  564. for ( int i = 0; i < componentCount; ++i )
  565. {
  566. LogisticsComponent* pComponent = components[i].component;
  567. for ( int j = 0; j < pComponent->getComponentHeight(); ++j )
  568. {
  569. for ( int k = 0; k < pComponent->getComponentWidth(); ++k )
  570. {
  571. if ( components[i].xCoord + k == x
  572. && components[i].yCoord + j == y )
  573. {
  574. return &components[i];
  575. }
  576. }
  577. }
  578. }
  579. return NULL;
  580. }
  581. bool LogisticsVariant::hasJumpJets() const
  582. {
  583. for ( int i = 0; i < componentCount; i++ )
  584. {
  585. if ( components[i].component->getType() == COMPONENT_FORM_JUMPJET )
  586. return true;
  587. }
  588. return false;
  589. }
  590. bool LogisticsVariant::hasECM() const
  591. {
  592. for ( int i = 0; i < componentCount; i++ )
  593. {
  594. if ( components[i].component->getType() == COMPONENT_FORM_ECM )
  595. return true;
  596. }
  597. return false;
  598. }
  599. bool LogisticsVariant::hasSensor() const
  600. {
  601. for ( int i = 0; i < componentCount; i++ )
  602. {
  603. if ( components[i].component->getType() == COMPONENT_FORM_SENSOR )
  604. return true;
  605. }
  606. return false;
  607. }
  608. int LogisticsVariant::getComponentsWithLocation( long& count, long* IDArray, long* xLocationArray, long* yLocationArray )
  609. {
  610. if ( count < componentCount )
  611. return NEED_BIGGER_ARRAY;
  612. for ( int i = 0; i < componentCount; ++i )
  613. {
  614. IDArray[i] = components[i].component->getID();
  615. xLocationArray[i] = components[i].xCoord;
  616. yLocationArray[i] = components[i].yCoord;
  617. }
  618. count = componentCount;
  619. return 0;
  620. }
  621. int LogisticsVariant::getComponents( long& count, long* array )
  622. {
  623. for ( int i = 0; i < componentCount; ++i )
  624. {
  625. array[i] = components[i].component->getID();
  626. }
  627. count = componentCount;
  628. return count;
  629. }
  630. int LogisticsVariant::removeComponent( long xCoord, long yCoord )
  631. {
  632. LogisticsChassis::ComponentInfo* info = const_cast<LogisticsChassis::ComponentInfo*>(getComponentAtLocation( xCoord, yCoord ));
  633. if ( !info )
  634. return -1;
  635. if ( info->component && info->component->getType() == COMPONENT_FORM_HEATSINK )
  636. {
  637. if ( getMaxHeat() - info->component->getDamage() < getHeat() )
  638. return INSUFFICIENT_HEAT;
  639. }
  640. if ( !info )
  641. return INVALID_LOCATION;
  642. for ( int i = 0; i < componentCount; i++ )
  643. {
  644. if ( &components[i] == info )
  645. {
  646. memmove( &components[i], &components[i + 1], (componentCount - ( i + 1 )) * sizeof( LogisticsChassis::ComponentInfo ) );
  647. break;
  648. }
  649. }
  650. componentCount --;
  651. return 0;
  652. }
  653. // if you pass in -1's for x and y, we'll figure out where it can go, and return where it went
  654. int LogisticsVariant::addComponent( LogisticsComponent* pComponent, long& xCoord, long& yCoord )
  655. {
  656. int retVal = canAddComponent( pComponent, xCoord, yCoord );
  657. if ( retVal == 0 )
  658. {
  659. if ( addComponent( pComponent->getID(), xCoord, yCoord ) )
  660. return 0;
  661. else
  662. return ADD_COMPONENT_FAILED;
  663. }
  664. return retVal;
  665. }
  666. long LogisticsVariant::save( FitIniFile& file, long counter )
  667. {
  668. char tmp[256];
  669. char tmp2[256];
  670. sprintf( tmp, "Variant%ld", counter );
  671. file.writeBlock( tmp );
  672. file.writeIdString( "Chassis", chassis->fileName );
  673. file.writeIdString( "VariantName", variantName );
  674. file.writeIdLong( "ComponentCount", componentCount );
  675. for ( int i = 0; i < componentCount; i++ )
  676. {
  677. sprintf( tmp, "Component%ld", i );
  678. file.writeIdLong(tmp, components[i].component->getID() );
  679. strcpy( tmp2, tmp );
  680. strcat( tmp2, "x" );
  681. file.writeIdLong( tmp2, components[i].xCoord );
  682. strcpy( tmp2, tmp );
  683. strcat( tmp2, "y" );
  684. file.writeIdLong( tmp2, components[i].yCoord );
  685. strcpy( tmp2, tmp );
  686. strcat( tmp2, "Location" );
  687. file.writeIdLong( tmp2, components[i].location );
  688. }
  689. return 0;
  690. }
  691. void LogisticsVariant::setName( const char* pName )
  692. {
  693. variantName = pName;
  694. }
  695. int LogisticsVariant::getComponents( long& count, LogisticsComponent** array )
  696. {
  697. if ( count < componentCount )
  698. return NEED_BIGGER_ARRAY;
  699. for ( int i = 0; i < componentCount; ++i )
  700. {
  701. array[i] = components[i].component;
  702. }
  703. count = componentCount;
  704. return 0;
  705. }
  706. LogisticsComponent* LogisticsVariant::getCompAtLocation( int i, int j, long& realI, long& realJ )
  707. {
  708. realI = realJ = -1;
  709. const LogisticsChassis::ComponentInfo* pInfo = getComponentAtLocation( i, j );
  710. if ( pInfo )
  711. {
  712. realI = pInfo->xCoord;
  713. realJ = pInfo->yCoord;
  714. return pInfo->component;
  715. }
  716. return 0;
  717. }
  718. int LogisticsVariant::getComponentLocation( LogisticsComponent* pComp, long& x, long& y )
  719. {
  720. const LogisticsChassis::ComponentInfo* pInfo = getComponentAtLocation( x, y );
  721. x = y = -1;
  722. if ( pInfo )
  723. {
  724. x = pInfo->xCoord;
  725. y = pInfo->yCoord;
  726. }
  727. else
  728. {
  729. for ( int i = 0; i < componentCount; i++ )
  730. {
  731. if ( (components[i].component) == pComp )
  732. {
  733. x = components[i].xCoord;
  734. y = components[i].yCoord;
  735. return 0;
  736. }
  737. }
  738. return COMPONENT_NOT_FOUND;
  739. }
  740. return 0;
  741. }
  742. int LogisticsVariant::getOptimalRangeString( long& color ) const
  743. {
  744. float rangeDamage[3];
  745. long rangeColors[3] = {0xff6e7c00, 0xff005392,0xffa21600 };
  746. memset( rangeDamage, 0, sizeof ( float ) * 3 );
  747. float maxDamage = -1.f;
  748. for ( int i = 0; i < componentCount; i++ )
  749. {
  750. if ( components[i].component->isWeapon() )
  751. {
  752. float damageTimeRating = components[i].component->getDamage();
  753. if ( components[i].component->getRecycleTime() )
  754. damageTimeRating = components[i].component->getDamage() / components[i].component->getRecycleTime();
  755. rangeDamage[components[i].component->getRangeType()] += damageTimeRating;
  756. if ( rangeDamage[components[i].component->getRangeType()] > maxDamage )
  757. maxDamage = rangeDamage[components[i].component->getRangeType()];
  758. }
  759. }
  760. for ( i = 0; i < 3; i++ )
  761. {
  762. if ( rangeDamage[i] == maxDamage )
  763. {
  764. color = rangeColors[i];
  765. return IDS_HOTKEY1 + i;
  766. }
  767. }
  768. return IDS_HOTKEY1;
  769. }
  770. bool LogisticsVariant::allComponentsAvailable() const
  771. {
  772. // 06/05/01 hack, we wan't to hide this atlas for the whole game.
  773. if ( stricmp( "Renard's Atlas", variantName ) == 0 )
  774. return 0;
  775. for ( int i = 0; i < componentCount; i++ )
  776. {
  777. if ( !components[i].component->isAvailable() )
  778. return false;
  779. }
  780. return true;
  781. }
  782. void LogisticsVariant::setAvailable( bool available )
  783. {
  784. // 06/05/01 hack, we wan't to hide this atlas for the whole game.
  785. if ( stricmp( "Renard's Atlas", variantName ) == 0 )
  786. availableToUser = 0;
  787. else
  788. availableToUser = available;
  789. }
  790. void LogisticsVehicle::init( FitIniFile& file )
  791. {
  792. componentCount = 0;
  793. file.seekBlock( "ObjectType" );
  794. char tmp[256];
  795. file.readIdString( "AppearanceName", tmp, 255 );
  796. fileName = tmp;
  797. file.seekBlock( "General" );
  798. file.readIdLong( "DescIndex", chassisNameID );
  799. file.readIdFloat( "CurTonnage", maxWeight );
  800. char tmpWeightClass[256];
  801. cLoadString( IDS_VEHICLE_CLASS, tmpWeightClass, 256 );
  802. mechClass = tmpWeightClass;
  803. if ( NO_ERR !=file.readIdLong( "HouseID", houseID ) )
  804. {
  805. houseID = -1;
  806. }
  807. if ( NO_ERR != file.readIdLong( "EncyclopediaID", encyclopediaID ) )
  808. {
  809. encyclopediaID = IDS_VEHICLE_DESCRIPTION_0;
  810. }
  811. file.seekBlock( "VehicleDynamics" );
  812. file.readIdFloat( "MaxVelocity", speed );
  813. char* parts[5] = { "Front", "Left", "Right", "Rear", "Turret" };
  814. baseArmor = 0;
  815. unsigned char pts;
  816. for ( int i = 0; i < 5; i++ )
  817. {
  818. file.seekBlock( parts[i] );
  819. file.readIdUChar( "MaxArmorPoints", pts );
  820. baseArmor += pts;
  821. file.readIdUChar( "CurInternalStructure", pts );
  822. baseArmor += pts;
  823. }
  824. file.seekBlock( "InventoryInfo" );
  825. file.readIdUChar( "NumWeapons", pts );
  826. char blockName[256];
  827. for ( i = 4; i < 4 + pts; i++ )
  828. {
  829. sprintf( blockName, "Item:%ld", i );
  830. if ( NO_ERR == file.seekBlock( blockName ) )
  831. {
  832. unsigned char fitID;
  833. file.readIdUChar( "MasterID", fitID );
  834. LogisticsComponent* pComponent = LogisticsData::instance->getComponent( fitID );
  835. if ( pComponent )
  836. {
  837. components[componentCount].component = pComponent;
  838. components[componentCount].xCoord = 0;
  839. components[componentCount].yCoord = 0;
  840. componentCount++;
  841. }
  842. }
  843. }
  844. }
  845. int LogisticsVehicle::getComponents( long& count, LogisticsComponent** array )
  846. {
  847. gosASSERT( componentCount <= count );
  848. for ( int i = 0; i < componentCount; ++i )
  849. {
  850. array[i] = components[i].component;
  851. }
  852. count = componentCount;
  853. return count;
  854. }
  855. //*************************************************************************************************
  856. // end of file ( LogisticsVariant.cpp )