OUNITIF.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OUNITIF.CPP
  21. //Description : Unit Interface Routines
  22. #include <KEY.h>
  23. #include <OVGA.h>
  24. #include <OMOUSE.h>
  25. #include <OFONT.h>
  26. #include <OMOUSE.h>
  27. #include <OHELP.h>
  28. #include <OINFO.h>
  29. #include <OFIRMRES.h>
  30. #include <OIMGRES.h>
  31. #include <OBUTTON.h>
  32. #include <OBUTT3D.h>
  33. #include <OPOWER.h>
  34. #include <OSPY.h>
  35. #include <OSYS.h>
  36. #include <OGAME.h>
  37. #include <ONATION.h>
  38. #include <OWORLD.h>
  39. #include <OU_VEHI.h>
  40. #include <OREMOTE.h>
  41. #include <OSE.h>
  42. #include <OSERES.h>
  43. #include <OBUTTCUS.h>
  44. #include <OU_MARI.h>
  45. #ifdef NO_DEBUG_UNIT
  46. #undef err_when
  47. #undef err_here
  48. #undef err_if
  49. #undef err_else
  50. #undef err_now
  51. #define err_when(cond)
  52. #define err_here()
  53. #define err_if(cond)
  54. #define err_else
  55. #define err_now(msg)
  56. #undef DEBUG
  57. #endif
  58. //---------- Define constant ------------//
  59. enum { UNIT_MENU_MAIN,
  60. UNIT_MENU_BUILD,
  61. };
  62. #define BURN_COMBAT_LEVEL 80
  63. #define SPY_CLOAK_WIDTH 21
  64. //---------- Define static variables ----------//
  65. static Button3D button_build;
  66. static ButtonCustom button_build_array[MAX_FIRM_TYPE];
  67. static char button_build_flag[MAX_FIRM_TYPE];
  68. static Button3D button_settle;
  69. static Button3D button_assign;
  70. static Button3D button_promote, button_demote;
  71. static Button3D button_reward;
  72. static Button3D button_return_camp;
  73. static Button3D button_cancel;
  74. static Button button_cancel2;
  75. static Button3D button_resign;
  76. static Button3D button_succeed_king;
  77. static Button3D button_spy_notify;
  78. static Button3D button_spy_drop_identity;
  79. static Button3D button_aggressive_mode;
  80. static Button button_change_color;
  81. static short unit_menu_mode=UNIT_MENU_MAIN, last_unit_recno=0;
  82. // ##### begin Gilbert 3/10 #######//
  83. static short build_firm_button_order[MAX_FIRM_TYPE] =
  84. {
  85. FIRM_CAMP,
  86. FIRM_MINE,
  87. FIRM_FACTORY,
  88. FIRM_MARKET,
  89. FIRM_RESEARCH,
  90. FIRM_WAR_FACTORY,
  91. FIRM_INN,
  92. FIRM_HARBOR,
  93. FIRM_BASE,
  94. FIRM_MONSTER,
  95. };
  96. // ##### end Gilbert 3/10 #######//
  97. //--------- Declare static functions ---------//
  98. static void disp_debug_info(Unit* unitPtr, int dispY1, int refreshFlag);
  99. static void disp_firm_button(ButtonCustom *, int);
  100. static void group_resign();
  101. static void group_change_aggressive_mode();
  102. static void group_reward();
  103. static void group_change_spy_notify_flag();
  104. static void group_drop_spy_identity();
  105. //--------- Begin of function Unit::disp_info ---------//
  106. //
  107. void Unit::disp_info(int refreshFlag)
  108. {
  109. if( sprite_recno != last_unit_recno )
  110. {
  111. unit_menu_mode = UNIT_MENU_MAIN;
  112. last_unit_recno = sprite_recno;
  113. }
  114. switch( unit_menu_mode )
  115. {
  116. case UNIT_MENU_MAIN:
  117. switch( power.command_id )
  118. {
  119. case COMMAND_BUILD_FIRM:
  120. disp_build(refreshFlag);
  121. break;
  122. case COMMAND_SETTLE:
  123. disp_settle(refreshFlag);
  124. break;
  125. default:
  126. disp_main_menu(refreshFlag);
  127. }
  128. break;
  129. case UNIT_MENU_BUILD:
  130. disp_build_menu(refreshFlag);
  131. break;
  132. }
  133. }
  134. //----------- End of function Unit::disp_info -----------//
  135. //--------- Begin of function Unit::detect_info ---------//
  136. //
  137. void Unit::detect_info()
  138. {
  139. switch( unit_menu_mode )
  140. {
  141. case UNIT_MENU_MAIN:
  142. switch( power.command_id )
  143. {
  144. case COMMAND_BUILD_FIRM:
  145. detect_build();
  146. break;
  147. case COMMAND_SETTLE:
  148. detect_settle();
  149. break;
  150. default:
  151. detect_main_menu();
  152. }
  153. break;
  154. case UNIT_MENU_BUILD:
  155. detect_build_menu();
  156. break;
  157. }
  158. }
  159. //----------- End of function Unit::detect_info -----------//
  160. //--------- Begin of function Unit::disp_main_menu ---------//
  161. //
  162. void Unit::disp_main_menu(int refreshFlag)
  163. {
  164. disp_basic_info(INFO_Y1, refreshFlag);
  165. disp_unit_profile( INFO_Y1+52, refreshFlag );
  166. if( !should_show_info() )
  167. return;
  168. //---------------------------------//
  169. int y=INFO_Y1+98;
  170. if( race_id )
  171. {
  172. disp_unit_info( y, refreshFlag );
  173. y += 89;
  174. }
  175. //---------------------------------//
  176. if( is_own_spy() )
  177. {
  178. disp_spy_menu(y, refreshFlag);
  179. y+=spy_menu_height()+3;
  180. }
  181. if( is_own() )
  182. {
  183. if( refreshFlag == INFO_REPAINT )
  184. disp_button(y);
  185. y+=BUTTON_ACTION_HEIGHT;
  186. }
  187. #ifdef DEBUG
  188. if( sys.debug_session || sys.testing_session )
  189. disp_debug_info(this, INFO_Y2-68, refreshFlag);
  190. #endif
  191. }
  192. //----------- End of function Unit::disp_main_menu -----------//
  193. //-------- Begin of function Unit::should_show_info ------//
  194. //
  195. int Unit::should_show_info()
  196. {
  197. if( config.show_ai_info || is_own() )
  198. return 1;
  199. //---- if there is a phoenix of the player over this firm ----//
  200. if( nation_array.player_recno &&
  201. (~nation_array)->revealed_by_phoenix(next_x_loc(), next_y_loc()) )
  202. {
  203. return 1;
  204. }
  205. return 0;
  206. }
  207. //---------- End of function Unit::should_show_info --------//
  208. //--------- Begin of function Unit::detect_main_menu ---------//
  209. //
  210. void Unit::detect_main_menu()
  211. {
  212. if( detect_basic_info() )
  213. return;
  214. if( detect_unit_profile() )
  215. return;
  216. if( is_own_spy() )
  217. detect_spy_menu(INFO_Y1+187);
  218. if( is_own() )
  219. detect_button();
  220. }
  221. //----------- End of function Unit::detect_main_menu -----------//
  222. //--------- Begin of function Unit::disp_basic_info ---------//
  223. //
  224. void Unit::disp_basic_info(int dispY1, int refreshFlag)
  225. {
  226. //------- display the name of the unit --------//
  227. if( refreshFlag == INFO_REPAINT )
  228. {
  229. int dispName = unit_id == UNIT_CARAVAN || unit_res[unit_id]->unit_class == UNIT_CLASS_SHIP; // only display names for caravans and ships as their names are not displayed in the other part of the interface
  230. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+21 );
  231. if( nation_recno )
  232. {
  233. int dispTitle = is_own() || nation_recno==0; // only display title for own units or independent units (which is for rebel leader only)
  234. if( dispName )
  235. font_san.center_put( INFO_X1+21, dispY1, INFO_X2-2, dispY1+21, unit_name(dispTitle) );
  236. vga.d3_panel_down( INFO_X1+3, dispY1+3, INFO_X1+20, dispY1+18 );
  237. //------- display the nation color box -------//
  238. char *nationPict = image_button.get_ptr("V_COLCOD");
  239. vga_front.put_bitmap_remap(INFO_X1+3, dispY1+2, nationPict, game.get_color_remap_table(nation_recno, 0) );
  240. }
  241. else
  242. {
  243. if( dispName )
  244. font_san.center_put( INFO_X1, dispY1, INFO_X2-2, dispY1+21, unit_name() );
  245. }
  246. }
  247. dispY1+=23;
  248. //-------- display the hit points bar --------//
  249. if( refreshFlag == INFO_REPAINT )
  250. {
  251. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+27 );
  252. if( nation_recno == nation_array.player_recno &&
  253. can_resign())
  254. {
  255. button_resign.paint( INFO_X1+4, dispY1+1, "V_X-U", "V_X-D" );
  256. button_resign.set_help_code( "RESIGN" );
  257. }
  258. }
  259. //-------- display hit points in numbers --------//
  260. disp_hit_point(dispY1);
  261. }
  262. //----------- End of function Unit::disp_basic_info -----------//
  263. //--------- Begin of function Unit::detect_basic_info ---------//
  264. //
  265. int Unit::detect_basic_info()
  266. {
  267. //--- detect pressing on the name to center the unit on the screen ---//
  268. if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+21 ) )
  269. {
  270. world.go_loc( next_x_loc(), next_y_loc() );
  271. return 1;
  272. }
  273. //-------- detect resign button ----------//
  274. // ###### patch begin Alex 10/1 ########//
  275. // if( is_own() && rank_id != RANK_KING )
  276. if( nation_recno == nation_array.player_recno && rank_id != RANK_KING )
  277. {
  278. if( button_resign.detect(KEY_DEL) )
  279. {
  280. group_resign();
  281. return 1;
  282. }
  283. }
  284. // ###### patch end Alex 10/1 ########//
  285. return 0;
  286. }
  287. //----------- End of function Unit::detect_basic_info -----------//
  288. //--------- Begin of function Unit::disp_button ---------//
  289. //
  290. void Unit::disp_button(int dispY1)
  291. {
  292. int x=INFO_X1;
  293. //---- if currently in the mode of selecting a unit to succeed the king ----//
  294. if( nation_array.player_recno &&
  295. nation_recno == nation_array.player_recno &&
  296. (~nation_array)->king_unit_recno == 0 )
  297. {
  298. if( race_id )
  299. button_succeed_king.paint( x, dispY1, 'A', "SUCCEED" );
  300. return;
  301. }
  302. //------- display aggressive mode button ------//
  303. button_aggressive_mode.paint( x, dispY1, 'A', aggressive_mode ? (char*)"AGGRESS1" : (char*)"AGGRESS0" );
  304. x += BUTTON_ACTION_WIDTH;
  305. //---------- only for human units ---------//
  306. if( unit_res[unit_id]->unit_class == UNIT_CLASS_HUMAN && race_id )
  307. {
  308. int firmId;
  309. for( firmId=1; firmId<=MAX_FIRM_TYPE ; firmId++ )
  310. {
  311. if( firm_res[firmId]->can_build(sprite_recno) )
  312. break;
  313. }
  314. if( firmId<=MAX_FIRM_TYPE &&
  315. nation_recno == nation_array.player_recno ) // a spy cannot build structure for another nation
  316. {
  317. button_build.paint( x, dispY1, 'A', "BUILD" );
  318. x += BUTTON_ACTION_WIDTH;
  319. }
  320. else
  321. {
  322. button_build.reset();
  323. }
  324. //-------- settle button ----------//
  325. if( mobile_type==UNIT_LAND && rank_id != RANK_KING )
  326. {
  327. button_settle.paint( x, dispY1, 'A', "SETTLE" );
  328. x += BUTTON_ACTION_WIDTH;
  329. }
  330. else
  331. {
  332. button_settle.reset();
  333. }
  334. //-------- promote/demote button --------//
  335. button_promote.reset();
  336. button_demote.reset();
  337. if( nation_recno == nation_array.player_recno ) // you can't promote your spy in other nation
  338. {
  339. if( rank_id==RANK_SOLDIER && skill.skill_id==SKILL_LEADING )
  340. {
  341. if(unit_array.selected_count==1)
  342. {
  343. button_promote.paint( x, dispY1, 'A', "PROMOTE" );
  344. x += BUTTON_ACTION_WIDTH;
  345. }
  346. }
  347. else if( rank_id == RANK_GENERAL )
  348. {
  349. if( unit_array.selected_count==1 )
  350. {
  351. button_demote.paint( x, dispY1, 'A', "DEMOTE" );
  352. x += BUTTON_ACTION_WIDTH;
  353. }
  354. }
  355. }
  356. if( x+BUTTON_ACTION_WIDTH-5 > INFO_X2 )
  357. {
  358. x = INFO_X1;
  359. dispY1 += BUTTON_ACTION_HEIGHT;
  360. }
  361. //------------ "reward" button ---------//
  362. if( nation_recno == nation_array.player_recno && // you can't promote your spy in other nation
  363. rank_id != RANK_KING )
  364. {
  365. button_reward.paint( x, dispY1, 'A', "REWARD" );
  366. x += BUTTON_ACTION_WIDTH;
  367. if( x+BUTTON_ACTION_WIDTH-5 > INFO_X2 )
  368. {
  369. x = INFO_X1;
  370. dispY1 += BUTTON_ACTION_HEIGHT;
  371. }
  372. }
  373. else
  374. {
  375. button_reward.reset();
  376. }
  377. //------ "Return Camp" button -------//
  378. if( home_camp_firm_recno &&
  379. firm_array[home_camp_firm_recno]->region_id == region_id() )
  380. {
  381. button_return_camp.paint( x, dispY1, 'A', "RETCAMP" );
  382. x += BUTTON_ACTION_WIDTH;
  383. if( x+BUTTON_ACTION_WIDTH-5 > INFO_X2 )
  384. {
  385. x = INFO_X1;
  386. dispY1 += BUTTON_ACTION_HEIGHT;
  387. }
  388. }
  389. else
  390. {
  391. button_return_camp.reset();
  392. }
  393. /*
  394. //-------- burn button ----------//
  395. if( skill.combat_level > BURN_COMBAT_LEVEL && mobile_type==UNIT_LAND )
  396. {
  397. button_burn.paint_text( x, dispY1, "Burn" );
  398. x += 60;
  399. }
  400. else
  401. button_burn.reset();
  402. //-------- assign to firm button --------//
  403. if( mobile_type==UNIT_LAND )
  404. {
  405. button_assign.paint_text( x, dispY1, "Assign" );
  406. x+=60;
  407. }
  408. else
  409. button_assign.reset();
  410. */
  411. }
  412. //------- spy notify button ------//
  413. if( spy_recno && true_nation_recno() == nation_array.player_recno )
  414. {
  415. int notifyFlag = spy_array[spy_recno]->notify_cloaked_nation_flag;
  416. button_spy_notify.paint( x, dispY1, 'A', notifyFlag ? (char*)"SPYNOTI1" : (char*)"SPYNOTI0" );
  417. x += BUTTON_ACTION_WIDTH;
  418. if( x+BUTTON_ACTION_WIDTH-5 > INFO_X2 )
  419. {
  420. x = INFO_X1;
  421. dispY1 += BUTTON_ACTION_HEIGHT;
  422. }
  423. button_spy_drop_identity.paint( x, dispY1, 'A', "NOSPY" );
  424. }
  425. else
  426. {
  427. button_spy_notify.reset();
  428. button_spy_drop_identity.reset();
  429. }
  430. //---- display button for changing nation color scheme ----//
  431. if( sys.debug_session )
  432. button_change_color.paint_text( INFO_X1, INFO_Y2-20, "Change Nation Color" );
  433. }
  434. //----------- End of function Unit::disp_button -----------//
  435. //--------- Begin of function Unit::detect_button ---------//
  436. //
  437. void Unit::detect_button()
  438. {
  439. //---- if currently in the mode of selecting a unit to succeed the king ----//
  440. if( nation_array.player_recno &&
  441. nation_recno == nation_array.player_recno &&
  442. (~nation_array)->king_unit_recno == 0 )
  443. {
  444. if( race_id && button_succeed_king.detect() )
  445. {
  446. if( !remote.is_enable() )
  447. {
  448. (~nation_array)->succeed_king(sprite_recno);
  449. info.disp();
  450. }
  451. else
  452. {
  453. // packet structure : <unit recno> <nation recno>
  454. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_SUCCEED_KING, 2*sizeof(short));
  455. *shortPtr = sprite_recno;
  456. shortPtr[1] = nation_array.player_recno;
  457. }
  458. }
  459. return;
  460. }
  461. //--------- "return camp" button ---------//
  462. if( home_camp_firm_recno && button_return_camp.detect() )
  463. {
  464. // sound effect
  465. se_res.far_sound(next_x_loc(), next_y_loc(), 1, 'S', sprite_id, "ACK");
  466. unit_array.return_camp(COMMAND_PLAYER);
  467. return;
  468. }
  469. //------- toggle unit aggressive mode button ------//
  470. if( button_aggressive_mode.detect() )
  471. {
  472. group_change_aggressive_mode();
  473. }
  474. //-------- build button --------//
  475. if( button_build.detect() )
  476. {
  477. unit_menu_mode = UNIT_MENU_BUILD;
  478. info.disp();
  479. }
  480. //-------- settle button ---------//
  481. if( button_settle.detect() )
  482. {
  483. power.issue_command(COMMAND_SETTLE, sprite_recno);
  484. info.disp();
  485. return;
  486. }
  487. //-------- detect promote/demote button --------//
  488. if( rank_id == RANK_SOLDIER )
  489. {
  490. if( button_promote.detect() )
  491. {
  492. if(!remote.is_enable() )
  493. {
  494. set_rank(RANK_GENERAL);
  495. }
  496. else
  497. {
  498. // packet structure : <unit recno> <new rank>
  499. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_SET_RANK, 2*sizeof(short));
  500. *shortPtr = sprite_recno;
  501. shortPtr[1] = RANK_GENERAL;
  502. }
  503. se_ctrl.immediate_sound("TURN_ON");
  504. }
  505. }
  506. else if( rank_id == RANK_GENERAL )
  507. {
  508. if( button_demote.detect() )
  509. {
  510. if( !remote.is_enable() )
  511. {
  512. set_rank(RANK_SOLDIER);
  513. }
  514. else
  515. {
  516. // packet structure : <unit recno> <new rank>
  517. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_SET_RANK, 2*sizeof(short));
  518. *shortPtr = sprite_recno;
  519. shortPtr[1] = RANK_SOLDIER;
  520. }
  521. se_ctrl.immediate_sound("TURN_OFF");
  522. }
  523. }
  524. //------------ detect assign to firm button ------------//
  525. if( button_assign.detect() )
  526. {
  527. power.issue_command(COMMAND_ASSIGN, sprite_recno);
  528. }
  529. //------------ "reward" button ---------//
  530. if( button_reward.detect() )
  531. {
  532. group_reward();
  533. }
  534. //------- spy notify button ------//
  535. if( spy_recno && button_spy_notify.detect() )
  536. {
  537. group_change_spy_notify_flag();
  538. }
  539. //------- drop spy identity button ------//
  540. if( spy_recno && button_spy_drop_identity.detect() )
  541. {
  542. group_drop_spy_identity();
  543. }
  544. /*
  545. //--------- detect button for changing nation color -------//
  546. if( button_change_color.detect() )
  547. {
  548. Nation* nationPtr = nation_array[nation_recno];
  549. if( ++nationPtr->color_scheme_id > MAX_COLOR_SCHEME )
  550. nationPtr->color_scheme_id = 1;
  551. nationPtr->nation_color = game.color_remap_array[nationPtr->color_scheme_id-1].main_color;
  552. }
  553. */
  554. }
  555. //----------- End of function Unit::detect_button -----------//
  556. //----- Begin of static function Unit::can_resign -----//
  557. int Unit::can_resign()
  558. {
  559. return rank_id != RANK_KING;
  560. }
  561. //------ End of static function Unit::can_resign ----//
  562. //----- Begin of static function group_change_aggressive_mode -----//
  563. //
  564. static void group_change_aggressive_mode()
  565. {
  566. Unit* unitPtr = unit_array[unit_array.selected_recno];
  567. int newAggressiveMode = !unitPtr->aggressive_mode;
  568. //------ group chaning spy notify flag -------//
  569. for( int i=unit_array.size() ; i>0 ; i-- )
  570. {
  571. if( unit_array.is_deleted(i) )
  572. continue;
  573. unitPtr = unit_array[i];
  574. //------ if this is a player spy --------//
  575. if( unitPtr->selected_flag && unitPtr->is_own() )
  576. {
  577. if( !remote.is_enable() )
  578. {
  579. unitPtr->aggressive_mode = newAggressiveMode;
  580. }
  581. else
  582. {
  583. // packet structure : <unit no> <new aggressive mode>
  584. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_CHANGE_AGGRESSIVE_MODE, sizeof(short)*2);
  585. *shortPtr = i;
  586. shortPtr[1] = newAggressiveMode;
  587. }
  588. }
  589. }
  590. if( newAggressiveMode )
  591. se_ctrl.immediate_sound("TURN_ON");
  592. else
  593. se_ctrl.immediate_sound("TURN_OFF");
  594. button_aggressive_mode.update_bitmap( newAggressiveMode ? (char*)"AGGRESS1" : (char*)"AGGRESS0" );
  595. }
  596. //------ End of static function group_change_aggressive_mode ----//
  597. //----- Begin of static function group_resign -----//
  598. //
  599. static void group_resign()
  600. {
  601. Unit* unitPtr;
  602. //------ group chaning spy notify flag -------//
  603. for( int i=unit_array.size() ; i>0 ; i-- )
  604. {
  605. if( unit_array.is_deleted(i) )
  606. continue;
  607. unitPtr = unit_array[i];
  608. //------ if this is a player spy --------//
  609. if( unitPtr->selected_flag && unitPtr->is_own() && unitPtr->can_resign())
  610. unitPtr->resign(COMMAND_PLAYER);
  611. }
  612. }
  613. //------ End of static function group_resign ----//
  614. //----- Begin of static function group_reward -----//
  615. //
  616. static void group_reward()
  617. {
  618. Unit* unitPtr;
  619. //------ group chaning spy notify flag -------//
  620. for( int i=unit_array.size() ; i>0 ; i-- )
  621. {
  622. if( unit_array.is_deleted(i) )
  623. continue;
  624. unitPtr = unit_array[i];
  625. //------ if this is a player spy --------//
  626. if( unitPtr->selected_flag && unitPtr->is_own() )
  627. {
  628. if( !remote.is_enable() )
  629. unitPtr->reward(nation_array.player_recno);
  630. else
  631. {
  632. // packet structure : <unit no> + <rewarding nation recno>
  633. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_REWARD,sizeof(short)*2);
  634. *shortPtr = i;
  635. shortPtr[1] = nation_array.player_recno;
  636. }
  637. }
  638. }
  639. se_ctrl.immediate_sound("TURN_ON");
  640. }
  641. //------ End of static function group_reward ----//
  642. //----- Begin of static function group_change_spy_notify_flag -----//
  643. //
  644. static void group_change_spy_notify_flag()
  645. {
  646. Unit* unitPtr = unit_array[unit_array.selected_recno];
  647. Spy* spyPtr = spy_array[ unitPtr->spy_recno ];
  648. char newNotifyFlag = !spyPtr->notify_cloaked_nation_flag;
  649. //------ group chaning spy notify flag -------//
  650. for( int i=unit_array.size() ; i>0 ; i-- )
  651. {
  652. if( unit_array.is_deleted(i) )
  653. continue;
  654. unitPtr = unit_array[i];
  655. //------ if this is a player spy --------//
  656. if( unitPtr->selected_flag && unitPtr->is_own_spy() )
  657. {
  658. if( !remote.is_enable() )
  659. {
  660. spy_array[unitPtr->spy_recno]->notify_cloaked_nation_flag = newNotifyFlag;
  661. }
  662. else
  663. {
  664. // packet structure : <spy recno> <new notify_cloaked_nation_flag>
  665. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_CHANGE_NOTIFY_FLAG, sizeof(short)*2);
  666. *shortPtr = unitPtr->spy_recno;
  667. shortPtr[1] = newNotifyFlag;
  668. }
  669. }
  670. }
  671. //--------- update the spy bitmap ----------//
  672. button_spy_notify.update_bitmap( newNotifyFlag ? (char*)"SPYNOTI1" : (char*)"SPYNOTI0" );
  673. if( newNotifyFlag )
  674. se_ctrl.immediate_sound("TURN_ON");
  675. else
  676. se_ctrl.immediate_sound("TURN_OFF");
  677. }
  678. //------ End of static function group_change_spy_notify_flag ----//
  679. //------ Begin of static function group_drop_spy_identity -------//
  680. //
  681. static void group_drop_spy_identity()
  682. {
  683. Unit* unitPtr;
  684. //------ group drop spy identity -------//
  685. for( int i=unit_array.size() ; i>0 ; i-- )
  686. {
  687. if( unit_array.is_deleted(i) )
  688. continue;
  689. unitPtr = unit_array[i];
  690. //------ if this is a player spy --------//
  691. if( unitPtr->selected_flag && unitPtr->is_own_spy() )
  692. {
  693. if( !remote.is_enable() )
  694. {
  695. spy_array[unitPtr->spy_recno]->drop_spy_identity();
  696. }
  697. else
  698. {
  699. // packet structure : <spy recno>
  700. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_DROP_IDENTITY, sizeof(short));
  701. shortPtr[0] = unitPtr->spy_recno;
  702. }
  703. }
  704. }
  705. se_ctrl.immediate_sound("TURN_OFF");
  706. }
  707. //------- End of static function group_drop_spy_identity -------//
  708. //--------- Begin of function Unit::disp_build_menu ---------//
  709. //
  710. void Unit::disp_build_menu(int refreshFlag)
  711. {
  712. //---------- paint buttons ------------//
  713. if( refreshFlag == INFO_REPAINT )
  714. {
  715. // ####### begin Gilbert 3/10 ########//
  716. int firmId, x=INFO_X1, y=INFO_Y1, addedCount=0;
  717. String str;
  718. for( int i = 0; i < MAX_FIRM_TYPE; ++i )
  719. {
  720. firmId = build_firm_button_order[i];
  721. //---- check if the unit is the right race to build this firm ----//
  722. button_build_flag[i] = 0;
  723. if( firm_res[firmId]->can_build(sprite_recno) )
  724. {
  725. // button_build_array[firmId-1].paint( x, y, str, "F-DOWN");
  726. button_build_array[i].paint( x, y, x+99-1, y+60-1,
  727. disp_firm_button, ButtonCustomPara( game.get_color_remap_table(nation_recno,0) ,
  728. (unit_id << 16) + (race_id << 8) + firmId) );
  729. button_build_flag[i] = 1;
  730. addedCount++;
  731. if( addedCount & 1)
  732. {
  733. // old number, increase in x
  734. x += 102;
  735. }
  736. else
  737. {
  738. // even number, increase in y, reset x
  739. x -= 102;
  740. y += 63;
  741. }
  742. }
  743. }
  744. // ####### end Gilbert 3/10 ########//
  745. button_cancel.paint( x, y, 'A', "CANCEL" );
  746. }
  747. }
  748. //----------- End of function Unit::disp_build_menu -----------//
  749. //--------- Begin of function Unit::detect_build_menu ---------//
  750. //
  751. void Unit::detect_build_menu()
  752. {
  753. //----------- detect build buttons ------------//
  754. int firmId, addedCount=0, rc=0;
  755. // ##### begin Gilbert 3/10 #######//
  756. for( int i=0; i<MAX_FIRM_TYPE ; i++ )
  757. {
  758. firmId = build_firm_button_order[i];
  759. //---- check if the unit is the right race to build this firm ----//
  760. if( button_build_flag[i] && firm_res[firmId]->can_build(sprite_recno) )
  761. {
  762. if( button_build_array[i].detect() )
  763. {
  764. power.issue_command(COMMAND_BUILD_FIRM, sprite_recno, firmId);
  765. rc = 1;
  766. break;
  767. }
  768. addedCount++;
  769. }
  770. }
  771. // ##### end Gilbert 3/10 #######//
  772. //---------- detect cancel button ----------//
  773. if( button_cancel.detect() )
  774. {
  775. // ###### begin Gilbert 26/9 ######//
  776. se_ctrl.immediate_sound("TURN_OFF");
  777. // ###### end Gilbert 26/9 ######//
  778. rc = 1;
  779. }
  780. if( rc )
  781. {
  782. unit_menu_mode = UNIT_MENU_MAIN;
  783. info.disp();
  784. }
  785. }
  786. //----------- End of function Unit::detect_build_menu -----------//
  787. //--------- Begin of function Unit::disp_build ---------//
  788. //
  789. // Display the info when the player has selected the type of
  790. // structure to build.
  791. //
  792. void Unit::disp_build(int refreshFlag)
  793. {
  794. if( refreshFlag == INFO_REPAINT )
  795. {
  796. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+42 );
  797. String str;
  798. str = translate.process("Please select a location to build the ");
  799. str += firm_res[power.command_para]->name;
  800. str += ".";
  801. // FRENCH
  802. // font_san.put_paragraph( INFO_X1, INFO_Y1, INFO_X2, INFO_Y2, str, 0 );
  803. font_san.put_paragraph( INFO_X1+7, INFO_Y1+5, INFO_X2-7, INFO_Y2-5, str );
  804. button_cancel2.paint_text( INFO_X1, INFO_Y1+45, INFO_X2, INFO_Y1+70, "Cancel" );
  805. }
  806. }
  807. //----------- End of function Unit::disp_build -----------//
  808. //--------- Begin of function Unit::detect_build ---------//
  809. //
  810. void Unit::detect_build()
  811. {
  812. if( button_cancel2.detect() )
  813. {
  814. // ###### begin Gilbert 26/9 ######//
  815. se_ctrl.immediate_sound("TURN_OFF");
  816. // ###### end Gilbert 26/9 ######//
  817. power.command_id = 0;
  818. info.disp();
  819. }
  820. }
  821. //----------- End of function Unit::detect_build -----------//
  822. //--------- Begin of function Unit::disp_settle ---------//
  823. //
  824. // Display the info when the player has selected the type of
  825. // structure to build.
  826. //
  827. void Unit::disp_settle(int refreshFlag)
  828. {
  829. if( refreshFlag == INFO_REPAINT )
  830. {
  831. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+42 );
  832. font_san.put_paragraph( INFO_X1+7, INFO_Y1+5, INFO_X2-7, INFO_Y2-5,
  833. "Please select a location to settle." );
  834. button_cancel2.paint_text( INFO_X1, INFO_Y1+45, INFO_X2, INFO_Y1+70, "Cancel" );
  835. }
  836. }
  837. //----------- End of function Unit::disp_settle -----------//
  838. //--------- Begin of function Unit::detect_settle ---------//
  839. //
  840. void Unit::detect_settle()
  841. {
  842. if( button_cancel2.detect() )
  843. {
  844. // ###### begin Gilbert 26/9 ######//
  845. se_ctrl.immediate_sound("TURN_OFF");
  846. // ###### end Gilbert 26/9 ######//
  847. power.command_id = 0;
  848. info.disp();
  849. }
  850. }
  851. //----------- End of function Unit::detect_settle -----------//
  852. //--------- Begin of function Unit::disp_unit_info ---------//
  853. //
  854. // Display the skill information of the people in the town.
  855. //
  856. // <int> dispY1 - the top y coordination of the info area
  857. // <int> refreshFlag - refresh flag
  858. //
  859. void Unit::disp_unit_info(int dispY1, int refreshFlag)
  860. {
  861. #ifdef DEBUG
  862. if(debug2_enable_flag)
  863. {
  864. if(unit_res[unit_id]->unit_class == UNIT_CLASS_MONSTER)
  865. {
  866. int x=INFO_X1+4, y=dispY1+20;
  867. y+=20;
  868. font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
  869. font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
  870. font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
  871. font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);
  872. font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
  873. font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
  874. font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
  875. font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
  876. y-=20;
  877. font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
  878. font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
  879. font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
  880. font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
  881. y-=20;
  882. font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
  883. }
  884. }
  885. #endif
  886. //--------------------------------------------//
  887. if( !race_id ) // if it's not a human unit, don't display anything
  888. return;
  889. if( refreshFlag==INFO_REPAINT )
  890. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+87 );
  891. int x=INFO_X1+4, y=dispY1+4;
  892. String str;
  893. //--------- display loyalty ---------//
  894. if( rank_id != RANK_KING && (nation_recno || spy_recno) )
  895. {
  896. if( spy_recno && // only display spy loyalty instead of unit loyalty if this is a spy and this spy is ours
  897. true_nation_recno() == nation_array.player_recno )
  898. {
  899. font_san.field( x, y, "Loyalty", x+92, spy_array[spy_recno]->spy_loyalty, 1, INFO_X2-2, refreshFlag);
  900. }
  901. else if( nation_recno )
  902. {
  903. info.disp_loyalty( x, y, x+92, loyalty, target_loyalty, nation_recno, refreshFlag );
  904. }
  905. y+=16;
  906. }
  907. //--------- display combat level ----------//
  908. font_san.field( x, y, "Combat" , x+92, skill.combat_level, 1, INFO_X2-2, refreshFlag);
  909. y+=16;
  910. //-------- display skill level ---------//
  911. if( skill.skill_id )
  912. {
  913. if( refreshFlag == INFO_REPAINT )
  914. font_san.field( x, y, skill.skill_des(), x+92, skill.skill_level , 1, INFO_X2-2, refreshFlag);
  915. else
  916. font_san.field( x, y, skill.skill_des(), x+92, skill.skill_level , 1, INFO_X2-2, refreshFlag);
  917. y+=16;
  918. }
  919. //------- display spying skill if the unit is a spy -----//
  920. if( spy_recno && spy_array[spy_recno]->true_nation_recno == nation_array.player_recno ) // only spies of the player's nation can see the spy skill details
  921. {
  922. font_san.field( x, y, "Spying", x+92, spy_array[spy_recno]->spy_skill, 1, INFO_X2-2, refreshFlag);
  923. y+=16;
  924. }
  925. //--------- display debug info ---------//
  926. if( !is_civilian() && rank_id != RANK_KING )
  927. font_san.field( x, y, "Contribution", x+92, nation_contribution, 1, INFO_X2-2, refreshFlag);
  928. }
  929. //----------- End of function Unit::disp_unit_info -----------//
  930. //--------- Begin of function Unit::disp_unit_profile ---------//
  931. //
  932. // <int> dispY1 - the top y coordination of the info area
  933. // <int> refreshFlag
  934. //
  935. void Unit::disp_unit_profile(int dispY1, int refreshFlag)
  936. {
  937. //--------- set help parameters --------//
  938. int x=INFO_X1+4;
  939. if( mouse.in_area(x, dispY1+3, x+UNIT_LARGE_ICON_WIDTH-1, dispY1+UNIT_LARGE_ICON_HEIGHT+2) )
  940. help.set_unit_help( unit_id, rank_id, x, dispY1+3, x+UNIT_LARGE_ICON_WIDTH-1, dispY1+UNIT_LARGE_ICON_HEIGHT+2 );
  941. //-----------------------------------------//
  942. if( refreshFlag != INFO_REPAINT ) // only display in repaint mode
  943. return;
  944. //-----------------------------------------//
  945. char *str=NULL;
  946. if( race_id )
  947. {
  948. if( rank_id == RANK_KING )
  949. {
  950. str = "King";
  951. }
  952. else if( rank_id == RANK_GENERAL )
  953. {
  954. // ##### patch begin Gilbert 17/2 #####//
  955. if( unit_mode == UNIT_MODE_REBEL )
  956. str = "Rebel Leader";
  957. else
  958. str = "General";
  959. // ##### patch end Gilbert 17/2 #####//
  960. }
  961. else if( unit_mode == UNIT_MODE_DEFEND_TOWN )
  962. {
  963. str = "Defending Villager";
  964. }
  965. else if( unit_mode == UNIT_MODE_REBEL )
  966. {
  967. str = "Rebel";
  968. }
  969. else if( unit_res[unit_id]->unit_class == UNIT_CLASS_GOD )
  970. {
  971. str = "Greater Being";
  972. }
  973. else
  974. {
  975. if( should_show_info() )
  976. {
  977. switch( skill.skill_id )
  978. {
  979. case SKILL_LEADING:
  980. str = "Soldier";
  981. break;
  982. case SKILL_CONSTRUCTION:
  983. str = "Construction Worker";
  984. break;
  985. case SKILL_MINING:
  986. str = "Miner";
  987. break;
  988. case SKILL_MFT:
  989. str = "Worker";
  990. break;
  991. case SKILL_RESEARCH:
  992. str = "Scientist";
  993. break;
  994. case SKILL_SPYING:
  995. str = "Spy";
  996. break;
  997. default:
  998. str = "Peasant";
  999. break;
  1000. }
  1001. }
  1002. else //--- don't display too much info on enemy units ---//
  1003. {
  1004. if( skill.skill_id == SKILL_LEADING )
  1005. str = "Soldier";
  1006. else if( is_civilian() )
  1007. str = "Civilian";
  1008. }
  1009. }
  1010. }
  1011. //---------------- paint the panel --------------//
  1012. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+44);
  1013. vga_front.put_bitmap( x, dispY1+3, unit_res[unit_id]->get_large_icon_ptr(rank_id) );
  1014. //--------------------------------------//
  1015. x += UNIT_LARGE_ICON_WIDTH;
  1016. if( str )
  1017. {
  1018. font_san.center_put( x, dispY1+4, INFO_X2-2, dispY1+21, str );
  1019. font_san.center_put( x, dispY1+22, INFO_X2-2, dispY1+40, unit_name(0) ); // 0-without title
  1020. }
  1021. else
  1022. {
  1023. font_san.center_put( x, dispY1, INFO_X2-2, dispY1+44, unit_name() ); // non-human units
  1024. }
  1025. }
  1026. //----------- End of function Unit::disp_unit_profile -----------//
  1027. //--------- Begin of function Unit::detect_unit_profile ---------//
  1028. //
  1029. int Unit::detect_unit_profile()
  1030. {
  1031. if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1+54, INFO_X2, INFO_Y1+97 ) )
  1032. {
  1033. world.go_loc( next_x_loc(), next_y_loc() );
  1034. return 1;
  1035. }
  1036. return 0;
  1037. }
  1038. //----------- End of function Unit::detect_unit_profile -----------//
  1039. //--------- Begin of function Unit::disp_spy_menu ---------//
  1040. //
  1041. void Unit::disp_spy_menu(int dispY1, int refreshFlag)
  1042. {
  1043. err_when( !spy_recno );
  1044. static char lastCanChangeCloak;
  1045. static short lastSpyMenuHeight, lastNationCount;
  1046. char canChangeAnyCloak = can_spy_change_nation();
  1047. short spyMenuHeight = spy_menu_height();
  1048. //-- if the spy can always change back to its original color. So if it is currently cloaked as another nation, it should be able to revert back any time ---//
  1049. char canChangeOwnCloak = canChangeAnyCloak; // change back to its own cloak
  1050. if( true_nation_recno() != nation_recno )
  1051. canChangeOwnCloak = 1;
  1052. //---------------------------------------------//
  1053. if( canChangeOwnCloak != lastCanChangeCloak ||
  1054. spyMenuHeight != lastSpyMenuHeight ||
  1055. nation_array.nation_count != lastNationCount )
  1056. {
  1057. lastCanChangeCloak = canChangeOwnCloak;
  1058. lastSpyMenuHeight = spyMenuHeight;
  1059. lastNationCount = nation_array.nation_count;
  1060. info.disp();
  1061. return;
  1062. }
  1063. //---- if enemy nearby and cannot change cloak right now ---//
  1064. if( !canChangeOwnCloak )
  1065. {
  1066. if( refreshFlag==INFO_REPAINT )
  1067. {
  1068. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+26 );
  1069. font_san.center_put( INFO_X1, dispY1, INFO_X2-2, dispY1+26, "Enemies Nearby" );
  1070. }
  1071. return;
  1072. }
  1073. //---------------------------------------------//
  1074. if( refreshFlag==INFO_REPAINT )
  1075. {
  1076. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+spyMenuHeight-1 );
  1077. font_san.put( INFO_X1+6, dispY1+6, "Spy Cloak:" );
  1078. }
  1079. Nation* nationPtr = nation_array[true_nation_recno()];
  1080. int x=INFO_X1+80, y=dispY1+4, nationColor;
  1081. for( int i=1 ; i<=nation_array.size()+1 ; i++ )
  1082. {
  1083. if( canChangeAnyCloak )
  1084. {
  1085. if( i <= nation_array.size() ) // exclude independent town
  1086. {
  1087. if( nation_array.is_deleted(i) || !nationPtr->get_relation(i)->has_contact )
  1088. continue;
  1089. }
  1090. }
  1091. else if( canChangeOwnCloak )
  1092. {
  1093. if( i!=nation_recno && i!=true_nation_recno() ) // only display the current cloaked nation and its true nation
  1094. continue;
  1095. }
  1096. else
  1097. err_here();
  1098. //-----------------------------------//
  1099. if( i>nation_array.size() ) // independent
  1100. {
  1101. nationColor = nation_array.nation_color_array[0];
  1102. }
  1103. else
  1104. {
  1105. nationColor = nation_array[i]->nation_color;
  1106. }
  1107. vga_front.bar( x+2, y+2, x+SPY_CLOAK_WIDTH-3, y+16, nationColor );
  1108. if( i == nation_recno ||
  1109. (i==nation_array.size()+1 && nation_recno==0) )
  1110. {
  1111. vga_front.rect( x, y, x+SPY_CLOAK_WIDTH-1, y+18, 2, V_YELLOW );
  1112. }
  1113. else
  1114. vga_front.rect( x, y, x+SPY_CLOAK_WIDTH-1, y+18, 2, VGA_GRAY+8 );
  1115. x+=SPY_CLOAK_WIDTH+4;
  1116. if( x+SPY_CLOAK_WIDTH > INFO_X2 )
  1117. {
  1118. x = INFO_X1+80;
  1119. y += 22;
  1120. }
  1121. }
  1122. }
  1123. //----------- End of function Unit::disp_spy_menu -----------//
  1124. //--------- Begin of function Unit::spy_menu_height ---------//
  1125. //
  1126. // Return the height of the spy menu.
  1127. //
  1128. int Unit::spy_menu_height()
  1129. {
  1130. if( !can_spy_change_nation() )
  1131. return 27;
  1132. int cloakCount=1;
  1133. Nation* nationPtr = nation_array[true_nation_recno()];
  1134. for( int i=1 ; i<=nation_array.size() ; i++ )
  1135. {
  1136. if( nation_array.is_deleted(i) )
  1137. continue;
  1138. if( i==nation_recno || nationPtr->get_relation(i)->has_contact )
  1139. cloakCount++;
  1140. }
  1141. if( cloakCount > 4 )
  1142. return 47;
  1143. else
  1144. return 27;
  1145. }
  1146. //----------- End of function Unit::spy_menu_height -----------//
  1147. //--------- Begin of function Unit::detect_spy_menu ---------//
  1148. //
  1149. void Unit::detect_spy_menu(int dispY1)
  1150. {
  1151. Nation* nationPtr = nation_array[true_nation_recno()];
  1152. int x=INFO_X1+80, y=dispY1+4, nationRecno, changeFlag=0;
  1153. char canChangeAnyCloak = can_spy_change_nation();
  1154. char canChangeOwnCloak = canChangeAnyCloak; // change back to its own cloak
  1155. if( true_nation_recno() != nation_recno )
  1156. canChangeOwnCloak = 1;
  1157. if( !canChangeOwnCloak )
  1158. return;
  1159. int i;
  1160. for( i=1 ; i<=nation_array.size()+1 ; i++ )
  1161. {
  1162. if( i > nation_array.size() )
  1163. {
  1164. nationRecno = 0;
  1165. }
  1166. else
  1167. {
  1168. if( canChangeAnyCloak )
  1169. {
  1170. if( nation_array.is_deleted(i) || !nationPtr->get_relation(i)->has_contact )
  1171. continue;
  1172. }
  1173. else
  1174. {
  1175. if( i!=nation_recno && i!=true_nation_recno() ) // only display the current cloaked nation and its true nation
  1176. continue;
  1177. }
  1178. nationRecno = i;
  1179. }
  1180. //---------------------------//
  1181. if( mouse.single_click(x, y, x+SPY_CLOAK_WIDTH-1, y+22) )
  1182. {
  1183. changeFlag=1;
  1184. break;
  1185. }
  1186. x+=SPY_CLOAK_WIDTH+4;
  1187. if( x+SPY_CLOAK_WIDTH > INFO_X2 )
  1188. {
  1189. x = INFO_X1+80;
  1190. y += 22;
  1191. }
  1192. }
  1193. if( !changeFlag )
  1194. return;
  1195. //--- group changing the cloaks of all of your spies currently selected ---//
  1196. Unit* unitPtr;
  1197. for( i=unit_array.size() ; i>0 ; i-- )
  1198. {
  1199. if( unit_array.is_deleted(i) )
  1200. continue;
  1201. unitPtr = unit_array[i];
  1202. if( unitPtr->is_own_spy() && unitPtr->selected_flag )
  1203. unitPtr->spy_change_nation(nationRecno, COMMAND_PLAYER);
  1204. }
  1205. disp_spy_menu(dispY1, INFO_UPDATE);
  1206. }
  1207. //----------- End of function Unit::detect_spy_menu -----------//
  1208. //----------- Begin of function Unit::disp_hit_point -----------//
  1209. void Unit::disp_hit_point(int dispY1)
  1210. {
  1211. int hitPoints;
  1212. if( hit_points > (float)0 && hit_points < (float)1 )
  1213. hitPoints = 1; // display 1 for value between 0 and 1
  1214. else
  1215. hitPoints = (int) hit_points;
  1216. Vga::active_buf->indicator(0x0f, INFO_X1+30, dispY1+1, hit_points, max_hit_points, 0);
  1217. }
  1218. //----------- End of function Unit::disp_hit_point -----------//
  1219. #ifdef DEBUG
  1220. //----------- Begin of static function disp_debug_info -----------//
  1221. static void disp_debug_info(Unit* unitPtr, int dispY1, int refreshFlag)
  1222. {
  1223. if( unitPtr->spy_recno &&
  1224. unitPtr->true_nation_recno() == nation_array.player_recno )
  1225. {
  1226. return; // don't display debug info as it will overlap with the buttons
  1227. }
  1228. //---------------------------------------//
  1229. static char* action_mode_str_array[] =
  1230. {
  1231. "Stop",
  1232. "Attack unit",
  1233. "Attack firm",
  1234. "Attack town",
  1235. "Attack wall",
  1236. "Assign to firm",
  1237. "Assign to town",
  1238. "Assign to vehicle",
  1239. "Assign to ship",
  1240. "Ship to beach",
  1241. "Build firm",
  1242. "Settle",
  1243. "Burn",
  1244. "Die",
  1245. "Move",
  1246. "Go cast power",
  1247. "Auto defense attack target",
  1248. "Auto defense detect target",
  1249. "Auto defense back camp",
  1250. "Defend town attack target",
  1251. "Defend town detect target",
  1252. "Defend town back town",
  1253. "Monster defend attack target",
  1254. "Monster defend detect target",
  1255. "Monster defend back firm",
  1256. };
  1257. static char* unit_mode_str_array[] =
  1258. {
  1259. "",
  1260. "Oversee",
  1261. "Defend town",
  1262. "Construct",
  1263. "Rebel",
  1264. "Monster",
  1265. "On Ship",
  1266. "In Harbor",
  1267. };
  1268. static char* cur_action_str_array[] =
  1269. {
  1270. "Idle",
  1271. "Ready to move",
  1272. "Move",
  1273. "Wait",
  1274. "Attack",
  1275. "Turn",
  1276. "Ship extra move",
  1277. "Die",
  1278. };
  1279. if( refreshFlag == INFO_REPAINT )
  1280. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+65 );
  1281. int x=INFO_X1+3, y=dispY1+3;
  1282. font_san.disp( INFO_X2-80, y , unitPtr->sprite_recno, 1, INFO_X2-41 );
  1283. font_san.disp( INFO_X2-80, y+16, unitPtr->ai_action_id, 1, INFO_X2-41 );
  1284. font_san.disp( INFO_X2-80, y+32, unitPtr->home_camp_firm_recno, 1, INFO_X2-41 );
  1285. font_san.disp( INFO_X2-80, y+48, unitPtr->original_action_mode, 1, INFO_X2-41 );
  1286. font_san.disp( INFO_X2-40, y , unitPtr->leader_unit_recno, 1, INFO_X2-3 );
  1287. font_san.disp( x, y , action_mode_str_array[unitPtr->action_mode] , INFO_X2-81 );
  1288. font_san.disp( x, y+=16, action_mode_str_array[unitPtr->action_mode2], INFO_X2-81 );
  1289. font_san.disp( x, y+=16, unit_mode_str_array [unitPtr->unit_mode] , INFO_X2-81 );
  1290. font_san.disp( x, y+=16, cur_action_str_array [unitPtr->cur_action-1] , INFO_X2-81 );
  1291. }
  1292. //----------- End of static function disp_debug_info -----------//
  1293. #endif
  1294. // ---------- begin of static function disp_firm_button --------//
  1295. static void disp_firm_button(ButtonCustom *button, int)
  1296. {
  1297. // button->custom_para.ptr is the color remap table
  1298. // button->custom_para.value is (unit_id << 16) + (race_id << 8) + firm_id
  1299. int firmId = button->custom_para.value & 0xff;
  1300. int raceId = (button->custom_para.value >> 8) & 0xff;
  1301. // format is "F-d-n", d is firmId, n is build code for FIRM_BASE
  1302. String str;
  1303. str += "F-";
  1304. str += firmId;
  1305. if( firmId == FIRM_BASE )
  1306. {
  1307. str += "-";
  1308. str += raceId;
  1309. }
  1310. char *bitmap = image_button.get_ptr(str);
  1311. mouse.hide_area(button->x1, button->y1, button->x2, button->y2 );
  1312. vga_front.put_bitmap_trans_remap_decompress(button->x1, button->y1, bitmap, (char*) button->custom_para.ptr);
  1313. if( button->pushed_flag )
  1314. {
  1315. image_button.put_front(button->x1, button->y1, "F-DOWN", 1);
  1316. }
  1317. mouse.show_area();
  1318. }
  1319. // ---------- end of static function disp_firm_button --------//