/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// Filename : OOPTMENU.CPP
// Description : in-game option menu (async version)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
enum { BASIC_OPTION_X_SPACE = 78,
BASIC_OPTION_HEIGHT = 32 };
enum { COLOR_OPTION_X_SPACE = 35,
COLOR_OPTION_HEIGHT = 32 };
enum { SERVICE_OPTION_X_SPACE = 180,
SERVICE_OPTION_HEIGHT = 139 };
enum { SLIDE_BUTTON_WIDTH = 23,
SLIDE_BUTTON_HEIGHT = 24 };
static char race_table[MAX_RACE] = // race translation table
{
RACE_CHINESE, RACE_GREEK, RACE_JAPANESE, RACE_MAYA,
RACE_PERSIAN, RACE_NORMAN, RACE_VIKING
};
static char reverse_race_table[MAX_RACE] = // race translation table
{
5, 3, 1, 6, 4, 0, 2
};
static void disp_virtual_button(ButtonCustom *button, int);
static void disp_slide_bar(SlideBar *slideBar, int);
// return 1 if ok, config is changed
#define IGOPTION_SE_VOL 0x00000001
#define IGOPTION_MUSIC_VOL 0x00000002
#define IGOPTION_RACE 0x00000004
#define IGOPTION_HELP 0x00000008
#define IGOPTION_NEWS 0x00000010
#define IGOPTION_GAME_SPEED 0x00000020
#define IGOPTION_SCROLL_SPEED 0x00000040
#define IGOPTION_REPORT 0x00000080
#define IGOPTION_SHOW_ICON 0x00000100
#define IGOPTION_DRAW_PATH 0x00000200
#define IGOPTION_MAP_ID 0x00000400
#define IGOPTION_PAGE 0x40000000
#define IGOPTION_ALL 0x7FFFFFFF
OptionMenu::OptionMenu() : help_group(3), news_group(2), report_group(2) ,
show_icon_group(2), show_path_group(4)
{
active_flag = 0;
}
void OptionMenu::enter(char untilExitFlag)
{
if( is_active() )
return;
int i;
refresh_flag = IGOPTION_ALL;
update_flag = 0;
active_flag = 1;
info.save_game_scr();
Config& tempConfig = config;
old_config = config;
// -------- initialize sound effect volume --------//
se_vol_slide.init_slide(264, 123, 420, 123+SLIDE_BUTTON_HEIGHT-1,
SLIDE_BUTTON_WIDTH, disp_slide_bar);
se_vol_slide.set(0, 100, tempConfig.sound_effect_flag ? tempConfig.sound_effect_volume : 0);
// -------- initialize music volume --------//
music_vol_slide.init_slide(566, 123, 722, 123+SLIDE_BUTTON_HEIGHT-1,
SLIDE_BUTTON_WIDTH, disp_slide_bar);
music_vol_slide.set(0, 100, tempConfig.music_flag ? tempConfig.wav_music_volume : 0);
// -------- initialize frame speed volume --------//
frame_speed_slide.init_slide(196, 410, 352, 410+SLIDE_BUTTON_HEIGHT-1,
SLIDE_BUTTON_WIDTH, disp_slide_bar);
frame_speed_slide.set(0, 31, tempConfig.frame_speed <= 30 ? tempConfig.frame_speed: 31);
// use frame 31 to represent full speed (i.e. 99)
// -------- initialize scroll speed volume --------//
scroll_speed_slide.init_slide(196, 454, 352, 454+SLIDE_BUTTON_HEIGHT-1,
SLIDE_BUTTON_WIDTH, disp_slide_bar);
scroll_speed_slide.set(0, 10, tempConfig.scroll_speed );
// --------- initialize race buttons ---------- //
for( i = 0; i < MAX_RACE; ++i )
{
race_button[i].create(181+i*BASIC_OPTION_X_SPACE, 162,
181+(i+1)*BASIC_OPTION_X_SPACE-1, 162+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, race_table[i]));
}
// --------- initialize help button group ---------- //
for( i = 0; i < 3; ++i )
{
help_group[i].create(120+i*BASIC_OPTION_X_SPACE, 244,
120+(i+1)*BASIC_OPTION_X_SPACE-1, 244+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&help_group, i), 0, 0);
}
// --------- initialize news button group ---------- //
for( i = 0; i < 2; ++i )
{
news_group[i].create(198+i*BASIC_OPTION_X_SPACE, 320,
198+(i+1)*BASIC_OPTION_X_SPACE-1, 320+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&news_group, 1-i), 0, 0);
}
// --------- initialize report button group ---------- //
for( i = 0; i < 2; ++i )
{
report_group[i].create(572+i*BASIC_OPTION_X_SPACE, 244,
572+(i+1)*BASIC_OPTION_X_SPACE-1, 244+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&report_group, 1-i), 0, 0);
}
// --------- initialize show icon button group ---------- //
for( i = 0; i < 2; ++i )
{
show_icon_group[i].create(572+i*BASIC_OPTION_X_SPACE, 320,
572+(i+1)*BASIC_OPTION_X_SPACE-1, 320+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&show_icon_group, 1-i), 0, 0);
}
// --------- initialize show path button group ---------- //
for( i = 0; i < 4; ++i )
{
show_path_group[i].create(572+(i/2)*BASIC_OPTION_X_SPACE, 408+(i%2)*BASIC_OPTION_HEIGHT,
572+(i/2+1)*BASIC_OPTION_X_SPACE-1, 408+(i%2+1)*BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&show_path_group, i), 0, 0);
}
// --------- other buttons --------//
start_button.create(200, 520, "RETURN-U", "RETURN-D", 1, 0);
cancel_button.create(416, 520, "CANCEL-U", "CANCEL-D", 1, 0);
mouse_cursor.set_icon(CURSOR_NORMAL);
power.win_opened = 1;
if( untilExitFlag )
{
while( is_active() )
{
sys.yield();
mouse.get_event();
disp();
sys.blt_virtual_buf();
music.yield();
detect();
}
}
}
void OptionMenu::disp(int needRepaint)
{
if( !active_flag )
return;
if( needRepaint )
refresh_flag = IGOPTION_ALL;
int i;
Config &tempConfig = config;
// ------- display --------//
if(refresh_flag)
{
if( refresh_flag & IGOPTION_PAGE )
{
image_interface.put_to_buf( &vga_back, "OPTIONS");
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
start_button.paint();
cancel_button.paint();
}
if( refresh_flag & IGOPTION_SE_VOL )
{
se_vol_slide.paint(tempConfig.sound_effect_flag ? percent_to_slide_volume(tempConfig.sound_effect_volume) : 0);
}
if( refresh_flag & IGOPTION_MUSIC_VOL )
{
music_vol_slide.paint(tempConfig.music_flag ? percent_to_slide_volume(tempConfig.wav_music_volume) : 0);
}
if( refresh_flag & IGOPTION_RACE )
{
for( i = 0; i < MAX_RACE; ++i )
race_button[i].paint();
}
if( refresh_flag & IGOPTION_HELP )
{
help_group.paint(tempConfig.help_mode);
}
if( refresh_flag & IGOPTION_NEWS )
{
news_group.paint(1-tempConfig.disp_news_flag);
}
if( refresh_flag & IGOPTION_GAME_SPEED )
{
frame_speed_slide.paint(tempConfig.frame_speed <= 30 ? tempConfig.frame_speed: 31);
}
if( refresh_flag & IGOPTION_SCROLL_SPEED )
{
scroll_speed_slide.paint(tempConfig.scroll_speed);
}
if( refresh_flag & IGOPTION_REPORT )
{
report_group.paint(1-tempConfig.opaque_report);
}
if( refresh_flag & IGOPTION_SHOW_ICON )
{
show_icon_group.paint(1-tempConfig.show_all_unit_icon);
}
if( refresh_flag & IGOPTION_DRAW_PATH )
{
show_path_group.paint(tempConfig.show_unit_path);
}
if( refresh_flag & IGOPTION_MAP_ID )
{
//int x2;
//x2 = font_san.put(521, 64, "Map ID : ", 1);
//x2 = font_san.put(x2, 64, info.random_seed, 1);
}
refresh_flag = 0;
}
}
int OptionMenu::detect()
{
if( !active_flag )
return 0;
Config &tempConfig = config;
int i;
int retFlag1 = 1;
if( se_vol_slide.detect() == 1)
{
tempConfig.sound_effect_flag = se_vol_slide.view_recno > 0;
if( se_vol_slide.view_recno > 0)
tempConfig.sound_effect_volume = slide_to_percent_volume(se_vol_slide.view_recno);
else
tempConfig.sound_effect_volume = 1; // never set sound_effect_volume = 0
audio.set_wav_volume(tempConfig.sound_effect_volume);
// change music volume, sound effect volume may change music volume
if( tempConfig.music_flag )
{
music.change_volume( tempConfig.wav_music_volume);
}
}
else if( music_vol_slide.detect() == 1)
{
tempConfig.music_flag = music_vol_slide.view_recno > 0;
tempConfig.wav_music_volume = slide_to_percent_volume(music_vol_slide.view_recno);
if( tempConfig.music_flag )
{
music.change_volume( tempConfig.wav_music_volume );
}
}
else if( frame_speed_slide.detect() == 1)
{
tempConfig.frame_speed = frame_speed_slide.view_recno <= 30 ? frame_speed_slide.view_recno : 99;
}
else if( scroll_speed_slide.detect() == 1)
{
tempConfig.scroll_speed = scroll_speed_slide.view_recno;
}
else
retFlag1 = 0;
int retFlag2 = 0;
for( i = 0; i < MAX_RACE; ++i )
{
if( race_button[i].detect() )
{
if( config.music_flag )
{
music.play( race_button[i].custom_para.value + 1,
sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
{
// stop any music playing
music.stop();
}
retFlag2 = 1;
}
}
int retFlag3 = 1;
if( help_group.detect() >= 0)
{
tempConfig.help_mode = help_group[help_group()].custom_para.value;
//refresh_flag |= IGOPTION_HELP;
update_flag |= IGOPTION_HELP;
}
else if( news_group.detect() >= 0)
{
tempConfig.disp_news_flag = news_group[news_group()].custom_para.value;
//refresh_flag |= IGOPTION_HELP;
update_flag |= IGOPTION_HELP;
}
else if( report_group.detect() >= 0)
{
tempConfig.opaque_report = report_group[report_group()].custom_para.value;
//refresh_flag |= IGOPTION_REPORT;
update_flag |= IGOPTION_REPORT;
}
else if( show_icon_group.detect() >= 0)
{
tempConfig.show_all_unit_icon = show_icon_group[show_icon_group()].custom_para.value;
//refresh_flag |= IGOPTION_SHOW_ICON;
update_flag |= IGOPTION_SHOW_ICON;
}
else if( show_path_group.detect() >= 0)
{
tempConfig.show_unit_path = show_path_group[show_path_group()].custom_para.value;
//refresh_flag |= IGOPTION_DRAW_PATH;
update_flag |= IGOPTION_DRAW_PATH;
}
else if( start_button.detect(KEY_RETURN) )
{
if( &config != &tempConfig)
config = tempConfig;
exit(1);
if( update_flag )
{
// save config
Config fileConfig;
if( !fileConfig.load("CONFIG.DAT") )
fileConfig.init();
fileConfig.change_preference(tempConfig);
fileConfig.save("CONFIG.DAT");
}
}
else if( cancel_button.detect(KEY_ESC) )
{
config = old_config;
exit(0);
}
else
retFlag3 = 0;
return retFlag1 || retFlag2 || retFlag3;
}
// 0 = abort
// 1 = accept
void OptionMenu::exit(int action)
{
// reflect the effect of config.music_flag, config.wav_music_volume
audio.set_wav_volume(config.sound_effect_volume);
if( config.music_flag )
{
if( music.is_playing() )
{
music.change_volume(config.wav_music_volume);
}
}
else
{
music.stop();
}
// temporary disable active_flag for info.rest_game_scr to call info.disp
active_flag = 0;
info.rest_game_scr();
active_flag = 1;
power.win_opened = 0;
active_flag = 0;
return;
}
void OptionMenu::abort()
{
info.rest_game_scr();
power.win_opened = 0;
active_flag = 0;
}
// ---------- begin of static function disp_virtual_button -----//
static void disp_virtual_button(ButtonCustom *button, int)
{
mouse.hide_area(button->x1, button->y1, button->x2, button->y2);
if( !button->pushed_flag )
{
// copy from back buffer to front buffer
IMGcopy(vga_front.buf_ptr(), vga_front.buf_pitch(),
vga_back.buf_ptr(), vga_back.buf_pitch(),
button->x1, button->y1, button->x2, button->y2 );
}
else
{
// copy from back buffer to front buffer, but the area is
// darkened by 2 scale
IMGcopyRemap(vga_front.buf_ptr(), vga_front.buf_pitch(),
vga_back.buf_ptr(), vga_back.buf_pitch(),
button->x1, button->y1, button->x2, button->y2,
vga.vga_color_table->get_table(-2) );
// draw black frame
if( button->x2-button->x1+1 == BASIC_OPTION_X_SPACE &&
button->y2-button->y1+1 == BASIC_OPTION_HEIGHT )
{
image_interface.put_front(button->x1, button->y1, "BAS_DOWN");
}
else if( button->x2-button->x1+1 == COLOR_OPTION_X_SPACE &&
button->y2-button->y1+1 == COLOR_OPTION_HEIGHT )
{
image_interface.put_front(button->x1, button->y1, "COL_DOWN");
}
else if( button->x2-button->x1+1 == SERVICE_OPTION_X_SPACE &&
button->y2-button->y1+1 == SERVICE_OPTION_HEIGHT )
{
image_interface.put_front(button->x1, button->y1, "NMPG-1BD");
}
}
mouse.show_area();
}
// ---------- end of static function disp_virtual_button -----//
// ---------- begin of static function disp_slide_bar -----//
static void disp_slide_bar(SlideBar *slideBar, int)
{
vga.blt_buf(slideBar->scrn_x1, slideBar->scrn_y1,
slideBar->scrn_x2, slideBar->scrn_y2, 0 );
image_interface.put_front(slideBar->rect_left(), slideBar->scrn_y1, "SLIDBALL");
}
// ---------- end of static function disp_slide_bar -----//
int OptionMenu::slide_to_percent_volume(int slideVolume)
{
switch( slideVolume / 10)
{
case 0:
return slideVolume * 5;
case 1:
case 2:
case 3:
return slideVolume+40;
break;
case 4:
case 5:
return slideVolume/2 + 60;
break;
case 6:
case 7:
case 8:
case 9:
case 10:
return slideVolume/4+75;
break;
default:
err_here();
return slideVolume;
}
}
// slideVolume 0 10 20 30 40 50 60 70 80 90 100
// !----!----!----!----!----!----!----!----!----!----!
// percentVoume 0 50 80 90 100
int OptionMenu::percent_to_slide_volume(int percentVolume)
{
switch(percentVolume/10)
{
case 0:
case 1:
case 2:
case 3:
case 4:
return percentVolume/5;
case 5:
case 6:
case 7:
return percentVolume - 40;
case 8:
return (percentVolume-60) * 2;
case 9:
case 10:
return (percentVolume-75) * 4;
default:
err_here();
return percentVolume;
}
}