OTALKMSG.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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 : OTALKMSG.CPP
  21. //Description : Object TalkMsg
  22. #include <OMOUSE.h>
  23. #include <OSYS.h>
  24. #include <OVGA.h>
  25. #include <OINFO.h>
  26. #include <OFONT.h>
  27. #include <OTECHRES.h>
  28. #include <OGAMESET.h>
  29. #include <ONEWS.h>
  30. #include <ONATION.h>
  31. #include <OTALKRES.h>
  32. //------ Define function pointers array ------//
  33. static char talk_msg_reply_needed_array[] =
  34. {
  35. 1,
  36. 1,
  37. 1,
  38. 0,
  39. 0,
  40. 0,
  41. 1,
  42. 1,
  43. 1,
  44. 1,
  45. 1,
  46. 0,
  47. 1,
  48. 1,
  49. 1,
  50. 1,
  51. 1,
  52. 1,
  53. 1,
  54. 0,
  55. };
  56. //------- Begin of function TalkMsg::TalkMsg --------//
  57. //
  58. TalkMsg::TalkMsg()
  59. {
  60. memset( this, 0, sizeof(TalkMsg) );
  61. }
  62. //-------- End of function TalkMsg::TalkMsg ---------//
  63. //------- Begin of function TalkMsg::process_accepted_reply --------//
  64. //
  65. void TalkMsg::process_accepted_reply()
  66. {
  67. Nation* toNation = nation_array[to_nation_recno];
  68. Nation* fromNation = nation_array[from_nation_recno];
  69. NationRelation* fromRelation = fromNation->get_relation(to_nation_recno);
  70. NationRelation* toRelation = toNation->get_relation(from_nation_recno);
  71. int goodRelationDec=0; // whether the message is for requesting help.
  72. switch(talk_id)
  73. {
  74. case TALK_PROPOSE_TRADE_TREATY:
  75. toNation->set_trade_treaty(from_nation_recno, 1);
  76. break;
  77. case TALK_PROPOSE_FRIENDLY_TREATY:
  78. toNation->form_friendly_treaty(from_nation_recno);
  79. break;
  80. case TALK_PROPOSE_ALLIANCE_TREATY:
  81. toNation->form_alliance_treaty(from_nation_recno);
  82. break;
  83. case TALK_END_TRADE_TREATY:
  84. toNation->set_trade_treaty(from_nation_recno, 0);
  85. //---- set reject date on proposing treaty ----//
  86. fromRelation->last_talk_reject_date_array[TALK_PROPOSE_TRADE_TREATY-1] = info.game_date;
  87. toRelation->last_talk_reject_date_array[TALK_PROPOSE_TRADE_TREATY-1] = info.game_date;
  88. fromRelation->last_talk_reject_date_array[TALK_END_TRADE_TREATY-1] = info.game_date;
  89. toRelation->last_talk_reject_date_array[TALK_END_TRADE_TREATY-1] = info.game_date;
  90. //----- decrease reputation -----//
  91. if( toNation->reputation > 0 )
  92. fromNation->change_reputation( -toNation->reputation * 5 / 100 );
  93. break;
  94. case TALK_END_FRIENDLY_TREATY:
  95. case TALK_END_ALLIANCE_TREATY:
  96. fromNation->end_treaty(to_nation_recno, NATION_NEUTRAL);
  97. //---- set reject date on proposing treaty ----//
  98. //
  99. // If a friendly treaty is rejected, assuming an alliance treaty
  100. // is even more impossible. (thus set reject date on both friendly
  101. // and alliance treaties.)
  102. //
  103. // If a alliance treaty is rejected, only set reject date on
  104. // alliance treaty, it may still try proposing friendly treaty later.
  105. //
  106. //---------------------------------------------//
  107. fromRelation->last_talk_reject_date_array[TALK_PROPOSE_FRIENDLY_TREATY-1] = info.game_date;
  108. toRelation->last_talk_reject_date_array[TALK_PROPOSE_FRIENDLY_TREATY-1] = info.game_date;
  109. fromRelation->last_talk_reject_date_array[TALK_PROPOSE_ALLIANCE_TREATY-1] = info.game_date;
  110. toRelation->last_talk_reject_date_array[TALK_PROPOSE_ALLIANCE_TREATY-1] = info.game_date;
  111. break;
  112. case TALK_REQUEST_MILITARY_AID:
  113. goodRelationDec = 10;
  114. break;
  115. case TALK_REQUEST_TRADE_EMBARGO:
  116. {
  117. //--- send an end treaty message to the target kingdom ---//
  118. TalkMsg talkMsg;
  119. memset(&talkMsg, 0, sizeof(TalkMsg));
  120. talkMsg.to_nation_recno = (char) talk_para1;
  121. talkMsg.from_nation_recno = to_nation_recno;
  122. talkMsg.talk_id = TALK_END_TRADE_TREATY;
  123. talk_res.send_talk_msg( &talkMsg, COMMAND_AUTO );
  124. goodRelationDec = 4;
  125. }
  126. break;
  127. case TALK_REQUEST_CEASE_WAR:
  128. unit_array.stop_war_between(to_nation_recno, from_nation_recno);
  129. toNation->set_relation_status(from_nation_recno, NATION_TENSE);
  130. fromRelation->last_talk_reject_date_array[TALK_DECLARE_WAR-1] = info.game_date;
  131. toRelation->last_talk_reject_date_array[TALK_DECLARE_WAR-1] = info.game_date;
  132. break;
  133. case TALK_REQUEST_DECLARE_WAR:
  134. #ifdef AMPLUS
  135. if( fromNation->get_relation_status(talk_para1) == NATION_HOSTILE ) // the requesting nation must be at war with the enemy
  136. {
  137. #else
  138. {
  139. err_when( fromNation->get_relation_status(talk_para1) != NATION_HOSTILE ); // the requesting nation must be at war with the enemy
  140. #endif
  141. //-- if we are currently allied or friendly with the nation, we need to terminate the friendly/alliance treaty first --//
  142. TalkMsg talkMsg;
  143. if( toNation->get_relation_status(talk_para1) == NATION_ALLIANCE )
  144. {
  145. memset(&talkMsg, 0, sizeof(TalkMsg));
  146. talkMsg.to_nation_recno = (char) talk_para1;
  147. talkMsg.from_nation_recno = to_nation_recno;
  148. talkMsg.talk_id = TALK_END_ALLIANCE_TREATY;
  149. talk_res.send_talk_msg( &talkMsg, COMMAND_AUTO );
  150. }
  151. else if( toNation->get_relation_status(talk_para1) == NATION_FRIENDLY )
  152. {
  153. memset(&talkMsg, 0, sizeof(TalkMsg));
  154. talkMsg.to_nation_recno = (char) talk_para1;
  155. talkMsg.from_nation_recno = to_nation_recno;
  156. talkMsg.talk_id = TALK_END_FRIENDLY_TREATY;
  157. talk_res.send_talk_msg( &talkMsg, COMMAND_AUTO );
  158. }
  159. //--- send a declare war message to the target kingdom ---//
  160. memset(&talkMsg, 0, sizeof(TalkMsg));
  161. talkMsg.to_nation_recno = (char) talk_para1;
  162. talkMsg.from_nation_recno = to_nation_recno;
  163. talkMsg.talk_id = TALK_DECLARE_WAR;
  164. talk_res.send_talk_msg( &talkMsg, COMMAND_AUTO );
  165. //----------------------------------------------------//
  166. goodRelationDec = 10;
  167. }
  168. break;
  169. case TALK_REQUEST_BUY_FOOD:
  170. {
  171. int buyCost = talk_para1 * talk_para2 / 10;
  172. fromNation->add_food( (float) talk_para1 );
  173. fromNation->add_expense( EXPENSE_IMPORTS, (float) buyCost, 0 );
  174. toNation->consume_food( (float) talk_para1 );
  175. toNation->add_income( INCOME_EXPORTS, (float) buyCost, 0 );
  176. break;
  177. }
  178. case TALK_DECLARE_WAR:
  179. toRelation->started_war_on_us_count++; // how many times this nation has started a war with us, the more the times the worse this nation is.
  180. toNation->set_relation_status(from_nation_recno, NATION_HOSTILE);
  181. fromRelation->last_talk_reject_date_array[TALK_REQUEST_CEASE_WAR-1] = info.game_date;
  182. toRelation->last_talk_reject_date_array[TALK_REQUEST_CEASE_WAR-1] = info.game_date;
  183. //--- decrease reputation of the nation which declares war ---//
  184. if( toNation->reputation > 0 )
  185. fromNation->change_reputation( -toNation->reputation * 20 / 100 );
  186. break;
  187. case TALK_GIVE_TRIBUTE:
  188. case TALK_GIVE_AID:
  189. fromNation->give_tribute( to_nation_recno, talk_para1 );
  190. break;
  191. case TALK_DEMAND_TRIBUTE:
  192. case TALK_DEMAND_AID:
  193. toNation->give_tribute( from_nation_recno, talk_para1 );
  194. goodRelationDec = talk_para1/200;
  195. break;
  196. case TALK_GIVE_TECH:
  197. fromNation->give_tech( to_nation_recno, talk_para1, talk_para2 );
  198. break;
  199. case TALK_DEMAND_TECH:
  200. talk_para2 = tech_res[talk_para1]->get_nation_tech_level(to_nation_recno); // get the latest tech version id. of the agreed nation.
  201. toNation->give_tech( from_nation_recno, talk_para1, talk_para2 );
  202. goodRelationDec = talk_para2*3;
  203. break;
  204. case TALK_REQUEST_SURRENDER:
  205. {
  206. float offeredAmt = (float) talk_para1 * 10; // * 10 is to restore its original value. It has been divided by 10 to cope with the upper limit of <short>
  207. toNation->add_income(INCOME_TRIBUTE, offeredAmt);
  208. fromNation->add_expense(EXPENSE_TRIBUTE, offeredAmt);
  209. toNation->surrender(from_nation_recno);
  210. break;
  211. }
  212. case TALK_SURRENDER:
  213. fromNation->surrender(to_nation_recno);
  214. break;
  215. default:
  216. err_here();
  217. }
  218. //---- if the nation accepts a message that is requesting help, then decrease its good_relation_duration_rating, so it won't accept so easily next time ---//
  219. if( goodRelationDec )
  220. toRelation->good_relation_duration_rating -= (float) goodRelationDec;
  221. //-- remove talk messges that are the same but sent from the opposite nation --//
  222. TalkMsg talkMsg;
  223. talkMsg.from_nation_recno = to_nation_recno;
  224. talkMsg.to_nation_recno = from_nation_recno;
  225. talkMsg.talk_id = talk_id;
  226. int loopCount=0;
  227. while(1)
  228. {
  229. err_when( loopCount++ > 100 );
  230. int talkMsgRecno = talk_res.is_talk_msg_exist(&talkMsg, 0); // don't check talk_para1 & talk_para2
  231. if( talkMsgRecno )
  232. talk_res.del_talk_msg(talkMsgRecno);
  233. else
  234. break;
  235. }
  236. }
  237. //-------- End of function TalkMsg::process_accepted_reply ---------//
  238. //----- Begin of function TalkMsg::is_reply_needed ------//
  239. //
  240. // Whether a reply is needed for this message.
  241. //
  242. int TalkMsg::is_reply_needed()
  243. {
  244. return talk_msg_reply_needed_array[talk_id-1];
  245. }
  246. //------- End of function TalkMsg::is_reply_needed ------//
  247. //----- Begin of function TalkMsg::is_valid_to_reply ------//
  248. //
  249. // Return whether this message is still valid. Only
  250. // if this message is valid, the receiver can answer
  251. // this message.
  252. //
  253. int TalkMsg::is_valid_to_reply()
  254. {
  255. //-----------------------------------------------------//
  256. // When a diplomatic message is sent, the receiver must
  257. // reply the message with a month.
  258. //-----------------------------------------------------//
  259. #define TALK_MSG_VALID_DAYS 30
  260. if( info.game_date > date + TALK_MSG_VALID_DAYS )
  261. return 0;
  262. //--- check if the nations are still there -----//
  263. if( nation_array.is_deleted(from_nation_recno) )
  264. return 0;
  265. if( nation_array.is_deleted(to_nation_recno) )
  266. return 0;
  267. //--------------------------------------//
  268. if( !talk_res.can_send_msg(to_nation_recno, from_nation_recno, talk_id) )
  269. return 0;
  270. //--------------------------------------//
  271. Nation* toNation = nation_array[to_nation_recno];
  272. Nation* fromNation = nation_array[from_nation_recno];
  273. switch( talk_id )
  274. {
  275. case TALK_REQUEST_TRADE_EMBARGO:
  276. if( nation_array.is_deleted(talk_para1) )
  277. return 0;
  278. //-- if the requesting nation is itself trading with the target nation --//
  279. if( fromNation->get_relation(talk_para1)->trade_treaty )
  280. return 0;
  281. //-- or if the requested nation already doesn't have a trade treaty with the nation --//
  282. if( !toNation->get_relation(talk_para1)->trade_treaty )
  283. return 0;
  284. break;
  285. case TALK_REQUEST_DECLARE_WAR:
  286. if( nation_array.is_deleted(talk_para1) )
  287. return 0;
  288. //-- if the requesting nation is no longer hostile with the nation --//
  289. if( fromNation->get_relation_status(talk_para1) != NATION_HOSTILE )
  290. return 0;
  291. //-- or if the requested nation has become hostile with the nation --//
  292. if( toNation->get_relation_status(talk_para1) == NATION_HOSTILE )
  293. return 0;
  294. break;
  295. case TALK_REQUEST_BUY_FOOD:
  296. return fromNation->cash >= talk_para1 * talk_para2 / 10;
  297. case TALK_GIVE_TRIBUTE:
  298. case TALK_GIVE_AID:
  299. return fromNation->cash >= talk_para1;
  300. case TALK_GIVE_TECH:
  301. /* // still display the message even if the nation already has the technology
  302. //---- if the nation has acquired the technology itself ----//
  303. if( tech_res[talk_para1]->get_nation_tech_level(to_nation_recno) >= talk_para2 )
  304. return 0;
  305. */
  306. break;
  307. case TALK_DEMAND_TECH:
  308. /*
  309. //---- if the requesting nation has acquired the technology itself ----//
  310. if( tech_res[talk_para1]->get_nation_tech_level(from_nation_recno) >= talk_para2 )
  311. return 0;
  312. */
  313. break;
  314. }
  315. return 1;
  316. }
  317. //------- End of function TalkMsg::is_valid_to_reply ------//
  318. //----- Begin of function TalkMsg::is_valid_to_disp ------//
  319. //
  320. // Return whether this message is still valid. Only
  321. // if this message is valid, the receiver can answer
  322. // this message.
  323. //
  324. int TalkMsg::is_valid_to_disp()
  325. {
  326. //--- check if the nations are still there -----//
  327. if( nation_array.is_deleted(from_nation_recno) )
  328. return 0;
  329. if( nation_array.is_deleted(to_nation_recno) )
  330. return 0;
  331. //--------------------------------------//
  332. Nation* toNation = nation_array[to_nation_recno];
  333. Nation* fromNation = nation_array[from_nation_recno];
  334. switch( talk_id )
  335. {
  336. case TALK_REQUEST_TRADE_EMBARGO:
  337. if( nation_array.is_deleted(talk_para1) )
  338. return 0;
  339. break;
  340. case TALK_REQUEST_DECLARE_WAR:
  341. if( nation_array.is_deleted(talk_para1) )
  342. return 0;
  343. break;
  344. }
  345. return 1;
  346. }
  347. //------- End of function TalkMsg::is_valid_to_disp ------//
  348. //----- Begin of function TalkMsg::can_accept ------//
  349. //
  350. // Return whether the receiver can accept this message
  351. // if he wants to.
  352. //
  353. int TalkMsg::can_accept()
  354. {
  355. Nation* toNation = nation_array[to_nation_recno];
  356. switch( talk_id )
  357. {
  358. case TALK_REQUEST_BUY_FOOD:
  359. return toNation->food >= talk_para1;
  360. case TALK_DEMAND_TRIBUTE:
  361. case TALK_DEMAND_AID:
  362. return toNation->cash >= talk_para1;
  363. case TALK_DEMAND_TECH: // the requested nation has the technology
  364. return tech_res[talk_para1]->get_nation_tech_level(to_nation_recno) > 0;
  365. }
  366. return 1;
  367. }
  368. //------- End of function TalkMsg::can_accept ------//
  369. //----- Begin of function TalkMsg::from_nation_name ------//
  370. //
  371. char* TalkMsg::from_nation_name()
  372. {
  373. static String str;
  374. str = nation_array[from_nation_recno]->nation_name();
  375. //------ add nation color bar -------//
  376. if( talk_res.msg_add_nation_color )
  377. {
  378. char colorCodeStr[] = " 0";
  379. colorCodeStr[1] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[from_nation_recno]->color_scheme_id;
  380. str += colorCodeStr;
  381. }
  382. return str;
  383. }
  384. //------- End of function TalkMsg::from_nation_name ------//
  385. //----- Begin of function TalkMsg::to_nation_name ------//
  386. //
  387. char* TalkMsg::to_nation_name()
  388. {
  389. static String str;
  390. str = nation_array[to_nation_recno]->nation_name();
  391. //------ add nation color bar -------//
  392. if( talk_res.msg_add_nation_color )
  393. {
  394. char colorCodeStr[] = " 0";
  395. colorCodeStr[1] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[to_nation_recno]->color_scheme_id;
  396. str += colorCodeStr;
  397. }
  398. return str;
  399. }
  400. //------- End of function TalkMsg::to_nation_name ------//
  401. //----- Begin of function TalkMsg::from_king_name ------//
  402. //
  403. char* TalkMsg::from_king_name()
  404. {
  405. static String str;
  406. str = translate.process("King ");
  407. str += nation_array[from_nation_recno]->king_name();
  408. //------ add nation color bar -------//
  409. if( talk_res.msg_add_nation_color )
  410. {
  411. char colorCodeStr[] = " 0";
  412. colorCodeStr[1] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[from_nation_recno]->color_scheme_id;
  413. str += colorCodeStr;
  414. }
  415. return str;
  416. }
  417. //------- End of function TalkMsg::from_king_name ------//
  418. //----- Begin of function TalkMsg::to_king_name ------//
  419. //
  420. char* TalkMsg::to_king_name()
  421. {
  422. static String str;
  423. str = translate.process("King ");
  424. str += nation_array[to_nation_recno]->king_name();
  425. //------ add nation color bar -------//
  426. if( talk_res.msg_add_nation_color )
  427. {
  428. char colorCodeStr[] = " 0";
  429. colorCodeStr[1] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[to_nation_recno]->color_scheme_id;
  430. str += colorCodeStr;
  431. }
  432. return str;
  433. }
  434. //------- End of function TalkMsg::to_king_name ------//
  435. //----- Begin of function TalkMsg::nation_color_code_str ------//
  436. //
  437. char* TalkMsg::nation_color_code_str(int nationRecno)
  438. {
  439. static char colorCodeStr[] = " 0";
  440. colorCodeStr[1] = FIRST_NATION_COLOR_CODE_IN_TEXT + nation_array[nationRecno]->color_scheme_id;
  441. return colorCodeStr;
  442. }
  443. //------- End of function TalkMsg::nation_color_code_str ------//