OOPTMENU.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  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 : OOPTMENU.CPP
  21. // Description : in-game option menu (async version)
  22. #include <OVGA.h>
  23. #include <OVGABUF.h>
  24. #include <OINFO.h>
  25. #include <OCOLTBL.h>
  26. #include <ORACERES.h>
  27. #include <OMOUSE.h>
  28. #include <OMOUSECR.h>
  29. #include <KEY.h>
  30. #include <OPOWER.h>
  31. #include <OIMGRES.h>
  32. #include <OFONT.h>
  33. #include <OAUDIO.h>
  34. #include <OMUSIC.h>
  35. #include <OSYS.h>
  36. #include <OOPTMENU.h>
  37. enum { BASIC_OPTION_X_SPACE = 78,
  38. BASIC_OPTION_HEIGHT = 32 };
  39. enum { COLOR_OPTION_X_SPACE = 35,
  40. COLOR_OPTION_HEIGHT = 32 };
  41. enum { SERVICE_OPTION_X_SPACE = 180,
  42. SERVICE_OPTION_HEIGHT = 139 };
  43. enum { SLIDE_BUTTON_WIDTH = 23,
  44. SLIDE_BUTTON_HEIGHT = 24 };
  45. static char race_table[MAX_RACE] = // race translation table
  46. {
  47. RACE_CHINESE, RACE_GREEK, RACE_JAPANESE, RACE_MAYA,
  48. RACE_PERSIAN, RACE_NORMAN, RACE_VIKING
  49. };
  50. static char reverse_race_table[MAX_RACE] = // race translation table
  51. {
  52. 5, 3, 1, 6, 4, 0, 2
  53. };
  54. static void disp_virtual_button(ButtonCustom *button, int);
  55. static void disp_slide_bar(SlideBar *slideBar, int);
  56. // return 1 if ok, config is changed
  57. #define IGOPTION_SE_VOL 0x00000001
  58. #define IGOPTION_MUSIC_VOL 0x00000002
  59. #define IGOPTION_RACE 0x00000004
  60. #define IGOPTION_HELP 0x00000008
  61. #define IGOPTION_NEWS 0x00000010
  62. #define IGOPTION_GAME_SPEED 0x00000020
  63. #define IGOPTION_SCROLL_SPEED 0x00000040
  64. #define IGOPTION_REPORT 0x00000080
  65. #define IGOPTION_SHOW_ICON 0x00000100
  66. #define IGOPTION_DRAW_PATH 0x00000200
  67. #define IGOPTION_MAP_ID 0x00000400
  68. #define IGOPTION_PAGE 0x40000000
  69. #define IGOPTION_ALL 0x7FFFFFFF
  70. OptionMenu::OptionMenu() : help_group(3), news_group(2), report_group(2) ,
  71. show_icon_group(2), show_path_group(4)
  72. {
  73. active_flag = 0;
  74. }
  75. void OptionMenu::enter(char untilExitFlag)
  76. {
  77. if( is_active() )
  78. return;
  79. int i;
  80. refresh_flag = IGOPTION_ALL;
  81. update_flag = 0;
  82. active_flag = 1;
  83. info.save_game_scr();
  84. Config& tempConfig = config;
  85. old_config = config;
  86. // -------- initialize sound effect volume --------//
  87. se_vol_slide.init_slide(264, 123, 420, 123+SLIDE_BUTTON_HEIGHT-1,
  88. SLIDE_BUTTON_WIDTH, disp_slide_bar);
  89. se_vol_slide.set(0, 100, tempConfig.sound_effect_flag ? tempConfig.sound_effect_volume : 0);
  90. // -------- initialize music volume --------//
  91. music_vol_slide.init_slide(566, 123, 722, 123+SLIDE_BUTTON_HEIGHT-1,
  92. SLIDE_BUTTON_WIDTH, disp_slide_bar);
  93. music_vol_slide.set(0, 100, tempConfig.music_flag ? tempConfig.wav_music_volume : 0);
  94. // -------- initialize frame speed volume --------//
  95. frame_speed_slide.init_slide(196, 410, 352, 410+SLIDE_BUTTON_HEIGHT-1,
  96. SLIDE_BUTTON_WIDTH, disp_slide_bar);
  97. frame_speed_slide.set(0, 31, tempConfig.frame_speed <= 30 ? tempConfig.frame_speed: 31);
  98. // use frame 31 to represent full speed (i.e. 99)
  99. // -------- initialize scroll speed volume --------//
  100. scroll_speed_slide.init_slide(196, 454, 352, 454+SLIDE_BUTTON_HEIGHT-1,
  101. SLIDE_BUTTON_WIDTH, disp_slide_bar);
  102. scroll_speed_slide.set(0, 10, tempConfig.scroll_speed );
  103. // --------- initialize race buttons ---------- //
  104. for( i = 0; i < MAX_RACE; ++i )
  105. {
  106. race_button[i].create(181+i*BASIC_OPTION_X_SPACE, 162,
  107. 181+(i+1)*BASIC_OPTION_X_SPACE-1, 162+BASIC_OPTION_HEIGHT-1,
  108. disp_virtual_button, ButtonCustomPara(NULL, race_table[i]));
  109. }
  110. // --------- initialize help button group ---------- //
  111. for( i = 0; i < 3; ++i )
  112. {
  113. help_group[i].create(120+i*BASIC_OPTION_X_SPACE, 244,
  114. 120+(i+1)*BASIC_OPTION_X_SPACE-1, 244+BASIC_OPTION_HEIGHT-1,
  115. disp_virtual_button, ButtonCustomPara(&help_group, i), 0, 0);
  116. }
  117. // --------- initialize news button group ---------- //
  118. for( i = 0; i < 2; ++i )
  119. {
  120. news_group[i].create(198+i*BASIC_OPTION_X_SPACE, 320,
  121. 198+(i+1)*BASIC_OPTION_X_SPACE-1, 320+BASIC_OPTION_HEIGHT-1,
  122. disp_virtual_button, ButtonCustomPara(&news_group, 1-i), 0, 0);
  123. }
  124. // --------- initialize report button group ---------- //
  125. for( i = 0; i < 2; ++i )
  126. {
  127. report_group[i].create(572+i*BASIC_OPTION_X_SPACE, 244,
  128. 572+(i+1)*BASIC_OPTION_X_SPACE-1, 244+BASIC_OPTION_HEIGHT-1,
  129. disp_virtual_button, ButtonCustomPara(&report_group, 1-i), 0, 0);
  130. }
  131. // --------- initialize show icon button group ---------- //
  132. for( i = 0; i < 2; ++i )
  133. {
  134. show_icon_group[i].create(572+i*BASIC_OPTION_X_SPACE, 320,
  135. 572+(i+1)*BASIC_OPTION_X_SPACE-1, 320+BASIC_OPTION_HEIGHT-1,
  136. disp_virtual_button, ButtonCustomPara(&show_icon_group, 1-i), 0, 0);
  137. }
  138. // --------- initialize show path button group ---------- //
  139. for( i = 0; i < 4; ++i )
  140. {
  141. show_path_group[i].create(572+(i/2)*BASIC_OPTION_X_SPACE, 408+(i%2)*BASIC_OPTION_HEIGHT,
  142. 572+(i/2+1)*BASIC_OPTION_X_SPACE-1, 408+(i%2+1)*BASIC_OPTION_HEIGHT-1,
  143. disp_virtual_button, ButtonCustomPara(&show_path_group, i), 0, 0);
  144. }
  145. // --------- other buttons --------//
  146. start_button.create(200, 520, "RETURN-U", "RETURN-D", 1, 0);
  147. cancel_button.create(416, 520, "CANCEL-U", "CANCEL-D", 1, 0);
  148. mouse_cursor.set_icon(CURSOR_NORMAL);
  149. power.win_opened = 1;
  150. if( untilExitFlag )
  151. {
  152. while( is_active() )
  153. {
  154. sys.yield();
  155. mouse.get_event();
  156. disp();
  157. sys.blt_virtual_buf();
  158. music.yield();
  159. detect();
  160. }
  161. }
  162. }
  163. void OptionMenu::disp(int needRepaint)
  164. {
  165. if( !active_flag )
  166. return;
  167. if( needRepaint )
  168. refresh_flag = IGOPTION_ALL;
  169. int i;
  170. Config &tempConfig = config;
  171. // ------- display --------//
  172. if(refresh_flag)
  173. {
  174. if( refresh_flag & IGOPTION_PAGE )
  175. {
  176. image_interface.put_to_buf( &vga_back, "OPTIONS");
  177. vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
  178. start_button.paint();
  179. cancel_button.paint();
  180. }
  181. if( refresh_flag & IGOPTION_SE_VOL )
  182. {
  183. se_vol_slide.paint(tempConfig.sound_effect_flag ? percent_to_slide_volume(tempConfig.sound_effect_volume) : 0);
  184. }
  185. if( refresh_flag & IGOPTION_MUSIC_VOL )
  186. {
  187. music_vol_slide.paint(tempConfig.music_flag ? percent_to_slide_volume(tempConfig.wav_music_volume) : 0);
  188. }
  189. if( refresh_flag & IGOPTION_RACE )
  190. {
  191. for( i = 0; i < MAX_RACE; ++i )
  192. race_button[i].paint();
  193. }
  194. if( refresh_flag & IGOPTION_HELP )
  195. {
  196. help_group.paint(tempConfig.help_mode);
  197. }
  198. if( refresh_flag & IGOPTION_NEWS )
  199. {
  200. news_group.paint(1-tempConfig.disp_news_flag);
  201. }
  202. if( refresh_flag & IGOPTION_GAME_SPEED )
  203. {
  204. frame_speed_slide.paint(tempConfig.frame_speed <= 30 ? tempConfig.frame_speed: 31);
  205. }
  206. if( refresh_flag & IGOPTION_SCROLL_SPEED )
  207. {
  208. scroll_speed_slide.paint(tempConfig.scroll_speed);
  209. }
  210. if( refresh_flag & IGOPTION_REPORT )
  211. {
  212. report_group.paint(1-tempConfig.opaque_report);
  213. }
  214. if( refresh_flag & IGOPTION_SHOW_ICON )
  215. {
  216. show_icon_group.paint(1-tempConfig.show_all_unit_icon);
  217. }
  218. if( refresh_flag & IGOPTION_DRAW_PATH )
  219. {
  220. show_path_group.paint(tempConfig.show_unit_path);
  221. }
  222. if( refresh_flag & IGOPTION_MAP_ID )
  223. {
  224. //int x2;
  225. //x2 = font_san.put(521, 64, "Map ID : ", 1);
  226. //x2 = font_san.put(x2, 64, info.random_seed, 1);
  227. }
  228. refresh_flag = 0;
  229. }
  230. }
  231. int OptionMenu::detect()
  232. {
  233. if( !active_flag )
  234. return 0;
  235. Config &tempConfig = config;
  236. int i;
  237. int retFlag1 = 1;
  238. if( se_vol_slide.detect() == 1)
  239. {
  240. tempConfig.sound_effect_flag = se_vol_slide.view_recno > 0;
  241. if( se_vol_slide.view_recno > 0)
  242. tempConfig.sound_effect_volume = slide_to_percent_volume(se_vol_slide.view_recno);
  243. else
  244. tempConfig.sound_effect_volume = 1; // never set sound_effect_volume = 0
  245. audio.set_wav_volume(tempConfig.sound_effect_volume);
  246. // change music volume, sound effect volume may change music volume
  247. if( tempConfig.music_flag )
  248. {
  249. music.change_volume( tempConfig.wav_music_volume);
  250. }
  251. }
  252. else if( music_vol_slide.detect() == 1)
  253. {
  254. tempConfig.music_flag = music_vol_slide.view_recno > 0;
  255. tempConfig.wav_music_volume = slide_to_percent_volume(music_vol_slide.view_recno);
  256. if( tempConfig.music_flag )
  257. {
  258. music.change_volume( tempConfig.wav_music_volume );
  259. }
  260. }
  261. else if( frame_speed_slide.detect() == 1)
  262. {
  263. tempConfig.frame_speed = frame_speed_slide.view_recno <= 30 ? frame_speed_slide.view_recno : 99;
  264. }
  265. else if( scroll_speed_slide.detect() == 1)
  266. {
  267. tempConfig.scroll_speed = scroll_speed_slide.view_recno;
  268. }
  269. else
  270. retFlag1 = 0;
  271. int retFlag2 = 0;
  272. for( i = 0; i < MAX_RACE; ++i )
  273. {
  274. if( race_button[i].detect() )
  275. {
  276. if( config.music_flag )
  277. {
  278. music.play( race_button[i].custom_para.value + 1,
  279. sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
  280. }
  281. else
  282. {
  283. // stop any music playing
  284. music.stop();
  285. }
  286. retFlag2 = 1;
  287. }
  288. }
  289. int retFlag3 = 1;
  290. if( help_group.detect() >= 0)
  291. {
  292. tempConfig.help_mode = help_group[help_group()].custom_para.value;
  293. //refresh_flag |= IGOPTION_HELP;
  294. update_flag |= IGOPTION_HELP;
  295. }
  296. else if( news_group.detect() >= 0)
  297. {
  298. tempConfig.disp_news_flag = news_group[news_group()].custom_para.value;
  299. //refresh_flag |= IGOPTION_HELP;
  300. update_flag |= IGOPTION_HELP;
  301. }
  302. else if( report_group.detect() >= 0)
  303. {
  304. tempConfig.opaque_report = report_group[report_group()].custom_para.value;
  305. //refresh_flag |= IGOPTION_REPORT;
  306. update_flag |= IGOPTION_REPORT;
  307. }
  308. else if( show_icon_group.detect() >= 0)
  309. {
  310. tempConfig.show_all_unit_icon = show_icon_group[show_icon_group()].custom_para.value;
  311. //refresh_flag |= IGOPTION_SHOW_ICON;
  312. update_flag |= IGOPTION_SHOW_ICON;
  313. }
  314. else if( show_path_group.detect() >= 0)
  315. {
  316. tempConfig.show_unit_path = show_path_group[show_path_group()].custom_para.value;
  317. //refresh_flag |= IGOPTION_DRAW_PATH;
  318. update_flag |= IGOPTION_DRAW_PATH;
  319. }
  320. else if( start_button.detect(KEY_RETURN) )
  321. {
  322. if( &config != &tempConfig)
  323. config = tempConfig;
  324. exit(1);
  325. if( update_flag )
  326. {
  327. // save config
  328. Config fileConfig;
  329. if( !fileConfig.load("CONFIG.DAT") )
  330. fileConfig.init();
  331. fileConfig.change_preference(tempConfig);
  332. fileConfig.save("CONFIG.DAT");
  333. }
  334. }
  335. else if( cancel_button.detect(KEY_ESC) )
  336. {
  337. config = old_config;
  338. exit(0);
  339. }
  340. else
  341. retFlag3 = 0;
  342. return retFlag1 || retFlag2 || retFlag3;
  343. }
  344. // 0 = abort
  345. // 1 = accept
  346. void OptionMenu::exit(int action)
  347. {
  348. // reflect the effect of config.music_flag, config.wav_music_volume
  349. audio.set_wav_volume(config.sound_effect_volume);
  350. if( config.music_flag )
  351. {
  352. if( music.is_playing() )
  353. {
  354. music.change_volume(config.wav_music_volume);
  355. }
  356. }
  357. else
  358. {
  359. music.stop();
  360. }
  361. // temporary disable active_flag for info.rest_game_scr to call info.disp
  362. active_flag = 0;
  363. info.rest_game_scr();
  364. active_flag = 1;
  365. power.win_opened = 0;
  366. active_flag = 0;
  367. return;
  368. }
  369. void OptionMenu::abort()
  370. {
  371. info.rest_game_scr();
  372. power.win_opened = 0;
  373. active_flag = 0;
  374. }
  375. // ---------- begin of static function disp_virtual_button -----//
  376. static void disp_virtual_button(ButtonCustom *button, int)
  377. {
  378. mouse.hide_area(button->x1, button->y1, button->x2, button->y2);
  379. if( !button->pushed_flag )
  380. {
  381. // copy from back buffer to front buffer
  382. IMGcopy(vga_front.buf_ptr(), vga_front.buf_pitch(),
  383. vga_back.buf_ptr(), vga_back.buf_pitch(),
  384. button->x1, button->y1, button->x2, button->y2 );
  385. }
  386. else
  387. {
  388. // copy from back buffer to front buffer, but the area is
  389. // darkened by 2 scale
  390. IMGcopyRemap(vga_front.buf_ptr(), vga_front.buf_pitch(),
  391. vga_back.buf_ptr(), vga_back.buf_pitch(),
  392. button->x1, button->y1, button->x2, button->y2,
  393. vga.vga_color_table->get_table(-2) );
  394. // draw black frame
  395. if( button->x2-button->x1+1 == BASIC_OPTION_X_SPACE &&
  396. button->y2-button->y1+1 == BASIC_OPTION_HEIGHT )
  397. {
  398. image_interface.put_front(button->x1, button->y1, "BAS_DOWN");
  399. }
  400. else if( button->x2-button->x1+1 == COLOR_OPTION_X_SPACE &&
  401. button->y2-button->y1+1 == COLOR_OPTION_HEIGHT )
  402. {
  403. image_interface.put_front(button->x1, button->y1, "COL_DOWN");
  404. }
  405. else if( button->x2-button->x1+1 == SERVICE_OPTION_X_SPACE &&
  406. button->y2-button->y1+1 == SERVICE_OPTION_HEIGHT )
  407. {
  408. image_interface.put_front(button->x1, button->y1, "NMPG-1BD");
  409. }
  410. }
  411. mouse.show_area();
  412. }
  413. // ---------- end of static function disp_virtual_button -----//
  414. // ---------- begin of static function disp_slide_bar -----//
  415. static void disp_slide_bar(SlideBar *slideBar, int)
  416. {
  417. vga.blt_buf(slideBar->scrn_x1, slideBar->scrn_y1,
  418. slideBar->scrn_x2, slideBar->scrn_y2, 0 );
  419. image_interface.put_front(slideBar->rect_left(), slideBar->scrn_y1, "SLIDBALL");
  420. }
  421. // ---------- end of static function disp_slide_bar -----//
  422. int OptionMenu::slide_to_percent_volume(int slideVolume)
  423. {
  424. switch( slideVolume / 10)
  425. {
  426. case 0:
  427. return slideVolume * 5;
  428. case 1:
  429. case 2:
  430. case 3:
  431. return slideVolume+40;
  432. break;
  433. case 4:
  434. case 5:
  435. return slideVolume/2 + 60;
  436. break;
  437. case 6:
  438. case 7:
  439. case 8:
  440. case 9:
  441. case 10:
  442. return slideVolume/4+75;
  443. break;
  444. default:
  445. err_here();
  446. return slideVolume;
  447. }
  448. }
  449. // slideVolume 0 10 20 30 40 50 60 70 80 90 100
  450. // !----!----!----!----!----!----!----!----!----!----!
  451. // percentVoume 0 50 80 90 100
  452. int OptionMenu::percent_to_slide_volume(int percentVolume)
  453. {
  454. switch(percentVolume/10)
  455. {
  456. case 0:
  457. case 1:
  458. case 2:
  459. case 3:
  460. case 4:
  461. return percentVolume/5;
  462. case 5:
  463. case 6:
  464. case 7:
  465. return percentVolume - 40;
  466. case 8:
  467. return (percentVolume-60) * 2;
  468. case 9:
  469. case 10:
  470. return (percentVolume-75) * 4;
  471. default:
  472. err_here();
  473. return percentVolume;
  474. }
  475. }