OFIRMIF3.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  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 : OFIRMIF3.CPP
  21. //Description : Firm interface functions - part 3
  22. #include <OVGA.h>
  23. #include <OFONT.h>
  24. #include <OINFO.h>
  25. #include <OSYS.h>
  26. #include <OBUTT3D.h>
  27. #include <OMOUSE.h>
  28. #include <ONEWS.h>
  29. #include <OUNIT.h>
  30. #include <ORACERES.h>
  31. #include <ONATION.h>
  32. #include <OSPY.h>
  33. #include <OFIRM.h>
  34. #include <OREMOTE.h>
  35. //---------- Define constant ------------//
  36. #define BRIBE_OPTION_HEIGHT 19
  37. //-------- Define bribe amounts ---------//
  38. #define BRIBE_AMOUNT_COUNT 6
  39. #define MAX_BRIBE_AMOUNT 4000
  40. static short bribe_amount_array[] = { 500, 1000, 1500, 2000, 3000, 4000 };
  41. //-------- Define static vars ---------//
  42. static Button3D button_cancel;
  43. //------ declare static functions -------//
  44. static void disp_bribe_button(int y, int bribeAmount, int buttonUp);
  45. //--------- Begin of function Firm::disp_bribe_menu ---------//
  46. //
  47. void Firm::disp_bribe_menu(int refreshFlag)
  48. {
  49. //---- if the briber or bribe target is no longer valid -----//
  50. if( bribe_result == BRIBE_NONE )
  51. {
  52. if( !validate_cur_bribe() )
  53. {
  54. firm_menu_mode = FIRM_MENU_MAIN;
  55. bribe_result = BRIBE_NONE;
  56. info.disp();
  57. return;
  58. }
  59. }
  60. //------------------------------------//
  61. if( refreshFlag != INFO_REPAINT )
  62. return;
  63. //------ display the bribe menu ------//
  64. if( bribe_result == BRIBE_NONE )
  65. {
  66. int y=INFO_Y1;
  67. font_san.d3_put( INFO_X1, y, INFO_X2, y+19, "Bribe" );
  68. y+=22;
  69. disp_bribe_unit( y );
  70. y+=49;
  71. for( int i=0 ; i<BRIBE_AMOUNT_COUNT ; i++ )
  72. {
  73. disp_bribe_button( y, bribe_amount_array[i], 1);
  74. err_when( bribe_amount_array[i] > MAX_BRIBE_AMOUNT );
  75. y += BRIBE_OPTION_HEIGHT+2;
  76. }
  77. disp_bribe_button( y, 0, 1);
  78. }
  79. //------ display the bribe result -----//
  80. else
  81. {
  82. int x=INFO_X1+4, y=INFO_Y1+4, y2=y+font_san.height()-1;
  83. if( bribe_result == BRIBE_SUCCEED )
  84. {
  85. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+24 );
  86. font_san.center_put( INFO_X1, y, INFO_X2, y2, "Bribing Succeeded." );
  87. }
  88. else
  89. {
  90. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
  91. font_san.center_put( INFO_X1, y , INFO_X2, y2, "Bribing Failed." );
  92. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
  93. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
  94. }
  95. y+=26;
  96. button_cancel.paint( INFO_X1, y, 'A', "CONTINUE" );
  97. }
  98. }
  99. //----------- End of function Firm::disp_bribe_menu -----------//
  100. //--------- Begin of function Firm::detect_bribe_menu ---------//
  101. //
  102. void Firm::detect_bribe_menu()
  103. {
  104. //----- if it is display the bribe result right now -----//
  105. if( bribe_result != BRIBE_NONE )
  106. {
  107. if( button_cancel.detect() )
  108. {
  109. firm_menu_mode = FIRM_MENU_MAIN;
  110. bribe_result = BRIBE_NONE;
  111. info.disp();
  112. }
  113. return;
  114. }
  115. //-------------------------------------------//
  116. int i, y=INFO_Y1+22+49;
  117. for( i=0 ; i<BRIBE_AMOUNT_COUNT ; i++ )
  118. {
  119. if( mouse.single_click(INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1) )
  120. {
  121. disp_bribe_button( y, bribe_amount_array[i], 0); // 0-display pressed button
  122. while( mouse.left_press )
  123. {
  124. sys.yield();
  125. mouse.get_event();
  126. }
  127. //--------- bribe now ---------//
  128. // ####### begin Gilbert 13/10 #######//
  129. if( !remote.is_enable() )
  130. {
  131. spy_bribe(bribe_amount_array[i], action_spy_recno, selected_worker_id);
  132. action_spy_recno = 0;
  133. }
  134. else
  135. {
  136. // packet structure <firm recno> <spy recno> <bribe target : worker (0=overseer)> <amount>
  137. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_BRIBE, 4*sizeof(short));
  138. *shortPtr = firm_recno;
  139. shortPtr[1] = action_spy_recno;
  140. shortPtr[2] = selected_worker_id;
  141. shortPtr[3] = bribe_amount_array[i];
  142. }
  143. // ####### end Gilbert 13/10 #######//
  144. }
  145. y += BRIBE_OPTION_HEIGHT+2;
  146. }
  147. //------ detect the cancel button --------//
  148. if( mouse.single_click(INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1) )
  149. {
  150. disp_bribe_button( y, 0, 0); // 0-display pressed button
  151. while( mouse.left_press )
  152. {
  153. sys.yield();
  154. mouse.get_event();
  155. }
  156. firm_menu_mode = FIRM_MENU_MAIN;
  157. info.disp();
  158. }
  159. }
  160. //----------- End of function Firm::detect_bribe_menu -----------//
  161. //--------- Begin of function Firm::validate_cur_bribe ---------//
  162. //
  163. // Whether the current bribe action is still valid.
  164. //
  165. int Firm::validate_cur_bribe()
  166. {
  167. if( spy_array.is_deleted(action_spy_recno) ||
  168. spy_array[action_spy_recno]->true_nation_recno != nation_array.player_recno )
  169. {
  170. return 0;
  171. }
  172. return can_spy_bribe( selected_worker_id, spy_array[action_spy_recno]->true_nation_recno );
  173. }
  174. //----------- End of function Firm::validate_cur_bribe -----------//
  175. //-------- Begin of static function disp_bribe_button --------//
  176. //
  177. static void disp_bribe_button(int y, int bribeAmount, int buttonUp)
  178. {
  179. if( buttonUp )
  180. vga.d3_panel_up( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1 );
  181. else
  182. vga.d3_panel_down( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1 );
  183. //--------- if display cancel button ---------//
  184. if( bribeAmount==0 )
  185. font_san.center_put( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1, "Cancel" );
  186. else
  187. {
  188. String str;
  189. #ifdef GERMAN
  190. str = m.format(bribeAmount,2);
  191. str += " anbieten";
  192. #else
  193. str = translate.process("Offer ");
  194. str += m.format(bribeAmount,2);
  195. #endif
  196. font_san.center_put( INFO_X1, y, INFO_X2, y+BRIBE_OPTION_HEIGHT-1, str );
  197. }
  198. }
  199. //--------- End of static function disp_bribe_button ---------//
  200. //--------- Begin of function Firm::can_spy_bribe ---------//
  201. //
  202. // <int> bribeWorkerId - worker id. in this firm to bribe
  203. // 0 - if bribe an overseer.
  204. //
  205. // <int> briberNationRecno - the nation recno of the briber.
  206. //
  207. int Firm::can_spy_bribe(int bribeWorkerId, int briberNationRecno)
  208. {
  209. int canBribe=0;
  210. int spyRecno;
  211. err_when( bribeWorkerId < 0 || bribeWorkerId > MAX_WORKER );
  212. if( bribeWorkerId ) // the overseer is selected
  213. spyRecno = worker_array[bribeWorkerId-1].spy_recno;
  214. else
  215. spyRecno = unit_array[overseer_recno]->spy_recno;
  216. if( spyRecno )
  217. {
  218. canBribe = spy_array[spyRecno]->true_nation_recno != briberNationRecno; // only when the unit is not yet a spy of the player. Still display the bribe button when it's a spy of another nation
  219. }
  220. else
  221. {
  222. if( bribeWorkerId )
  223. canBribe = worker_array[bribeWorkerId-1].race_id>0; // cannot bribe if it's a weapon
  224. else
  225. canBribe = unit_array[overseer_recno]->rank_id != RANK_KING; // cannot bribe a king
  226. }
  227. return canBribe;
  228. }
  229. //----------- End of function Firm::can_spy_bribe -----------//
  230. //--------- Begin of function Firm::spy_bribe ---------//
  231. //
  232. // The money the spy offers to bribe the unit.
  233. //
  234. // <int> bribeAmount - the amount offered
  235. // <short> birberSpyRecno - spy recno of the briber
  236. // <short> workerId - if 0, then bribe the overseer,
  237. // if >0, then bribe a worker.
  238. //
  239. // return: <int> >0 - bribing succeeded, return the spy recno of the bribed unit (as it has been turned into a spy)
  240. // 0 - bribing failed
  241. //
  242. int Firm::spy_bribe(int bribeAmount, short briberSpyRecno, short workerId)
  243. {
  244. if( !can_spy_bribe(workerId, spy_array[briberSpyRecno]->true_nation_recno) ) // this can happen in multiplayer as there is a one frame delay when the message is sent and when it is processed
  245. return 0;
  246. //---------------------------------------//
  247. int succeedChance = spy_bribe_succeed_chance(bribeAmount, briberSpyRecno, workerId);
  248. Spy* spyPtr = spy_array[briberSpyRecno];
  249. nation_array[spyPtr->true_nation_recno]->add_expense( EXPENSE_BRIBE, (float) bribeAmount, 0 );
  250. //------ if the bribe succeeds ------//
  251. if( succeedChance > 0 && m.random(100) < succeedChance )
  252. {
  253. int spyRecno = spy_array.add_spy(); // add a new Spy record
  254. Spy* newSpy = spy_array[spyRecno];
  255. newSpy->spy_skill = 10;
  256. newSpy->action_mode = SPY_IDLE;
  257. newSpy->spy_loyalty = min( 100, max(30,succeedChance) ); // within the 30-100 range
  258. newSpy->true_nation_recno = spyPtr->true_nation_recno;
  259. newSpy->cloaked_nation_recno = spyPtr->cloaked_nation_recno;
  260. if( workerId )
  261. {
  262. Worker* workerPtr = worker_array+workerId-1;
  263. workerPtr->spy_recno = spyRecno;
  264. newSpy->race_id = workerPtr->race_id;
  265. newSpy->name_id = workerPtr->name_id;
  266. err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE );
  267. if( !newSpy->name_id ) // if this worker does not have a name, give him one now as a spy must reserve a name (see below on use_name_id() for reasons)
  268. newSpy->name_id = race_res[newSpy->race_id]->get_new_name_id();
  269. }
  270. else if( overseer_recno )
  271. {
  272. Unit* unitPtr = unit_array[overseer_recno];
  273. unitPtr->spy_recno = spyRecno;
  274. newSpy->race_id = unitPtr->race_id;
  275. newSpy->name_id = unitPtr->name_id;
  276. err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE );
  277. }
  278. else
  279. err_here();
  280. newSpy->set_place( SPY_FIRM, firm_recno );
  281. //-- Spy always registers its name twice as his name will be freed up in deinit(). Keep an additional right because when a spy is assigned to a town, the normal program will free up the name id., so we have to keep an additional copy
  282. race_res[newSpy->race_id]->use_name_id(newSpy->name_id);
  283. bribe_result = BRIBE_SUCCEED;
  284. if( firm_recno == firm_array.selected_recno )
  285. info.disp();
  286. return newSpy->spy_recno;
  287. }
  288. else //------- if the bribe fails --------//
  289. {
  290. spyPtr->get_killed(0); // the spy gets killed when the action failed.
  291. // 0 - don't display new message for the spy being killed, so we already display the msg on the interface
  292. bribe_result = BRIBE_FAIL;
  293. if( firm_recno == firm_array.selected_recno )
  294. info.disp();
  295. return 0;
  296. }
  297. }
  298. //----------- End of function Firm::spy_bribe -----------//
  299. //--------- Begin of function Firm::spy_birbe_succeed_chance ---------//
  300. //
  301. // The money the spy offers to bribe the unit.
  302. //
  303. // <int> bribeAmount - the amount offered
  304. // <short> birberSpyRecno - spy recno of the briber
  305. // <short> workerId - if 0, then bribe the overseer,
  306. // if >0, then bribe a worker.
  307. //
  308. // return: <int> 1 - bribing succeeded
  309. // 0 - bribing failed
  310. //
  311. int Firm::spy_bribe_succeed_chance(int bribeAmount, short briberSpyRecno, short workerId)
  312. {
  313. Spy* spyPtr = spy_array[briberSpyRecno];
  314. err_when( spyPtr->spy_place != SPY_FIRM );
  315. err_when( spyPtr->spy_place_para != firm_recno );
  316. //---- if the bribing target is a worker ----//
  317. int unitLoyalty, unitRaceId, targetSpyRecno, unitCommandPower;
  318. if( workerId )
  319. {
  320. Worker* workerPtr = worker_array+workerId-1;
  321. unitLoyalty = workerPtr->loyalty();
  322. unitRaceId = workerPtr->race_id;
  323. unitCommandPower = 0;
  324. targetSpyRecno = workerPtr->spy_recno;
  325. }
  326. else if( overseer_recno )
  327. {
  328. Unit* unitPtr = unit_array[overseer_recno];
  329. unitLoyalty = unitPtr->loyalty;
  330. unitRaceId = unitPtr->race_id;
  331. unitCommandPower = unitPtr->commander_power();
  332. targetSpyRecno = unitPtr->spy_recno;
  333. }
  334. else
  335. err_here();
  336. err_when( unitRaceId < 1 || unitRaceId > MAX_RACE );
  337. //---- determine whether the bribe will be successful ----//
  338. int succeedChance;
  339. if( targetSpyRecno ) // if the bribe target is also a spy
  340. {
  341. err_when( spy_array[targetSpyRecno]->true_nation_recno == spyPtr->true_nation_recno ); // the player shouldn't be able to bribe units of his own
  342. succeedChance = 0;
  343. }
  344. else
  345. {
  346. succeedChance = spyPtr->spy_skill - unitLoyalty - unitCommandPower
  347. + (int) nation_array[spyPtr->true_nation_recno]->reputation
  348. + 200 * bribeAmount / MAX_BRIBE_AMOUNT;
  349. //-- the chance is higher if the spy or the spy's king is racially homongenous to the bribe target,
  350. int spyKingRaceId = nation_array[ spyPtr->true_nation_recno ]->race_id;
  351. succeedChance += race_res.is_same_race(spyPtr->race_id, unitRaceId) * 10 +
  352. race_res.is_same_race(spyKingRaceId, unitRaceId) * 10;
  353. if( unitLoyalty > 60 ) // harder for bribe units with over 60 loyalty
  354. succeedChance -= (unitLoyalty-60);
  355. if( unitLoyalty > 70 ) // harder for bribe units with over 70 loyalty
  356. succeedChance -= (unitLoyalty-70);
  357. if( unitLoyalty > 80 ) // harder for bribe units with over 80 loyalty
  358. succeedChance -= (unitLoyalty-80);
  359. if( unitLoyalty > 90 ) // harder for bribe units with over 90 loyalty
  360. succeedChance -= (unitLoyalty-90);
  361. if( unitLoyalty == 100 )
  362. succeedChance = 0;
  363. }
  364. return succeedChance;
  365. }
  366. //----------- End of function Firm::spy_birbe_succeed_chance -----------//
  367. //--------- Begin of function Firm::disp_bribe_unit ---------//
  368. //
  369. void Firm::disp_bribe_unit(int dispY1)
  370. {
  371. //---------------- paint the panel -----------------//
  372. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+46);
  373. //------- get the info of the bribe target ---------//
  374. // ####### begin Gilbert 8/8 ########//
  375. int raceId, unitLoyalty, unitId, rankId;
  376. char* unitName;
  377. if( selected_worker_id )
  378. {
  379. Worker* workerPtr = worker_array+selected_worker_id-1;
  380. raceId = workerPtr->race_id;
  381. unitId = workerPtr->unit_id;
  382. unitLoyalty = workerPtr->loyalty();
  383. unitName = race_res[raceId]->get_name(workerPtr->name_id);
  384. rankId = workerPtr->rank_id;
  385. }
  386. else if( overseer_recno )
  387. {
  388. Unit* unitPtr = unit_array[overseer_recno];
  389. raceId = unitPtr->race_id;
  390. unitId = unitPtr->unit_id;
  391. unitLoyalty = unitPtr->loyalty;
  392. unitName = unitPtr->unit_name();
  393. rankId = unitPtr->rank_id;
  394. }
  395. else
  396. err_here();
  397. //--------- display info of the bribe target ---------//
  398. int x=INFO_X1+6, y=dispY1+4;
  399. vga_front.put_bitmap(x, y, unit_res[unitId]->get_large_icon_ptr(rankId) );
  400. font_san.put( x+UNIT_LARGE_ICON_WIDTH+6, y+4, unitName );
  401. //------- display skill and productivity ---------//
  402. String str;
  403. str = translate.process("Loyalty: ");
  404. str += unitLoyalty;
  405. font_san.disp( x+UNIT_LARGE_ICON_WIDTH+6, y+20, str, INFO_X2-10 );
  406. }
  407. //----------- End of function Firm::disp_bribe_unit -----------//
  408. //--------- Begin of function Firm::disp_assassinate_result ---------//
  409. //
  410. void Firm::disp_assassinate_result(int refreshFlag)
  411. {
  412. if( refreshFlag != INFO_REPAINT )
  413. return;
  414. int x=INFO_X1+4, y=INFO_Y1+4, y2=y+font_san.height()-1;
  415. if( assassinate_result == ASSASSINATE_SUCCEED_AT_LARGE )
  416. {
  417. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+43 );
  418. font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
  419. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Escaped." );
  420. }
  421. else if( assassinate_result == ASSASSINATE_SUCCEED_KILLED )
  422. {
  423. #ifdef GERMAN
  424. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+80 );
  425. font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
  426. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy" ); // German text is longer
  427. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Was Caught" );
  428. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
  429. #else
  430. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
  431. font_san.center_put( INFO_X1, y, INFO_X2, y2, "Assassination Succeeded." );
  432. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
  433. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
  434. #endif
  435. }
  436. else
  437. {
  438. #ifdef GERMAN
  439. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+80 );
  440. font_san.center_put( INFO_X1, y , INFO_X2, y2, "Assassination Failed." );
  441. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy" );
  442. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Was Caught" );
  443. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
  444. #else
  445. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+62 );
  446. font_san.center_put( INFO_X1, y , INFO_X2, y2, "Assassination Failed." );
  447. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "Your Spy Was Caught" );
  448. font_san.center_put( INFO_X1, y+=18, INFO_X2, y2+=18, "And Executed." );
  449. #endif
  450. }
  451. y+=26;
  452. button_cancel.paint( INFO_X1, y, 'A', "CONTINUE" );
  453. }
  454. //----------- End of function Firm::disp_assassinate_result -----------//
  455. //--------- Begin of function Firm::detect_assassinate_result ---------//
  456. //
  457. void Firm::detect_assassinate_result()
  458. {
  459. //----- if it is display the bribe result right now -----//
  460. if( button_cancel.detect() )
  461. {
  462. firm_menu_mode = FIRM_MENU_MAIN;
  463. assassinate_result = 0;
  464. info.disp();
  465. }
  466. }
  467. //----------- End of function Firm::detect_assassinate_result -----------//