OF_BASE.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  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 : OF_BASE.CPP
  21. //Description : Firm Base
  22. #include <OINFO.h>
  23. #include <OVGA.h>
  24. #include <ODATE.h>
  25. #include <OMOUSE.h>
  26. #include <OIMGRES.h>
  27. #include <OHELP.h>
  28. #include <OSTR.h>
  29. #include <OFONT.h>
  30. #include <OCONFIG.h>
  31. #include <OUNIT.h>
  32. #include <OSPY.h>
  33. #include <OGAME.h>
  34. #include <OBUTT3D.h>
  35. #include <ONATION.h>
  36. #include <ORACERES.h>
  37. #include <OWALLRES.h>
  38. #include <OGODRES.h>
  39. #include <OPOWER.h>
  40. #include <OTOWN.h>
  41. #include <OWORLD.h>
  42. #include <OF_BASE.h>
  43. #include <OREMOTE.h>
  44. #include <OSERES.h>
  45. #include <OSE.h>
  46. //----------- Define static vars -------------//
  47. static Button3D button_invoke, button_reward;
  48. //--------- Begin of function FirmBase::FirmBase ---------//
  49. //
  50. FirmBase::FirmBase()
  51. {
  52. firm_skill_id = SKILL_PRAYING;
  53. }
  54. //----------- End of function FirmBase::FirmBase -----------//
  55. //--------- Begin of function FirmBase::~FirmBase ---------//
  56. //
  57. FirmBase::~FirmBase()
  58. {
  59. err_when( race_id<1 || race_id>MAX_RACE );
  60. nation_array[nation_recno]->base_count_array[race_id-1]--;
  61. err_when( nation_array[nation_recno]->base_count_array[race_id-1] < 0 );
  62. }
  63. //----------- End of function FirmBase::~FirmBase -----------//
  64. //--------- Begin of function FirmBase::init_derived ---------//
  65. //
  66. void FirmBase::init_derived()
  67. {
  68. pray_points = (float) 0;
  69. //------ increase NationBase::base_count_array[] -----//
  70. err_when( race_id<1 || race_id>MAX_RACE );
  71. nation_array[nation_recno]->base_count_array[race_id-1]++;
  72. //---------- set the god id. ----------//
  73. god_id = 0 ;
  74. god_unit_recno = 0;
  75. for( int i=1 ; i<=god_res.god_count ; i++ )
  76. {
  77. if( god_res[i]->race_id == race_id &&
  78. god_res[i]->is_nation_know(nation_recno) )
  79. {
  80. god_id = i;
  81. break;
  82. }
  83. }
  84. err_when( god_id==0 );
  85. }
  86. //----------- End of function FirmBase::init_derived -----------//
  87. //--------- Begin of function FirmBase::assign_unit ---------//
  88. //
  89. void FirmBase::assign_unit(int unitRecno)
  90. {
  91. Unit* unitPtr = unit_array[unitRecno];
  92. //### begin alex 18/9 ###//
  93. /*//------ only assign units of the right race ------//
  94. if( unitPtr->race_id != race_id )
  95. return;*/
  96. //#### end alex 18/9 ####//
  97. //------- if this is a construction worker -------//
  98. if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION )
  99. {
  100. set_builder(unitRecno);
  101. return;
  102. }
  103. //### begin alex 18/9 ###//
  104. //------ only assign units of the right race ------//
  105. if( unitPtr->race_id != race_id )
  106. return;
  107. //#### end alex 18/9 ####//
  108. //-------- assign the unit ----------//
  109. int rankId = unit_array[unitRecno]->rank_id;
  110. if( rankId == RANK_GENERAL || rankId==RANK_KING )
  111. {
  112. assign_overseer(unitRecno);
  113. }
  114. else
  115. {
  116. assign_worker(unitRecno);
  117. }
  118. }
  119. //----------- End of function FirmBase::assign_unit -----------//
  120. //--------- Begin of function FirmBase::assign_overseer ---------//
  121. //
  122. void FirmBase::assign_overseer(int overseerRecno)
  123. {
  124. //---- reset the team member count of the general ----//
  125. if( overseerRecno )
  126. {
  127. Unit* unitPtr = unit_array[overseerRecno];
  128. err_when( !unitPtr->race_id );
  129. err_when( unitPtr->rank_id != RANK_GENERAL && unitPtr->rank_id != RANK_KING );
  130. err_when( !unitPtr->team_info );
  131. unitPtr->team_info->member_count = 0;
  132. }
  133. //----- assign the overseer now -------//
  134. Firm::assign_overseer(overseerRecno);
  135. }
  136. //----------- End of function FirmBase::assign_overseer -----------//
  137. //--------- Begin of function FirmBase::put_info ---------//
  138. //
  139. void FirmBase::put_info(int refreshFlag)
  140. {
  141. disp_basic_info(INFO_Y1, refreshFlag);
  142. if( !should_show_info() )
  143. return;
  144. disp_base_info(INFO_Y1+54, refreshFlag);
  145. disp_worker_list(INFO_Y1+104, refreshFlag);
  146. disp_worker_info(INFO_Y1+168, refreshFlag);
  147. disp_god_info(INFO_Y1+226, refreshFlag);
  148. //------ display button -------//
  149. int x, y=INFO_Y1+279;
  150. if( own_firm() )
  151. {
  152. if( refreshFlag==INFO_REPAINT )
  153. {
  154. button_invoke.paint( INFO_X1, y, 'A', "INVOKE" );
  155. button_reward.paint( INFO_X1+BUTTON_ACTION_WIDTH, y, 'A', "REWARDSP" );
  156. }
  157. if( can_invoke() )
  158. button_invoke.enable();
  159. else
  160. button_invoke.disable();
  161. if( nation_array[nation_recno]->cash >= REWARD_COST &&
  162. ( (overseer_recno && unit_array[overseer_recno]->rank_id != RANK_KING)
  163. || selected_worker_id ) )
  164. {
  165. button_reward.enable();
  166. }
  167. else
  168. {
  169. button_reward.disable();
  170. }
  171. x=INFO_X1+BUTTON_ACTION_WIDTH*2;
  172. }
  173. else
  174. x=INFO_X1;
  175. disp_spy_button(x, y, refreshFlag);
  176. }
  177. //----------- End of function FirmBase::put_info -----------//
  178. //--------- Begin of function FirmBase::detect_info ---------//
  179. //
  180. void FirmBase::detect_info()
  181. {
  182. if( detect_basic_info() )
  183. return;
  184. if( !should_show_info() )
  185. return;
  186. //------ detect the overseer button -----//
  187. int rc = mouse.single_click(INFO_X1+6, INFO_Y1+58,
  188. INFO_X1+5+UNIT_LARGE_ICON_WIDTH, INFO_Y1+57+UNIT_LARGE_ICON_HEIGHT, 2 );
  189. if( rc==1 ) // display this overseer's info
  190. {
  191. selected_worker_id = 0;
  192. disp_base_info(INFO_Y1+54, INFO_UPDATE);
  193. disp_worker_list(INFO_Y1+104, INFO_UPDATE);
  194. disp_worker_info(INFO_Y1+168, INFO_UPDATE);
  195. }
  196. //--------- detect soldier info ---------//
  197. if( detect_worker_list() )
  198. {
  199. disp_base_info(INFO_Y1+54, INFO_UPDATE);
  200. disp_worker_list(INFO_Y1+104, INFO_UPDATE);
  201. disp_worker_info(INFO_Y1+168, INFO_UPDATE);
  202. }
  203. //---------- detect spy button ----------//
  204. detect_spy_button();
  205. if( !own_firm() )
  206. return;
  207. //------ detect the overseer button -----//
  208. if( rc==2 )
  209. {
  210. if(remote.is_enable())
  211. {
  212. // packet structure : <firm recno>
  213. short *shortPtr=(short *)remote.new_send_queue_msg(MSG_FIRM_MOBL_OVERSEER, sizeof(short));
  214. shortPtr[0] = firm_recno;
  215. }
  216. else
  217. {
  218. assign_overseer(0); // the overseer quits the camp
  219. }
  220. }
  221. //----------- detect invoke -----------//
  222. if( button_invoke.detect() )
  223. {
  224. if(remote.is_enable())
  225. {
  226. // ##### begin Gilbert 14/10 #######//
  227. // packet structure : <firm recno>
  228. short *shortPtr=(short *)remote.new_send_queue_msg(MSG_F_BASE_INVOKE_GOD, sizeof(short));
  229. shortPtr[0] = firm_recno;
  230. // ##### end Gilbert 14/10 #######//
  231. }
  232. else
  233. {
  234. invoke_god();
  235. }
  236. }
  237. //----------- detect reward -----------//
  238. if( button_reward.detect() )
  239. {
  240. reward(selected_worker_id, COMMAND_PLAYER);
  241. // ##### begin Gilbert 26/9 ########//
  242. se_ctrl.immediate_sound("TURN_ON");
  243. // ##### end Gilbert 26/9 ########//
  244. }
  245. }
  246. //----------- End of function FirmBase::detect_info -----------//
  247. //--------- Begin of function FirmBase::disp_base_info ---------//
  248. //
  249. void FirmBase::disp_base_info(int dispY1, int refreshFlag)
  250. {
  251. //---------------- paint the panel --------------//
  252. if( refreshFlag == INFO_REPAINT )
  253. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+46);
  254. if( !overseer_recno )
  255. return;
  256. //------------ display overseer info -------------//
  257. Unit* overseerUnit = unit_array[overseer_recno];
  258. int x=INFO_X1+6, y=dispY1+4, x1=x+UNIT_LARGE_ICON_WIDTH+8;
  259. if( selected_worker_id == 0 )
  260. {
  261. vga_front.rect( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+1, 2, V_YELLOW );
  262. }
  263. else
  264. {
  265. vga.blt_buf( x-2, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y-1, 0 );
  266. vga.blt_buf( x-2, y+UNIT_LARGE_ICON_HEIGHT+1, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
  267. vga.blt_buf( x-2, y-2, x-1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
  268. vga.blt_buf( x+UNIT_LARGE_ICON_WIDTH, y-2, x+UNIT_LARGE_ICON_WIDTH+1, y+UNIT_LARGE_ICON_HEIGHT+2, 0 );
  269. }
  270. //-------------------------------------//
  271. if( refreshFlag == INFO_REPAINT )
  272. {
  273. vga_front.put_bitmap(x, y, unit_res[overseerUnit->unit_id]->get_large_icon_ptr(overseerUnit->rank_id) );
  274. }
  275. //-------- set help parameters --------//
  276. if( mouse.in_area(x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3) )
  277. help.set_unit_help( overseerUnit->unit_id, overseerUnit->rank_id, x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3);
  278. //-------------------------------------//
  279. if( overseerUnit->rank_id == RANK_KING )
  280. {
  281. if( refreshFlag == INFO_REPAINT )
  282. font_san.put( x1, y, "King" );
  283. y+=14;
  284. }
  285. if( refreshFlag == INFO_REPAINT )
  286. font_san.put( x1, y, overseerUnit->unit_name(0), 0, INFO_X2-2 ); // 0-ask unit_name() not to return the title of the unit
  287. y+=14;
  288. //------- display leadership -------//
  289. String str;
  290. str = translate.process("Leadership");
  291. str += ": ";
  292. str += overseerUnit->skill.get_skill(SKILL_LEADING);
  293. font_san.disp( x1, y, str, INFO_X2-10 );
  294. y+=14;
  295. //--------- display loyalty ----------//
  296. if( overseerUnit->rank_id != RANK_KING )
  297. {
  298. x1 = font_san.put( x1, y, "Loyalty:" );
  299. int x2 = info.disp_loyalty( x1, y-1, x1, overseerUnit->loyalty, overseerUnit->target_loyalty, nation_recno, refreshFlag );
  300. if( overseerUnit->spy_recno )
  301. {
  302. //------ if this is the player's spy -------//
  303. if( overseerUnit->true_nation_recno() == nation_array.player_recno )
  304. {
  305. vga_front.put_bitmap( x2+5, y+1, image_icon.get_ptr("U_SPY") );
  306. x2 += 15;
  307. }
  308. }
  309. vga.blt_buf( x2, y-1, INFO_X2-2, dispY1+44, 0 );
  310. }
  311. }
  312. //----------- End of function FirmBase::disp_base_info -----------//
  313. //--------- Begin of function FirmBase::next_day ---------//
  314. //
  315. void FirmBase::next_day()
  316. {
  317. //----- call next_day() of the base class -----//
  318. Firm::next_day();
  319. //--------------------------------------//
  320. calc_productivity();
  321. //--------------------------------------//
  322. if( info.game_date%15 == firm_recno%15 ) // once a week
  323. {
  324. train_unit();
  325. recover_hit_point();
  326. }
  327. //------- increase pray points --------//
  328. if( overseer_recno && pray_points < MAX_PRAY_POINTS )
  329. {
  330. // ###### patch begin Gilbert 21/1 #######//
  331. if( config.fast_build )
  332. pray_points += productivity/10;
  333. else
  334. pray_points += productivity/100;
  335. // ###### patch end Gilbert 21/1 #######//
  336. if( pray_points > MAX_PRAY_POINTS )
  337. pray_points = (float) MAX_PRAY_POINTS;
  338. }
  339. //------ validate god_unit_recno ------//
  340. if( god_unit_recno )
  341. {
  342. if( unit_array.is_deleted(god_unit_recno) )
  343. god_unit_recno = 0;
  344. #ifdef DEBUG
  345. if( god_unit_recno )
  346. {
  347. err_when( !unit_array[god_unit_recno]->is_visible() );
  348. err_when( unit_array[god_unit_recno]->nation_recno != nation_recno );
  349. }
  350. #endif
  351. }
  352. }
  353. //----------- End of function FirmBase::next_day -----------//
  354. //------- Begin of function FirmBase::change_nation ---------//
  355. //
  356. void FirmBase::change_nation(int newNationRecno)
  357. {
  358. //--- update the UnitInfo vars of the workers in this firm ---//
  359. for( int i=0 ; i<worker_count ; i++ )
  360. unit_res[ worker_array[i].unit_id ]->unit_change_nation(newNationRecno, nation_recno, worker_array[i].rank_id );
  361. //------ update base_count_array[] --------//
  362. err_when( race_id<1 || race_id>MAX_RACE );
  363. nation_array[nation_recno]->base_count_array[race_id-1]--;
  364. err_when( nation_array[nation_recno]->base_count_array[race_id-1] < 0 );
  365. nation_array[newNationRecno]->base_count_array[race_id-1]++;
  366. //----- change the nation recno of the god invoked by the base if there is any ----//
  367. if( god_unit_recno && !unit_array.is_deleted(god_unit_recno) )
  368. unit_array[god_unit_recno]->change_nation(newNationRecno);
  369. //-------- change the nation of this firm now ----------//
  370. Firm::change_nation(newNationRecno);
  371. }
  372. //-------- End of function FirmBase::change_nation ---------//
  373. //------- Begin of function FirmBase::train_unit -------//
  374. //
  375. // Increase the praying skills of the prayers.
  376. //
  377. void FirmBase::train_unit()
  378. {
  379. if( !overseer_recno )
  380. return;
  381. Unit* overseerUnit = unit_array[overseer_recno];
  382. int overseerSkill = overseerUnit->skill.skill_level;
  383. int incValue;
  384. //------- increase the commander's leadership ---------//
  385. if( worker_count > 0 && overseerUnit->skill.skill_level < 100 )
  386. {
  387. //-- the more soldiers this commander has, the higher the leadership will increase ---//
  388. incValue = 3 * worker_count
  389. * (int) overseerUnit->hit_points / overseerUnit->max_hit_points
  390. * (100+overseerUnit->skill.skill_potential*2) / 100;
  391. overseerUnit->skill.skill_level_minor += incValue;
  392. if( overseerUnit->skill.skill_level_minor >= 100 )
  393. {
  394. overseerUnit->skill.skill_level_minor -= 100;
  395. overseerUnit->skill.skill_level++;
  396. }
  397. }
  398. //------- increase the prayer's skill level ------//
  399. int levelMinor;
  400. Worker* workerPtr = worker_array;
  401. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  402. {
  403. //------- increase prayer skill -----------//
  404. if( workerPtr->skill_level < overseerSkill )
  405. {
  406. incValue = max(20, overseerSkill-workerPtr->skill_level)
  407. * workerPtr->hit_points / workerPtr->max_hit_points()
  408. * (100+workerPtr->skill_potential*2) / 100;
  409. levelMinor = workerPtr->skill_level_minor + incValue; // with random factors, resulting in 75% to 125% of the original
  410. while( levelMinor >= 100 )
  411. {
  412. levelMinor -= 100;
  413. workerPtr->skill_level++;
  414. }
  415. workerPtr->skill_level_minor = levelMinor;
  416. }
  417. }
  418. }
  419. //-------- End of function FirmBase::train_unit --------//
  420. //------- Begin of function FirmBase::recover_hit_point -------//
  421. //
  422. // Prayers recover their hit points.
  423. //
  424. // No need to recover the hit points of the general here as
  425. // this is taken care in the Unit class function of the general.
  426. //
  427. void FirmBase::recover_hit_point()
  428. {
  429. Worker* workerPtr = worker_array;
  430. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  431. {
  432. //------- increase worker hit points --------//
  433. if( workerPtr->hit_points < workerPtr->max_hit_points() )
  434. workerPtr->hit_points++;
  435. }
  436. }
  437. //------- End of function FirmBase::recover_hit_point -------//
  438. //--------- Begin of function FirmBase::disp_god_info ---------//
  439. //
  440. void FirmBase::disp_god_info(int dispY1, int refreshFlag)
  441. {
  442. //---------------- paint the panel --------------//
  443. if( refreshFlag == INFO_REPAINT )
  444. vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+50 );
  445. //-------- display the icon of the mythical creature -------//
  446. int x=INFO_X1+4, y=dispY1+4;
  447. UnitInfo* unitInfo = unit_res[ god_res[god_id]->unit_id ];
  448. if( refreshFlag == INFO_REPAINT )
  449. {
  450. vga.d3_panel_down( x, y, x+UNIT_LARGE_ICON_WIDTH+3, y+UNIT_LARGE_ICON_HEIGHT+3, 2 );
  451. vga_front.put_bitmap( x+2, y+2, unitInfo->get_large_icon_ptr(0) );
  452. //----------- display text ------------//
  453. x += UNIT_LARGE_ICON_WIDTH+10;
  454. font_san.put( x, y+2, unitInfo->name );
  455. }
  456. else
  457. {
  458. x += UNIT_LARGE_ICON_WIDTH+10;
  459. }
  460. vga_front.indicator( 0x00, x-3, y+18, pray_points, (float) MAX_PRAY_POINTS, 0 );
  461. }
  462. //----------- End of function FirmBase::disp_god_info -----------//
  463. //--------- Begin of function FirmBase::invoke_god ---------//
  464. //
  465. // Invoke God.
  466. //
  467. void FirmBase::invoke_god()
  468. {
  469. god_unit_recno = god_res[god_id]->invoke(firm_recno, center_x, center_y);
  470. }
  471. //----------- End of function FirmBase::invoke_god -----------//
  472. //--------- Begin of function FirmBase::can_invoke ---------//
  473. //
  474. int FirmBase::can_invoke()
  475. {
  476. //----- if the base's god creature has been destroyed -----//
  477. if( god_unit_recno && unit_array.is_deleted(god_unit_recno) )
  478. god_unit_recno = 0;
  479. //---------------------------------------------------------//
  480. return !god_unit_recno && // one base can only support one god
  481. overseer_recno &&
  482. pray_points >= MAX_PRAY_POINTS/10; // there must be at least 10% of the maximum pray points to cast a creature
  483. }
  484. //----------- End of function FirmBase::can_invoke -----------//