PageRenderTime 63ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/game/minicomputer.cpp

https://code.google.com/
C++ | 1995 lines | 1696 code | 214 blank | 85 comment | 210 complexity | 7afedf25f82ee21a1d4f6210c40c5531 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. // Copyright (C) 1997, 1999-2001, 2008 Nathan Lamont
  2. // Copyright (C) 2008-2012 The Antares Authors
  3. //
  4. // This file is part of Antares, a tactical space combat game.
  5. //
  6. // Antares is free software: you can redistribute it and/or modify it
  7. // under the terms of the Lesser GNU General Public License as published
  8. // by the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // Antares is distributed in the hope that it will be useful, but
  12. // WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. // Lesser General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Lesser General Public
  17. // License along with Antares. If not, see http://www.gnu.org/licenses/
  18. #include "game/minicomputer.hpp"
  19. #include <algorithm>
  20. #include <sfz/sfz.hpp>
  21. #include "config/keys.hpp"
  22. #include "data/string-list.hpp"
  23. #include "drawing/color.hpp"
  24. #include "drawing/pix-table.hpp"
  25. #include "drawing/shapes.hpp"
  26. #include "drawing/sprite-handling.hpp"
  27. #include "drawing/text.hpp"
  28. #include "game/admiral.hpp"
  29. #include "game/globals.hpp"
  30. #include "game/instruments.hpp"
  31. #include "game/messages.hpp"
  32. #include "game/player-ship.hpp"
  33. #include "game/scenario-maker.hpp"
  34. #include "game/space-object.hpp"
  35. #include "game/starfield.hpp"
  36. #include "math/fixed.hpp"
  37. #include "sound/fx.hpp"
  38. #include "video/driver.hpp"
  39. using sfz::Bytes;
  40. using sfz::Rune;
  41. using sfz::String;
  42. using sfz::StringSlice;
  43. using sfz::bin;
  44. using sfz::scoped_array;
  45. using sfz::string_to_int;
  46. using std::max;
  47. namespace macroman = sfz::macroman;
  48. namespace antares {
  49. miniComputerDataType *gMiniScreenData = NULL;
  50. namespace {
  51. const int32_t kMiniScreenCharWidth = 25;
  52. const int32_t kMiniScreenLeft = 12;
  53. const int32_t kMiniScreenTop = 320;
  54. const int32_t kMiniScreenRight = 121;
  55. const int32_t kMiniScreenBottom = 440;
  56. const int32_t kMiniScreenWidth = kMiniScreenRight - kMiniScreenLeft;
  57. const int32_t kMiniScreenLeftBuffer = 3;
  58. const int32_t kMiniScreenCharHeight = 10; // height of the screen in characters
  59. const int32_t kMiniScreenTrueLineNum = kMiniScreenCharHeight + 2;
  60. const int32_t kButBoxLeft = 16;
  61. const int32_t kButBoxTop = 450;
  62. const int32_t kButBoxRight = 114;
  63. const int32_t kButBoxBottom = 475;
  64. const int32_t kMiniScreenNoLineSelected = -1;
  65. const int16_t kMiniScreenStringID = 3000;
  66. const int16_t kMiniDataStringID = 3001;
  67. const uint8_t kMiniScreenColor = GREEN;
  68. const uint8_t kMiniButColor = AQUA;
  69. const Rune kMiniScreenSpecChar = '\\';
  70. const Rune kEndLineChar = 'x';
  71. const Rune kUnderlineEndLineChar = 'u';
  72. const Rune kIntoButtonChar = 'I';
  73. const Rune kOutOfButtonChar = 'O';
  74. const Rune kSelectableLineChar = 'S';
  75. const int32_t kNoLineButton = -1;
  76. const int32_t kInLineButton = kCompAcceptKeyNum;
  77. const int32_t kOutLineButton = kCompCancelKeyNum;
  78. enum {
  79. kMainMiniScreen = 1,
  80. kBuildMiniScreen = 2,
  81. kSpecialMiniScreen = 3,
  82. kMessageMiniScreen = 4,
  83. kStatusMiniScreen = 5,
  84. };
  85. enum {
  86. kMainMiniBuild = 1,
  87. kMainMiniSpecial = 2,
  88. kMainMiniMessage = 3,
  89. kMainMiniStatus = 4,
  90. };
  91. const int32_t kBuildScreenFirstTypeLine = 2;
  92. const int32_t kBuildScreenWhereNameLine = 1;
  93. enum {
  94. kSpecialMiniTransfer = 1,
  95. kSpecialMiniHold = 2,
  96. kSpecialMiniGoToMe = 3,
  97. kSpecialMiniFire1 = 4,
  98. kSpecialMiniFire2 = 5,
  99. kSpecialMiniFireSpecial = 6,
  100. };
  101. enum {
  102. kMessageMiniNext = 1,
  103. kMessageMiniPrevious = 2,
  104. kMessageMiniLast = 3,
  105. };
  106. const int32_t kStatusMiniScreenFirstLine = 1;
  107. enum {
  108. kNoStatusData = -1, // no status for this line
  109. kPlainTextStatus = 0,
  110. kTrueFalseCondition = 1, // 0 = F, 1 = T, use condition not score
  111. kIntegerValue = 2, // interpret score as int
  112. kSmallFixedValue = 3, // interpret score as fixed
  113. kIntegerMinusValue = 4, // value - designated score
  114. kSmallFixedMinusValue = 5, // small fixed - designated score
  115. kMaxStatusTypeValue = kSmallFixedMinusValue,
  116. };
  117. const int32_t kMiniComputerPollTime = 60;
  118. const int32_t kMiniObjectDataNum = 2;
  119. const int32_t kMiniSelectObjectNum = 0;
  120. const int32_t kMiniSelectTop = 180;
  121. const int32_t kMiniIconHeight = 22;
  122. const int32_t kMiniIconWidth = 24;
  123. const int32_t kMiniIconLeft = (kMiniScreenLeft + 2);
  124. const int32_t kMiniHealthLeft = (kMiniIconLeft + kMiniIconWidth + 2);
  125. const int32_t kMiniBarWidth = 11;
  126. const int32_t kMiniBarHeight = 18;
  127. const int32_t kMiniEnergyLeft = (kMiniHealthLeft + kMiniBarWidth + 2);
  128. const int32_t kMiniRightColumnLeft = 57;
  129. const int32_t kMiniWeapon1LineNum = 2;
  130. const int32_t kMiniWeapon2LineNum = 3;
  131. const int32_t kMiniWeapon3LineNum = 1;
  132. const int32_t kMiniNameLineNum = 1;
  133. const int32_t kMiniDestLineNum = 4;
  134. const int32_t kMiniTargetObjectNum = 1;
  135. const int32_t kMiniTargetTop = 252;
  136. const int32_t kMiniAmmoTop = 161;
  137. const int32_t kMiniAmmoBottom = 170;
  138. const int32_t kMiniAmmoSingleWidth = 21;
  139. const int32_t kMiniAmmoLeftOne = 27;
  140. const int32_t kMiniAmmoLeftTwo = 64;
  141. const int32_t kMiniAmmoLeftSpecial = 100;
  142. const int32_t kMiniAmmoTextHBuffer = 2;
  143. inline void mPlayBeep3() {
  144. PlayVolumeSound(kComputerBeep3, kMediumVolume, kMediumPersistence, kLowPrioritySound);
  145. }
  146. inline void mPlayBeepBad() {
  147. PlayVolumeSound(kWarningTone, kMediumVolume, kMediumPersistence, kLowPrioritySound);
  148. }
  149. const int32_t kMaxShipBuffer = 40;
  150. void pad_to(String& s, size_t width) {
  151. if (s.size() < width) {
  152. String result;
  153. result.append((width - s.size()) / 2, ' ');
  154. result.append(s);
  155. result.append((1 + width - s.size()) / 2, ' ');
  156. swap(result, s);
  157. }
  158. }
  159. const int32_t MiniIconMacLineTop() {
  160. return computer_font->height * 2;
  161. }
  162. Rect mini_screen_line_bounds(long mtop, long mlinenum, long mleft, long mright) {
  163. Rect mbounds;
  164. mbounds.left = kMiniScreenLeft + mleft;
  165. mbounds.top = mtop + mlinenum * computer_font->height;
  166. mbounds.right = kMiniScreenLeft + mright;
  167. mbounds.bottom = mbounds.top + computer_font->height;
  168. return mbounds;
  169. }
  170. inline long mGetLineNumFromV(long mV) {
  171. return (((mV) - (kMiniScreenTop + globals()->gInstrumentTop)) / computer_font->height);
  172. }
  173. // for copying the fields of a space object relevant to the miniscreens:
  174. inline void mCopyMiniSpaceObject(
  175. spaceObjectType& mdestobject, const spaceObjectType& msourceobject) {
  176. (mdestobject).id = (msourceobject).id;
  177. (mdestobject).beamType = (msourceobject).beamType;
  178. (mdestobject).pulseType = (msourceobject).pulseType;
  179. (mdestobject).specialType = (msourceobject).specialType;
  180. (mdestobject).destinationLocation.h = (msourceobject).destinationLocation.h;
  181. (mdestobject).destinationLocation.v = (msourceobject).destinationLocation.v;
  182. (mdestobject).destinationObject = (msourceobject).destinationObject;
  183. (mdestobject).destObjectPtr = (msourceobject).destObjectPtr;
  184. (mdestobject).health = (msourceobject).health;
  185. (mdestobject).energy = (msourceobject).energy;
  186. (mdestobject).whichBaseObject = (msourceobject).whichBaseObject;
  187. (mdestobject).pixResID = (msourceobject).pixResID;
  188. (mdestobject).attributes = (msourceobject).attributes;
  189. (mdestobject).location = (msourceobject).location;
  190. (mdestobject).owner = (msourceobject).owner;
  191. (mdestobject).nextFarObject = (msourceobject).nextFarObject;
  192. (mdestobject).distanceGrid = (msourceobject).distanceGrid;
  193. (mdestobject).nextNearObject = (msourceobject).nextNearObject;
  194. (mdestobject).collisionGrid = (msourceobject).collisionGrid;
  195. (mdestobject).remoteFriendStrength = (msourceobject).remoteFriendStrength;
  196. (mdestobject).remoteFoeStrength = (msourceobject).remoteFoeStrength;
  197. (mdestobject).escortStrength = (msourceobject).escortStrength;
  198. (mdestobject).baseType = (msourceobject).baseType;
  199. }
  200. inline void mCopyBlankLineString(miniScreenLineType* mline, StringSlice mstring) {
  201. mline->string.assign(mstring);
  202. if (mline->string.size() > kMiniScreenCharWidth) {
  203. mline->string.resize(kMiniScreenCharWidth);
  204. }
  205. }
  206. inline spaceObjectType* mGetMiniObjectPtr(long mwhich) {
  207. return globals()->gMiniScreenData.objectData.get() + mwhich;
  208. }
  209. } // namespace
  210. void MiniComputerSetStatusStrings( void);
  211. long MiniComputerGetStatusValue( long);
  212. void MiniComputerMakeStatusString(int32_t which_line, String& string);
  213. void MiniScreenInit() {
  214. globals()->gMiniScreenData.selectLine = kMiniScreenNoLineSelected;
  215. globals()->gMiniScreenData.currentScreen = kMainMiniScreen;
  216. globals()->gMiniScreenData.pollTime = 0;
  217. globals()->gMiniScreenData.buildTimeBarValue = -1;
  218. globals()->gMiniScreenData.clickLine = kMiniScreenNoLineSelected;
  219. globals()->gMiniScreenData.lineData.reset(new miniScreenLineType[kMiniScreenTrueLineNum]);
  220. globals()->gMiniScreenData.objectData.reset(new spaceObjectType[kMiniObjectDataNum]);
  221. ClearMiniScreenLines();
  222. ClearMiniObjectData();
  223. }
  224. void MiniScreenCleanup() {
  225. globals()->gMiniScreenData.lineData.reset();
  226. globals()->gMiniScreenData.objectData.reset();
  227. }
  228. #pragma mark -
  229. void SetMiniScreenStatusStrList(short strID) {
  230. DisposeMiniScreenStatusStrList();
  231. if (strID > 0) {
  232. globals()->gMissionStatusStrList.reset(new StringList(strID));
  233. }
  234. }
  235. void DisposeMiniScreenStatusStrList( void) {
  236. globals()->gMissionStatusStrList.reset();
  237. }
  238. void ClearMiniScreenLines() {
  239. miniScreenLineType* c = globals()->gMiniScreenData.lineData.get();
  240. for (int32_t b = 0; b < kMiniScreenTrueLineNum; b++) {
  241. c->string.clear();
  242. c->hiliteLeft = c->hiliteRight = 0;
  243. c->whichButton = kNoLineButton;
  244. c->selectable = cannotSelect;
  245. c->underline = false;
  246. c->lineKind = plainLineKind;
  247. c->sourceData = NULL;
  248. c++;
  249. }
  250. }
  251. void ClearMiniObjectData( void)
  252. {
  253. spaceObjectType *o;
  254. o = mGetMiniObjectPtr( kMiniSelectObjectNum);
  255. o->id = -1;
  256. o->beamType = -1;
  257. o->pulseType = -1;
  258. o->specialType = -1;
  259. o->destinationLocation.h = o->destinationLocation.v = -1;
  260. o->destinationObject = -1;
  261. o->destObjectPtr = NULL;
  262. o->health = 0;
  263. o->energy = 0;
  264. o->whichBaseObject = -1;
  265. o->pixResID = -1;
  266. o->attributes = 0;
  267. o->baseType = NULL;
  268. o = mGetMiniObjectPtr( kMiniTargetObjectNum);
  269. o->id = -1;
  270. o->beamType = -1;
  271. o->pulseType = -1;
  272. o->specialType = -1;
  273. o->destinationLocation.h = o->destinationLocation.v = -1;
  274. o->destinationObject = -1;
  275. o->destObjectPtr = NULL;
  276. o->health = 0;
  277. o->energy = 0;
  278. o->whichBaseObject = -1;
  279. o->pixResID = -1;
  280. o->attributes = 0;
  281. o->baseType = NULL;
  282. globals()->gMiniScreenData.buildTimeBarValue = -1;
  283. globals()->gMiniScreenData.pollTime = 0;
  284. }
  285. void draw_mini_screen() {
  286. Rect mRect;
  287. Rect lRect, cRect;
  288. miniScreenLineType *c;
  289. RgbColor color, lightcolor, darkcolor, textcolor;
  290. unsigned char lineColor = kMiniScreenColor;
  291. long count, lineCorrect = 0;
  292. lRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, kMiniScreenRight,
  293. kMiniScreenBottom + globals()->gInstrumentTop);
  294. color = GetRGBTranslateColorShade(kMiniScreenColor, DARKEST);
  295. cRect = lRect;
  296. VideoDriver::driver()->fill_rect(cRect, color);
  297. mRect.left = kMiniScreenLeft;
  298. mRect.top = kMiniScreenTop + globals()->gInstrumentTop;
  299. mRect.right = kMiniScreenRight;
  300. mRect.bottom = kMiniScreenBottom + globals()->gInstrumentTop;
  301. c = globals()->gMiniScreenData.lineData.get();
  302. for ( count = 0; count < kMiniScreenTrueLineNum; count++)
  303. {
  304. if ( count == kMiniScreenCharHeight)
  305. {
  306. lRect.left = mRect.left = kButBoxLeft;
  307. lRect.top = mRect.top = kButBoxTop + globals()->gInstrumentTop;
  308. lRect.right = mRect.right = kButBoxRight;
  309. lRect.bottom = mRect.bottom = kButBoxBottom + globals()->gInstrumentTop;
  310. color = GetRGBTranslateColorShade(kMiniButColor, DARKEST);
  311. cRect = lRect;
  312. VideoDriver::driver()->fill_rect(cRect, color);
  313. lineCorrect = -kMiniScreenCharHeight;
  314. lineColor = kMiniButColor;
  315. }
  316. if ( c->underline)
  317. {
  318. const RgbColor color = GetRGBTranslateColorShade(lineColor, MEDIUM);
  319. int32_t y = mRect.top + (count + lineCorrect) * computer_font->height
  320. + computer_font->ascent;
  321. VideoDriver::driver()->draw_line(
  322. Point(mRect.left, y), Point(mRect.right - 2, y), color);
  323. }
  324. if ( c->hiliteLeft < c->hiliteRight)
  325. {
  326. if ( c->selectable == selectDim)
  327. textcolor = GetRGBTranslateColorShade(lineColor, VERY_DARK);
  328. else
  329. textcolor = GetRGBTranslateColorShade(lineColor, VERY_LIGHT);
  330. switch( c->lineKind)
  331. {
  332. case plainLineKind:
  333. if ( c->hiliteRight > c->hiliteLeft)
  334. {
  335. cRect.left = c->hiliteLeft;
  336. cRect.top = mRect.top + (( count + lineCorrect) * ( computer_font->height /* * 2 */));
  337. cRect.right = c->hiliteRight;
  338. cRect.bottom = cRect.top + computer_font->height /* * 2 */;
  339. // color = GetTranslateColorShade( lineColor, DARK);
  340. color = GetRGBTranslateColorShade(lineColor, DARK);
  341. lightcolor = GetRGBTranslateColorShade(lineColor, MEDIUM);
  342. darkcolor = GetRGBTranslateColorShade(lineColor, DARKER);
  343. draw_shaded_rect(cRect, color, lightcolor, darkcolor);
  344. }
  345. break;
  346. case buttonOffLineKind:
  347. cRect.left = c->hiliteLeft - 2;
  348. cRect.top = lRect.top + (( count + lineCorrect) * ( computer_font->height /* * 2 */));
  349. cRect.right = c->hiliteRight + 2;
  350. cRect.bottom = cRect.top + computer_font->height /* * 2 */;
  351. color = GetRGBTranslateColorShade(lineColor, MEDIUM);
  352. lightcolor = GetRGBTranslateColorShade(lineColor, LIGHT);
  353. darkcolor = GetRGBTranslateColorShade(lineColor, DARK);
  354. draw_shaded_rect(cRect, color, lightcolor, darkcolor);
  355. break;
  356. case buttonOnLineKind:
  357. cRect.left = c->hiliteLeft - 2;
  358. cRect.top = lRect.top + (( count + lineCorrect) * ( computer_font->height /* * 2 */));
  359. cRect.right = lRect.right; //c->hiliteRight + 2;
  360. cRect.bottom = cRect.top + computer_font->height /* * 2 */;
  361. color = GetRGBTranslateColorShade(lineColor, LIGHT);
  362. lightcolor = GetRGBTranslateColorShade(lineColor, VERY_LIGHT);
  363. darkcolor = GetRGBTranslateColorShade(lineColor, MEDIUM);
  364. draw_shaded_rect(cRect, color, lightcolor, darkcolor);
  365. textcolor = RgbColor::kBlack;
  366. break;
  367. }
  368. } else
  369. {
  370. if ( c->selectable == selectDim)
  371. textcolor = GetRGBTranslateColorShade(lineColor, MEDIUM);
  372. else
  373. textcolor = GetRGBTranslateColorShade(lineColor, VERY_LIGHT);
  374. }
  375. computer_font->draw_sprite(
  376. Point(
  377. mRect.left + kMiniScreenLeftBuffer,
  378. mRect.top + (count + lineCorrect) * computer_font->height + computer_font->ascent),
  379. c->string, textcolor);
  380. c++;
  381. }
  382. draw_mini_ship_data(*mGetMiniObjectPtr(kMiniSelectObjectNum), YELLOW, kMiniSelectTop, kMiniSelectObjectNum + 1);
  383. draw_mini_ship_data(*mGetMiniObjectPtr(kMiniTargetObjectNum), SKY_BLUE, kMiniTargetTop, kMiniTargetObjectNum + 1);
  384. }
  385. void MakeMiniScreenFromIndString(short whichString) {
  386. Rect mRect(kMiniScreenLeft, kMiniScreenTop, kMiniScreenRight, kMiniScreenBottom);
  387. mRect.offset(0, globals()->gInstrumentTop);
  388. ClearMiniScreenLines();
  389. globals()->gMiniScreenData.currentScreen = whichString;
  390. globals()->gMiniScreenData.selectLine = kMiniScreenNoLineSelected;
  391. StringList string_list(kMiniScreenStringID);
  392. StringSlice string = string_list.at(whichString - 1);
  393. miniScreenLineType* const line_begin = globals()->gMiniScreenData.lineData.get();
  394. miniScreenLineType* const line_switch = line_begin + kMiniScreenCharHeight;
  395. miniScreenLineType* const line_end = line_begin + kMiniScreenTrueLineNum;
  396. miniScreenLineType* line = line_begin;
  397. bool escape = false;
  398. SFZ_FOREACH(Rune r, string, {
  399. if (escape) {
  400. escape = false;
  401. switch (r) {
  402. case kUnderlineEndLineChar:
  403. line->underline = true;
  404. // fall through.
  405. case kEndLineChar:
  406. ++line;
  407. if (line == line_end) {
  408. return;
  409. } else if (line == line_switch) {
  410. mRect = Rect(kButBoxLeft, kButBoxTop, kButBoxRight, kButBoxBottom);
  411. mRect.offset(0, globals()->gInstrumentTop);
  412. }
  413. break;
  414. case kSelectableLineChar:
  415. line->selectable = selectable;
  416. if (globals()->gMiniScreenData.selectLine == kMiniScreenNoLineSelected) {
  417. globals()->gMiniScreenData.selectLine = line - line_begin;
  418. line->hiliteLeft = mRect.left;
  419. line->hiliteRight = mRect.right;
  420. }
  421. break;
  422. case kIntoButtonChar:
  423. {
  424. line->lineKind = buttonOffLineKind;
  425. line->whichButton = kInLineButton;
  426. line->hiliteLeft
  427. = mRect.left + kMiniScreenLeftBuffer
  428. + computer_font->logicalWidth * line->string.size();
  429. sfz::String key_name;
  430. GetKeyNumName(Preferences::preferences()->key(kCompAcceptKeyNum), &key_name);
  431. pad_to(key_name, kKeyNameLength);
  432. line->string.append(key_name);
  433. line->hiliteRight
  434. = mRect.left + kMiniScreenLeftBuffer
  435. + computer_font->logicalWidth * line->string.size() - 1;
  436. }
  437. break;
  438. case kOutOfButtonChar:
  439. {
  440. line->lineKind = buttonOffLineKind;
  441. line->whichButton = kOutLineButton;
  442. line->hiliteLeft
  443. = mRect.left + kMiniScreenLeftBuffer
  444. + computer_font->logicalWidth * line->string.size();
  445. sfz::String key_name;
  446. GetKeyNumName(
  447. Preferences::preferences()->key(kCompCancelKeyNum), &key_name);
  448. pad_to(key_name, kKeyNameLength);
  449. line->string.append(key_name);
  450. line->hiliteRight
  451. = mRect.left + kMiniScreenLeftBuffer
  452. + computer_font->logicalWidth * line->string.size() - 1;
  453. }
  454. break;
  455. case kMiniScreenSpecChar:
  456. line->string.append(1, kMiniScreenSpecChar);
  457. break;
  458. }
  459. } else if (r == kMiniScreenSpecChar) {
  460. escape = true;
  461. } else {
  462. line->string.append(1, r);
  463. }
  464. while (line->string.size() > kMiniScreenCharWidth) {
  465. String excess(line->string.slice(kMiniScreenCharWidth));
  466. line->string.resize(kMiniScreenCharWidth);
  467. ++line;
  468. if (line == line_end) {
  469. return;
  470. } else if (line == line_switch) {
  471. mRect = Rect(kButBoxLeft, kButBoxTop, kButBoxRight, kButBoxBottom);
  472. mRect.offset(0, globals()->gInstrumentTop);
  473. }
  474. line->string.assign(excess);
  475. }
  476. });
  477. }
  478. void MiniComputerHandleKeys( unsigned long theseKeys, unsigned long lastKeys)
  479. {
  480. miniScreenLineType *line;
  481. long count, scrap;
  482. Rect mRect;
  483. if (( theseKeys | lastKeys) & kCompAcceptKey)
  484. {
  485. // find out which line, if any, contains this button
  486. line = globals()->gMiniScreenData.lineData.get();
  487. count = 0;
  488. while (( line->whichButton !=kInLineButton) && ( count < kMiniScreenTrueLineNum))
  489. {
  490. count++;
  491. line++;
  492. }
  493. // hilite/unhilite this button
  494. if ( count < kMiniScreenTrueLineNum)
  495. {
  496. if (( theseKeys & kCompAcceptKey) && ( line->lineKind != buttonOnLineKind))
  497. {
  498. line->lineKind = buttonOnLineKind;
  499. mPlayBeep3();
  500. } else if ((!( theseKeys & kCompAcceptKey)) && ( line->lineKind != buttonOffLineKind))
  501. {
  502. line->lineKind = buttonOffLineKind;
  503. MiniComputerDoAccept();
  504. }
  505. }
  506. }
  507. if (( theseKeys | lastKeys) & kCompCancelKey)
  508. {
  509. // find out which line, if any, contains this button
  510. line = globals()->gMiniScreenData.lineData.get();
  511. count = 0;
  512. while (( line->whichButton !=kOutLineButton) && ( count < kMiniScreenTrueLineNum))
  513. {
  514. count++;
  515. line++;
  516. }
  517. if ( count < kMiniScreenCharHeight)
  518. {
  519. mRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, kMiniScreenRight,
  520. kMiniScreenBottom + globals()->gInstrumentTop);
  521. } else
  522. {
  523. mRect = Rect(kButBoxLeft, kButBoxTop + globals()->gInstrumentTop, kButBoxRight,
  524. kButBoxBottom + globals()->gInstrumentTop);
  525. }
  526. // hilite/unhilite this button
  527. if ( count < kMiniScreenTrueLineNum)
  528. {
  529. if (( theseKeys & kCompCancelKey) && ( line->lineKind != buttonOnLineKind))
  530. {
  531. line->lineKind = buttonOnLineKind;
  532. mPlayBeep3();
  533. } else if ((!( theseKeys & kCompCancelKey)) && ( line->lineKind != buttonOffLineKind))
  534. {
  535. line->lineKind = buttonOffLineKind;
  536. MiniComputerDoCancel();
  537. }
  538. }
  539. }
  540. if (( theseKeys & kCompUpKey) && ( !(lastKeys & kCompUpKey)) && ( globals()->gMiniScreenData.selectLine !=
  541. kMiniScreenNoLineSelected))
  542. {
  543. scrap = globals()->gMiniScreenData.selectLine;
  544. line = globals()->gMiniScreenData.lineData.get() + globals()->gMiniScreenData.selectLine;
  545. line->hiliteLeft = line->hiliteRight = 0;
  546. do
  547. {
  548. line--;
  549. globals()->gMiniScreenData.selectLine--;
  550. if ( globals()->gMiniScreenData.selectLine < 0)
  551. {
  552. globals()->gMiniScreenData.selectLine = kMiniScreenTrueLineNum - 1;
  553. line = globals()->gMiniScreenData.lineData.get() + kMiniScreenTrueLineNum - 1L;
  554. }
  555. } while ( line->selectable == cannotSelect);
  556. if ( globals()->gMiniScreenData.selectLine < kMiniScreenCharHeight)
  557. {
  558. mRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, kMiniScreenRight,
  559. kMiniScreenBottom + globals()->gInstrumentTop);
  560. } else
  561. {
  562. mRect = Rect(kButBoxLeft, kButBoxTop + globals()->gInstrumentTop, kButBoxRight,
  563. kButBoxBottom + globals()->gInstrumentTop);
  564. }
  565. line->hiliteLeft = mRect.left;
  566. line->hiliteRight = mRect.right;
  567. }
  568. if (( theseKeys & kCompDownKey) && ( !(lastKeys & kCompDownKey)) && ( globals()->gMiniScreenData.selectLine !=
  569. kMiniScreenNoLineSelected))
  570. {
  571. scrap = globals()->gMiniScreenData.selectLine;
  572. line = globals()->gMiniScreenData.lineData.get() + globals()->gMiniScreenData.selectLine;
  573. line->hiliteLeft = line->hiliteRight = 0;
  574. do
  575. {
  576. line++;
  577. globals()->gMiniScreenData.selectLine++;
  578. if ( globals()->gMiniScreenData.selectLine >= kMiniScreenTrueLineNum)
  579. {
  580. globals()->gMiniScreenData.selectLine = 0;
  581. line = globals()->gMiniScreenData.lineData.get();
  582. }
  583. } while ( line->selectable == cannotSelect);
  584. if ( globals()->gMiniScreenData.selectLine < kMiniScreenCharHeight)
  585. {
  586. mRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, kMiniScreenRight,
  587. kMiniScreenBottom + globals()->gInstrumentTop);
  588. } else
  589. {
  590. mRect = Rect(kButBoxLeft, kButBoxTop + globals()->gInstrumentTop, kButBoxRight,
  591. kButBoxBottom + globals()->gInstrumentTop);
  592. }
  593. line->hiliteLeft = mRect.left;
  594. line->hiliteRight = mRect.right;
  595. }
  596. }
  597. void MiniComputerHandleNull( long unitsToDo)
  598. {
  599. destBalanceType *buildAtObject = NULL;
  600. long count;
  601. spaceObjectType *realObject = NULL, *myObject = NULL, newObject;
  602. globals()->gMiniScreenData.pollTime += unitsToDo;
  603. if ( globals()->gMiniScreenData.pollTime > kMiniComputerPollTime)
  604. {
  605. globals()->gMiniScreenData.pollTime = 0;
  606. UpdateMiniScreenLines();
  607. // handle control/command/selected object
  608. myObject = mGetMiniObjectPtr( kMiniSelectObjectNum);
  609. count = GetAdmiralConsiderObject( globals()->gPlayerAdmiralNumber);
  610. if ( count >= 0)
  611. {
  612. realObject = gSpaceObjectData.get() + count;
  613. mCopyMiniSpaceObject( newObject, *realObject);
  614. } else
  615. {
  616. newObject.id = -1;
  617. newObject.beamType = -1;
  618. newObject.pulseType = -1;
  619. newObject.specialType = -1;
  620. newObject.destinationLocation.h = newObject.destinationLocation.v = -1;
  621. newObject.destinationObject = -1;
  622. newObject.destObjectPtr = NULL;
  623. newObject.health = 0;
  624. newObject.energy = 0;
  625. newObject.whichBaseObject = -1;
  626. newObject.pixResID = -1;
  627. newObject.attributes = 0;
  628. newObject.baseType = NULL;
  629. }
  630. mCopyMiniSpaceObject(*myObject, newObject);
  631. myObject = mGetMiniObjectPtr( kMiniTargetObjectNum);
  632. count = GetAdmiralDestinationObject( globals()->gPlayerAdmiralNumber);
  633. if ( count >= 0)
  634. {
  635. realObject = gSpaceObjectData.get() + count;
  636. mCopyMiniSpaceObject( newObject, *realObject);
  637. } else
  638. {
  639. newObject.id = -1;
  640. newObject.beamType = -1;
  641. newObject.pulseType = -1;
  642. newObject.specialType = -1;
  643. newObject.destinationLocation.h = newObject.destinationLocation.v = -1;
  644. newObject.destinationObject = -1;
  645. newObject.destObjectPtr = NULL;
  646. newObject.health = 0;
  647. newObject.energy = 0;
  648. newObject.whichBaseObject = -1;
  649. newObject.pixResID = -1;
  650. newObject.attributes = 0;
  651. newObject.baseType = NULL;
  652. }
  653. mCopyMiniSpaceObject(*myObject, newObject);
  654. int build_at = GetAdmiralBuildAtObject(globals()->gPlayerAdmiralNumber);
  655. if (build_at >= 0) {
  656. buildAtObject = mGetDestObjectBalancePtr(build_at);
  657. if (buildAtObject->totalBuildTime > 0) {
  658. int progress = buildAtObject->buildTime * kMiniBuildTimeHeight;
  659. progress /= buildAtObject->totalBuildTime;
  660. globals()->gMiniScreenData.buildTimeBarValue = progress;
  661. } else {
  662. globals()->gMiniScreenData.buildTimeBarValue = 0;
  663. }
  664. } else {
  665. globals()->gMiniScreenData.buildTimeBarValue = -1;
  666. }
  667. }
  668. }
  669. // only for updating volitile lines--doesn't draw whole screen!
  670. void UpdateMiniScreenLines( void)
  671. {
  672. admiralType *admiral = NULL;
  673. miniScreenLineType *line = NULL;
  674. baseObjectType *buildObject = NULL;
  675. long lineNum, count;
  676. Rect mRect;
  677. mRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, kMiniScreenRight,
  678. kMiniScreenBottom + globals()->gInstrumentTop);
  679. switch( globals()->gMiniScreenData.currentScreen)
  680. {
  681. case kBuildMiniScreen:
  682. admiral = globals()->gAdmiralData.get() + globals()->gPlayerAdmiralNumber;
  683. line = globals()->gMiniScreenData.lineData.get() +
  684. kBuildScreenWhereNameLine;
  685. if ( line->value !=
  686. GetAdmiralBuildAtObject( globals()->gPlayerAdmiralNumber))
  687. {
  688. if ( globals()->gMiniScreenData.selectLine !=
  689. kMiniScreenNoLineSelected)
  690. {
  691. line = globals()->gMiniScreenData.lineData.get()
  692. + globals()->gMiniScreenData.selectLine;
  693. line->hiliteLeft = line->hiliteRight = 0;
  694. globals()->gMiniScreenData.selectLine =
  695. kMiniScreenNoLineSelected;
  696. }
  697. MiniComputerSetBuildStrings();
  698. } else if ( GetAdmiralBuildAtObject( globals()->gPlayerAdmiralNumber)
  699. >= 0)
  700. {
  701. line = globals()->gMiniScreenData.lineData.get() + kBuildScreenFirstTypeLine;
  702. lineNum = kBuildScreenFirstTypeLine;
  703. for ( count = 0; count < kMaxShipCanBuild; count++)
  704. {
  705. buildObject = line->sourceData;
  706. if ( buildObject != NULL)
  707. {
  708. if ( buildObject->price > mFixedToLong(admiral->cash))
  709. {
  710. if ( line->selectable != selectDim)
  711. {
  712. line->selectable = selectDim;
  713. }
  714. } else
  715. {
  716. if (line->selectable != selectable)
  717. {
  718. if ( globals()->gMiniScreenData.selectLine ==
  719. kMiniScreenNoLineSelected)
  720. {
  721. globals()->gMiniScreenData.selectLine =
  722. lineNum;
  723. line->hiliteLeft = mRect.left;
  724. line->hiliteRight = mRect.right;
  725. }
  726. line->selectable = selectable;
  727. }
  728. }
  729. }
  730. line++;
  731. lineNum++;
  732. }
  733. }
  734. break;
  735. case kStatusMiniScreen:
  736. for ( count = kStatusMiniScreenFirstLine; count <
  737. kMiniScreenCharHeight; count++)
  738. {
  739. line =
  740. globals()->gMiniScreenData.lineData.get() +
  741. count;
  742. lineNum = MiniComputerGetStatusValue( count);
  743. if ( line->value != lineNum)
  744. {
  745. line->value = lineNum;
  746. MiniComputerMakeStatusString(count, line->string);
  747. }
  748. }
  749. break;
  750. }
  751. }
  752. static void draw_player_ammo_in_rect(int32_t value, int8_t hue, const Rect& rect) {
  753. if (value >= 0) {
  754. const RgbColor text_color = GetRGBTranslateColorShade(hue, VERY_LIGHT);
  755. const char digits[] = {
  756. ((value % 1000) / 100) + '0',
  757. ((value % 100) / 10) + '0',
  758. (value % 10) + '0',
  759. '\0',
  760. };
  761. Point origin(rect.left + kMiniAmmoTextHBuffer, rect.bottom - 1);
  762. computer_font->draw_sprite(origin, digits, text_color);
  763. }
  764. }
  765. void draw_player_ammo(int32_t ammo_one, int32_t ammo_two, int32_t ammo_special) {
  766. Rect clip(0, kMiniAmmoTop, kMiniAmmoSingleWidth, kMiniAmmoBottom);
  767. clip.offset(0, globals()->gInstrumentTop);
  768. clip.offset(kMiniAmmoLeftOne - clip.left, 0);
  769. draw_player_ammo_in_rect(ammo_one, RED, clip);
  770. clip.offset(kMiniAmmoLeftTwo - clip.left, 0);
  771. draw_player_ammo_in_rect(ammo_two, PALE_GREEN, clip);
  772. clip.offset(kMiniAmmoLeftSpecial - clip.left, 0);
  773. draw_player_ammo_in_rect(ammo_special, ORANGE, clip);
  774. }
  775. void draw_mini_ship_data(
  776. const spaceObjectType& newObject, unsigned char headerColor,
  777. short screenTop, short whichString) {
  778. Rect lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, 0, 0, kMiniScreenWidth);
  779. RgbColor color = GetRGBTranslateColorShade(headerColor, LIGHT);
  780. RgbColor lightcolor = GetRGBTranslateColorShade(headerColor, VERY_LIGHT);
  781. RgbColor darkcolor = GetRGBTranslateColorShade(headerColor, MEDIUM);
  782. draw_shaded_rect(lRect, color, lightcolor, darkcolor);
  783. String text(StringList(kMiniDataStringID).at(whichString - 1));
  784. computer_font->draw_sprite(
  785. Point(lRect.left + kMiniScreenLeftBuffer, lRect.top + computer_font->ascent),
  786. text, RgbColor::kBlack);
  787. if (newObject.attributes & kIsDestination) {
  788. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniNameLineNum, 0, kMiniScreenWidth);
  789. // get the color for writing the name
  790. color = GetRGBTranslateColorShade(PALE_GREEN, VERY_LIGHT);
  791. // move to the 1st line in the selection miniscreen
  792. String text(GetDestBalanceName(newObject.destinationObject));
  793. computer_font->draw_sprite(
  794. Point(lRect.left + kMiniScreenLeftBuffer, lRect.top + computer_font->ascent),
  795. text, color);
  796. } else {
  797. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniNameLineNum, 0, kMiniScreenWidth);
  798. if (newObject.whichBaseObject >= 0) {
  799. // get the color for writing the name
  800. color = GetRGBTranslateColorShade(PALE_GREEN, VERY_LIGHT);
  801. // move to the 1st line in the selection miniscreen, write the name
  802. String text(StringList(kSpaceObjectShortNameResID).at(newObject.whichBaseObject));
  803. computer_font->draw_sprite(
  804. Point(lRect.left + kMiniScreenLeftBuffer, lRect.top + computer_font->ascent),
  805. text, color);
  806. }
  807. }
  808. // set the rect for drawing the "icon" of the object type
  809. Rect dRect;
  810. dRect.left = kMiniIconLeft;
  811. dRect.top = screenTop + globals()->gInstrumentTop + MiniIconMacLineTop();
  812. dRect.right = kMiniScreenLeft + kMiniIconWidth;
  813. dRect.bottom = dRect.top + kMiniIconHeight;
  814. if ((newObject.whichBaseObject >= 0) && (newObject.pixResID >= 0)) {
  815. NatePixTable* pixTable = GetPixTable(newObject.pixResID);
  816. if (pixTable != NULL) {
  817. short whichShape;
  818. if (newObject.attributes & kIsSelfAnimated) {
  819. whichShape = more_evil_fixed_to_long(newObject.baseType->frame.animation.firstShape);
  820. } else {
  821. whichShape = 0;
  822. }
  823. // get the picture data
  824. const NatePixTable::Frame& frame = pixTable->at(whichShape);
  825. Rect rect(0, 0, frame.width(), frame.height());
  826. int32_t max_dimension = max(frame.width(), frame.height());
  827. if (max_dimension > kMiniIconHeight) {
  828. rect.right = (rect.right * (kMiniIconHeight - 4)) / max_dimension;
  829. rect.bottom = (rect.bottom * (kMiniIconHeight - 4)) / max_dimension;
  830. }
  831. rect.center_in(dRect);
  832. frame.sprite().draw(rect);
  833. }
  834. }
  835. color = GetRGBTranslateColorShade(PALE_GREEN, MEDIUM);
  836. draw_vbracket(dRect, color);
  837. if (newObject.baseType != NULL) {
  838. if ((newObject.baseType->health > 0) && (newObject.health > 0)) {
  839. Rect dRect;
  840. dRect.left = kMiniHealthLeft;
  841. dRect.top = screenTop + globals()->gInstrumentTop + MiniIconMacLineTop();
  842. dRect.right = dRect.left + kMiniBarWidth;
  843. dRect.bottom = dRect.top + kMiniIconHeight;
  844. uint32_t tlong = newObject.health * kMiniBarHeight;
  845. tlong /= newObject.baseType->health;
  846. color = GetRGBTranslateColorShade(SKY_BLUE, DARK);
  847. lRect.left = dRect.left + 2;
  848. lRect.top = dRect.top + 2;
  849. lRect.right = dRect.right - 2;
  850. lRect.bottom = dRect.bottom - 2 - tlong;
  851. VideoDriver::driver()->fill_rect(lRect, color);
  852. color = GetRGBTranslateColorShade(SKY_BLUE, LIGHT);
  853. lRect.top = dRect.bottom - 2 - tlong;
  854. lRect.bottom = dRect.bottom - 2;
  855. VideoDriver::driver()->fill_rect(lRect, color);
  856. color = GetRGBTranslateColorShade(SKY_BLUE, MEDIUM);
  857. draw_vbracket(dRect, color);
  858. }
  859. }
  860. if (newObject.baseType != NULL) {
  861. if ((newObject.baseType->energy > 0) && (newObject.energy > 0)) {
  862. Rect dRect;
  863. dRect.left = kMiniEnergyLeft;
  864. dRect.top = screenTop + globals()->gInstrumentTop + MiniIconMacLineTop();
  865. dRect.right = dRect.left + kMiniBarWidth;
  866. dRect.bottom = dRect.top + kMiniIconHeight;
  867. uint32_t tlong = newObject.energy * kMiniBarHeight;
  868. tlong /= newObject.baseType->energy;
  869. color = GetRGBTranslateColorShade(YELLOW, DARK);
  870. lRect.left = dRect.left + 2;
  871. lRect.top = dRect.top + 2;
  872. lRect.right = dRect.right - 2;
  873. lRect.bottom = dRect.bottom - 2 - tlong;
  874. VideoDriver::driver()->fill_rect(lRect, color);
  875. color = GetRGBTranslateColorShade(YELLOW, LIGHT);
  876. lRect.top = dRect.bottom - 2 - tlong;
  877. lRect.bottom = dRect.bottom - 2;
  878. VideoDriver::driver()->fill_rect(lRect, color);
  879. color = GetRGBTranslateColorShade(YELLOW, MEDIUM);
  880. draw_vbracket(dRect, color);
  881. }
  882. }
  883. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniWeapon1LineNum, kMiniRightColumnLeft, kMiniScreenWidth);
  884. // get the color for writing the name
  885. color = GetRGBTranslateColorShade(PALE_GREEN, VERY_LIGHT);
  886. // move to the 1st line in the selection miniscreen, write the name
  887. if (newObject.beamType >= 0) {
  888. String text(StringList(kSpaceObjectShortNameResID).at(newObject.beamType));
  889. computer_font->draw_sprite(
  890. Point(lRect.left, lRect.top + computer_font->ascent), text, color);
  891. }
  892. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniWeapon2LineNum, kMiniRightColumnLeft, kMiniScreenWidth);
  893. // get the color for writing the name
  894. color = GetRGBTranslateColorShade(PALE_GREEN, VERY_LIGHT);
  895. // move to the 1st line in the selection miniscreen, write the name
  896. if (newObject.pulseType >= 0) {
  897. String text(StringList(kSpaceObjectShortNameResID).at(newObject.pulseType));
  898. computer_font->draw_sprite(
  899. Point(lRect.left, lRect.top + computer_font->ascent), text, color);
  900. }
  901. // Don't show special weapons of destination objects.
  902. if (!(newObject.attributes & kIsDestination)) {
  903. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniWeapon3LineNum, kMiniRightColumnLeft, kMiniScreenWidth);
  904. // get the color for writing the name
  905. color = GetRGBTranslateColorShade(PALE_GREEN, VERY_LIGHT);
  906. // move to the 1st line in the selection miniscreen, write the name
  907. if (newObject.specialType >= 0) {
  908. String text(StringList(kSpaceObjectShortNameResID).at(newObject.specialType));
  909. computer_font->draw_sprite(
  910. Point(lRect.left, lRect.top + computer_font->ascent), text, color);
  911. }
  912. }
  913. lRect = mini_screen_line_bounds(screenTop + globals()->gInstrumentTop, kMiniDestLineNum, 0, kMiniScreenWidth);
  914. // write the name
  915. if (newObject.destinationObject >= 0) {
  916. if (newObject.destObjectPtr != NULL) {
  917. spaceObjectType* dObject = newObject.destObjectPtr;
  918. // get the color for writing the name
  919. if (dObject->owner == globals()->gPlayerAdmiralNumber) {
  920. color = GetRGBTranslateColorShade(GREEN, VERY_LIGHT);
  921. } else {
  922. color = GetRGBTranslateColorShade(RED, VERY_LIGHT);
  923. }
  924. if (dObject->attributes & kIsDestination) {
  925. String text(GetDestBalanceName(dObject->destinationObject));
  926. computer_font->draw_sprite(
  927. Point(lRect.left, lRect.top + computer_font->ascent), text, color);
  928. } else {
  929. String text(StringList(kSpaceObjectNameResID).at(dObject->whichBaseObject));
  930. computer_font->draw_sprite(
  931. Point(lRect.left, lRect.top + computer_font->ascent), text, color);
  932. }
  933. }
  934. }
  935. }
  936. void MiniComputerDoAccept( void)
  937. {
  938. if (true) { // TODO(sfiera): if non-networked.
  939. MiniComputerExecute( globals()->gMiniScreenData.currentScreen,
  940. globals()->gMiniScreenData.selectLine, globals()->gPlayerAdmiralNumber);
  941. } else {
  942. #ifdef NETSPROCKET_AVAILABLE
  943. if ( !SendMenuMessage( globals()->gGameTime + gNetLatency, globals()->gMiniScreenData.currentScreen,
  944. globals()->gMiniScreenData.selectLine))
  945. StopNetworking();
  946. #endif NETSPROCKET_AVAILABLE
  947. }
  948. }
  949. void MiniComputerExecute( long whichPage, long whichLine, long whichAdmiral)
  950. {
  951. spaceObjectType *anObject, *anotherObject;
  952. long l;
  953. switch ( whichPage)
  954. {
  955. case kMainMiniScreen:
  956. if ( whichAdmiral == globals()->gPlayerAdmiralNumber)
  957. {
  958. switch ( whichLine)
  959. {
  960. case kMainMiniBuild:
  961. MakeMiniScreenFromIndString( kBuildMiniScreen);
  962. MiniComputerSetBuildStrings();
  963. break;
  964. case kMainMiniSpecial:
  965. MakeMiniScreenFromIndString( kSpecialMiniScreen);
  966. break;
  967. case kMainMiniMessage:
  968. MakeMiniScreenFromIndString( kMessageMiniScreen);
  969. break;
  970. case kMainMiniStatus:
  971. MakeMiniScreenFromIndString( kStatusMiniScreen);
  972. MiniComputerSetStatusStrings();
  973. break;
  974. default:
  975. break;
  976. }
  977. }
  978. break;
  979. case kBuildMiniScreen:
  980. if ( globals()->keyMask & kComputerBuildMenu) return;
  981. if ( whichLine != kMiniScreenNoLineSelected)
  982. {
  983. if ( CountObjectsOfBaseType( -1, -1) <
  984. (kMaxSpaceObject - kMaxShipBuffer))
  985. {
  986. if (AdmiralScheduleBuild( whichAdmiral,
  987. whichLine - kBuildScreenFirstTypeLine) == false)
  988. {
  989. if ( whichAdmiral == globals()->gPlayerAdmiralNumber)
  990. mPlayBeepBad();
  991. }
  992. } else
  993. {
  994. if ( whichAdmiral == globals()->gPlayerAdmiralNumber)
  995. {
  996. SetStatusString("Maximum number of ships built", ORANGE);
  997. }
  998. }
  999. }
  1000. break;
  1001. case kSpecialMiniScreen:
  1002. if ( globals()->keyMask & kComputerSpecialMenu) return;
  1003. switch ( whichLine)
  1004. {
  1005. case kSpecialMiniTransfer:
  1006. l = GetAdmiralConsiderObject( whichAdmiral);
  1007. anObject = GetAdmiralFlagship( whichAdmiral);
  1008. if ( anObject != NULL)
  1009. {
  1010. if ( l != kNoShip)
  1011. {
  1012. anotherObject = gSpaceObjectData.get() + l;
  1013. if (( anotherObject->active != kObjectInUse) ||
  1014. ( !(anotherObject->attributes & kCanThink)) ||
  1015. ( anotherObject->attributes & kStaticDestination)
  1016. || ( anotherObject->owner != anObject->owner) ||
  1017. (!(anotherObject->attributes & kCanAcceptDestination))
  1018. || ( !(anotherObject->attributes & kCanBeDestination))
  1019. || ( anObject->active != kObjectInUse))
  1020. {
  1021. if ( whichAdmiral == globals()->gPlayerAdmiralNumber)
  1022. mPlayBeepBad();
  1023. } else
  1024. {
  1025. ChangePlayerShipNumber( whichAdmiral, l);
  1026. }
  1027. } else
  1028. {
  1029. PlayerShipBodyExpire( anObject, false);
  1030. }
  1031. }
  1032. break;
  1033. case kSpecialMiniFire1:
  1034. l = GetAdmiralConsiderObject( whichAdmiral);
  1035. if (( l != kNoShip))
  1036. {
  1037. anObject = gSpaceObjectData.get() + l;
  1038. if (( anObject->active) &&
  1039. (anObject->attributes & ( kCanAcceptDestination)))
  1040. {
  1041. anObject->keysDown |= kOneKey | kManualOverrideFlag;
  1042. }
  1043. }
  1044. break;
  1045. case kSpecialMiniFire2:
  1046. l = GetAdmiralConsiderObject( whichAdmiral);
  1047. if (( l != kNoShip))
  1048. {
  1049. anObject = gSpaceObjectData.get() + l;
  1050. if (( anObject->active) &&
  1051. (anObject->attributes & ( kCanAcceptDestination)))
  1052. {
  1053. anObject->keysDown |= kTwoKey | kManualOverrideFlag;
  1054. }
  1055. }
  1056. break;
  1057. case kSpecialMiniFireSpecial:
  1058. l = GetAdmiralConsiderObject( whichAdmiral);
  1059. if (( l != kNoShip))
  1060. {
  1061. anObject = gSpaceObjectData.get() + l;
  1062. if (( anObject->active) &&
  1063. (anObject->attributes & ( kCanAcceptDestination)))
  1064. {
  1065. anObject->keysDown |= kEnterKey | kManualOverrideFlag;
  1066. }
  1067. }
  1068. break;
  1069. case kSpecialMiniHold:
  1070. l = GetAdmiralConsiderObject( whichAdmiral);
  1071. if (( l != kNoShip))
  1072. {
  1073. anObject = gSpaceObjectData.get() + l;
  1074. SetObjectLocationDestination( anObject, &(anObject->location));
  1075. }
  1076. break;
  1077. case kSpecialMiniGoToMe:
  1078. l = GetAdmiralConsiderObject( whichAdmiral);
  1079. if (( l != kNoShip))
  1080. {
  1081. anObject = gSpaceObjectData.get() + l;
  1082. anotherObject = GetAdmiralFlagship( whichAdmiral);
  1083. SetObjectLocationDestination( anObject, &(anotherObject->location));
  1084. }
  1085. break;
  1086. default:
  1087. break;
  1088. }
  1089. break;
  1090. case kMessageMiniScreen:
  1091. if ( globals()->keyMask & kComputerMessageMenu) return;
  1092. if ( whichAdmiral == globals()->gPlayerAdmiralNumber)
  1093. {
  1094. switch ( whichLine)
  1095. {
  1096. case kMessageMiniNext:
  1097. AdvanceCurrentLongMessage();
  1098. break;
  1099. case kMessageMiniLast:
  1100. ReplayLastLongMessage();
  1101. break;
  1102. case kMessageMiniPrevious:
  1103. PreviousCurrentLongMessage();
  1104. break;
  1105. default:
  1106. break;
  1107. }
  1108. }
  1109. break;
  1110. default:
  1111. break;
  1112. }
  1113. }
  1114. void MiniComputerDoCancel( void)
  1115. {
  1116. switch ( globals()->gMiniScreenData.currentScreen)
  1117. {
  1118. case kBuildMiniScreen:
  1119. case kSpecialMiniScreen:
  1120. case kMessageMiniScreen:
  1121. case kStatusMiniScreen:
  1122. MakeMiniScreenFromIndString( kMainMiniScreen);
  1123. break;
  1124. default:
  1125. break;
  1126. }
  1127. }
  1128. void MiniComputerSetBuildStrings( void) // sets the ship type strings for the build screen
  1129. // also sets up the values = base object num
  1130. {
  1131. baseObjectType *buildObject = NULL;
  1132. admiralType *admiral = NULL;
  1133. destBalanceType *buildAtObject = NULL;
  1134. miniScreenLineType *line = NULL;
  1135. long count, baseNum, lineNum, buildAtObjectNum;
  1136. Rect mRect;
  1137. mRect = Rect(kMiniScreenLeft, kMiniScreenTop + globals()->gInstrumentTop, k

Large files files are truncated, but you can click here to view the full file