/*
* 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 : OHELP.CPP
//Description : Object Help
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//---------- Define constant -------------//
#define HELP_BOX_COLOR (VGA_GRAY+5)
#define HELP_INACTIVE_TIME ((float) 0.8) // when the mouse is inactive for one second, display help
enum { HELP_SCR_BUF_WIDTH = 400, // 400
HELP_SCR_BUF_HEIGHT = 200, // 300
HELP_SCR_BUF_SIZE = HELP_SCR_BUF_WIDTH * HELP_SCR_BUF_HEIGHT };
enum { MSG_LINE_SPACE = 4 };
enum { X_MARGIN = 10,
Y_MARGIN = 6 };
enum { MSG_WIN_WIDTH = 390,
MSG_HEAD_HEIGHT = 16 };
//------- Begin of function Help::Help ----------//
Help::Help()
{
memset( this, 0, sizeof(Help) );
help_info_array = (HelpInfo*) mem_add( sizeof(HelpInfo) * MAX_HELP_INFO );
save_scr_x1 = -1;
}
//------- Begin of function Help::Help ----------//
//------- Begin of function Help::~Help ----------//
Help::~Help()
{
deinit();
}
//------- Begin of function Help::~Help ----------//
//------- Begin of function Help::init ----------//
void Help::init(char* resName)
{
String str;
str = DIR_RES;
str += resName;
load( str );
save_scr_buf = mem_add(HELP_SCR_BUF_SIZE);
}
//------- Begin of function Help::init ----------//
//------- Begin of function Help::deinit ----------//
void Help::deinit()
{
if( save_scr_buf )
{
mem_del( save_scr_buf );
save_scr_buf = NULL;
}
if( help_info_array )
{
mem_del( help_info_array );
help_info_array = NULL;
}
if( help_text_buf )
{
mem_del( help_text_buf );
help_text_buf = NULL;
}
}
//------- Begin of function Help::deinit ----------//
//------- Begin of function Help::load ----------//
//
// helpFileName = name of the help file.
//
void Help::load(char* helpFileName)
{
//------ Open the file and allocate buffer -----//
FileTxt fileTxt( helpFileName );
int dataSize = fileTxt.file_size();
if( dataSize > help_text_buf_size )
{
help_text_buf = mem_resize( help_text_buf, dataSize ); // allocate a buffer larger than we need for the largest size possible
help_text_buf_size = dataSize;
}
//-------- read in help info one by one --------//
HelpInfo* iptr = help_info_array;
char* textPtr = help_text_buf;
int readLen, totalReadLen=0; // total length of text read into the help_text_buf
int loopCount=0;
char* tokenStr;
help_info_count=0;
while( !fileTxt.is_eof() )
{
err_when( loopCount++ > 10000 );
tokenStr = fileTxt.get_token(0); // don't advance the pointer
if( !tokenStr )
break;
//--------- if it's a help code ----------//
if( tokenStr[0] >= 'A' && tokenStr[0] <= 'Z' )
{
strncpy( iptr->help_code, tokenStr, iptr->HELP_CODE_LEN );
iptr->help_code[iptr->HELP_CODE_LEN] = NULL;
}
//------ if it's a help area position ------//
else if( tokenStr[0] >= '0' && tokenStr[0] <= '9' )
{
iptr->area_x1 = (short) fileTxt.get_num();
iptr->area_y1 = (short) fileTxt.get_num();
iptr->area_x2 = (short) fileTxt.get_num();
iptr->area_y2 = (short) fileTxt.get_num();
}
else
err_here();
//---------- next line -----------//
fileTxt.next_line();
if( fileTxt.is_eof() )
break;
//--------------------------------------------//
// get help title
//--------------------------------------------//
fileTxt.read_line( iptr->help_title, iptr->HELP_TITLE_LEN );
//---------------------------------------------------------//
// get help description
//---------------------------------------------------------//
readLen = fileTxt.read_paragraph(textPtr, help_text_buf_size-totalReadLen);
iptr->help_text_ptr = textPtr;
iptr->help_text_len = readLen;
textPtr += readLen;
totalReadLen += readLen;
err_when( totalReadLen>help_text_buf_size );
//----------- next help block -------------//
fileTxt.next_line(); // pass the page break line
help_info_count++;
iptr++;
err_when( help_info_count >= MAX_HELP_INFO );
}
}
//--------- End of function Help::load ----------//
//---------- Begin of function Help::save_scr ---------//
//
// Save the specified porton of the screen
//
// x1,y1,x2,y2 = the area of the screen
//
void Help::save_scr(int x1, int y1, int x2, int y2)
{
if( save_scr_x1 >= 0 ) // there is already a screen saved
return;
err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
long saveSize = (long)(x2-x1+1) * (y2-y1+1);
err_when( saveSize > HELP_SCR_BUF_SIZE );
save_scr_x1 = x1;
save_scr_y1 = y1;
save_scr_x2 = x2;
save_scr_y2 = y2;
mouse.hide_area( x1, y1, x2, y2 );
vga_front.read_bitmap( x1, y1, x2, y2, save_scr_buf );
mouse.show_area();
}
//------------ End of function Help::save_scr ---------//
//----------- Begin of function Help::rest_scr --------//
//
// Restore previously saved screen
//
void Help::rest_scr()
{
if( save_scr_x1 < 0 ) // already restored, or not saved yet
return;
err_when( save_scr_x1>save_scr_x2 || save_scr_y1>save_scr_y2 ||
save_scr_x1<0 || save_scr_y1<0 || save_scr_x2>=VGA_WIDTH || save_scr_y2>=VGA_HEIGHT );
// mouse.hide_area( save_scr_x1, save_scr_y1, save_scr_x2, save_scr_y2 );
vga_front.put_bitmap( save_scr_x1, save_scr_y1, save_scr_buf );
sys.blt_virtual_buf();
// mouse.show_area();
mouse.show();
save_scr_x1 = -1; // state that it has been restored.
}
//------------ End of function Help::rest_scr ----------//
//----------- Begin of function Help::disp --------//
//
// Display help message on the given screen location.
//
void Help::disp()
{
//---- first check if we should disp the help now ------//
if( !should_disp() )
{
help_code[0] = NULL; // reset it everytime after displaying, if the mouse is still on the button, help_code will be set again.
custom_help_title[0] = NULL;
return;
}
//-------- button help ---------//
if( help_code[0] )
{
//--------- locate the help and display it ----------//
int i;
HelpInfo* helpInfo = help_info_array;
for( i=0 ; ihelp_code[0] == help_code[0] &&
strcmp( helpInfo->help_code, help_code )==0 )
{
disp_help( help_x, help_y,
helpInfo->help_title, helpInfo->help_text_ptr );
break;
}
}
help_code[0] = NULL; // reset it everytime after displaying, if the mouse is still on the button, help_code will be set again.
}
//-------- custom help ---------//
else if( custom_help_title[0] )
{
disp_help(help_x, help_y, custom_help_title, custom_help_detail);
custom_help_title[0] = NULL;
}
//-------- other interface help ---------//
else
{
//--------- locate the help and display it ----------//
int i;
HelpInfo* helpInfo = help_info_array;
int spotX = mouse.cur_x;
int spotY = mouse.cur_y;
for( i=0 ; i= helpInfo->area_x1 && spotY >= helpInfo->area_y1 &&
spotX <= helpInfo->area_x2 && spotY <= helpInfo->area_y2 )
{
disp_help( (helpInfo->area_x1+helpInfo->area_x2)/2,
(helpInfo->area_y1+helpInfo->area_y2)/2,
helpInfo->help_title, helpInfo->help_text_ptr );
break;
}
}
}
}
//------------ End of function Help::disp ----------//
//---------- Begin of function Help::disp_help ----------//
//
// centerX, centerY - the center position of the help area.
// helpTitle - title of the help
// [char*] helpDetail - detail of the help.
//
void Help::disp_help(int centerX, int centerY, char* helpTitle, char* helpDetail)
{
if( config.help_mode == NO_HELP )
return;
mouse.hide();
//------ calculate the position of the help box ------//
int winWidth, winHeight, dispHelpDetail=0;
if( helpDetail && helpDetail[0] && // with detailed help
config.help_mode == DETAIL_HELP ) // Detailed Help
{
winWidth = font_san.text_width(helpDetail, -1, MSG_WIN_WIDTH-X_MARGIN*2) + X_MARGIN*2;
winHeight = Y_MARGIN*2 + font_san.height() + 8 + font_san.text_height(MSG_LINE_SPACE); // text_width() must be called before calling text_height()
dispHelpDetail = 1;
}
else // Help title only
{
winWidth = font_san.text_width(helpTitle, -1, MSG_WIN_WIDTH-X_MARGIN*2) + X_MARGIN*2;
winHeight = Y_MARGIN*2 + font_san.height();
}
//--- if the text is bigger than one text box can hold, use a scrollable text box ---//
int x1, y1, x2, y2;
if( winWidth * winHeight > HELP_SCR_BUF_SIZE )
{
x1 = max( 2, centerX - HELP_SCR_BUF_WIDTH / 2 );
y1 = max( 2, centerY - HELP_SCR_BUF_HEIGHT / 2 );
x2 = x1 + HELP_SCR_BUF_WIDTH - 1;
y2 = y1 + HELP_SCR_BUF_HEIGHT - 1;
}
else
{
x1 = max( 2, centerX - winWidth / 2 );
y1 = max( 2, centerY - winHeight / 2 );
x2 = x1 + winWidth - 1;
y2 = y1 + winHeight - 1;
}
if( x2 >= VGA_WIDTH )
{
x2 = VGA_WIDTH-10;
x1 = x2-winWidth+1;
}
if( y2 >= VGA_HEIGHT )
{
y2 = VGA_HEIGHT-3;
y1 = y2-winHeight+1;
}
//------------- save the area --------------//
help.save_scr( x1, y1, x2, y2 ); // save the screen to the private buffer in Help
//------- Draw box (and arrow if specified object) ------//
vga_front.bar( x1, y1, x2, y2, V_WHITE );
vga_front.bar( x1, y1, x2, y1+1, HELP_BOX_COLOR ); // Top border
vga_front.bar( x1, y2-1, x2, y2, HELP_BOX_COLOR ); // Bottom border
vga_front.bar( x1, y1, x1+1, y2, HELP_BOX_COLOR ); // Left border
vga_front.bar( x2-1, y1, x2, y2, HELP_BOX_COLOR ); // Right border
//--------- disp help detail -----------//
font_san.put( x1+X_MARGIN, y1+Y_MARGIN, helpTitle );
if( dispHelpDetail )
{
int y = y1 + Y_MARGIN + font_san.height() + 4;
vga_front.bar( x1, y, x2, y+1, HELP_BOX_COLOR ); // line between description and help text
font_san.put_paragraph( x1+X_MARGIN, y+4, x2-X_MARGIN, y2-Y_MARGIN, helpDetail, MSG_LINE_SPACE );
}
if( sys.debug_session )
sys.blt_virtual_buf();
//--- in a single player game, pause the game when a help message is disp_helplayed ---//
while( help.should_disp() )
{
sys.yield();
music.yield();
mouse.get_event();
}
help.rest_scr();
}
//--------- End of function Help::disp_help ----------//
//--------- Begin of function Help::should_disp --------//
//
int Help::should_disp()
{
if( config.help_mode == NO_HELP )
return 0;
if( VBrowse::press_record )
return 0;
if( last_mouse_x==mouse.cur_x && last_mouse_y==mouse.cur_y &&
!mouse.left_press && !mouse.right_press && !mouse.any_click(2) )
{
if( m.get_time() >= mouse_still_time + HELP_INACTIVE_TIME * 1000 )
{
return 1;
}
}
else
{
last_mouse_x = mouse.cur_x;
last_mouse_y = mouse.cur_y;
mouse_still_time = m.get_time();
}
return 0;
}
//---------- End of function Help::should_disp ---------//
//--------- Begin of function Help::set_help --------//
//
void Help::set_help(int x1, int y1, int x2, int y2, char* helpCode)
{
err_when( strlen(helpCode) > 8 );
if( !mouse.in_area(x1, y1, x2, y2) )
return;
strcpy( help_code, helpCode );
help_x = (x1+x2)/2;
help_y = (y1+y2)/2;
}
//---------- End of function Help::set_help ---------//
//--------- Begin of function Help::set_unit_help --------//
//
void Help::set_unit_help(int unitId, int rankId, int x1, int y1, int x2, int y2)
{
if( !mouse.in_area(x1, y1, x2, y2) )
return;
//-------- compose the help string --------//
static String str;
#if(defined(SPANISH) || defined(FRENCH))
str = "";
if( rankId==RANK_KING )
str = translate.process("King ");
else if( rankId==RANK_GENERAL )
str = translate.process("General ");
str += unit_res[unitId]->name;
#else
str = unit_res[unitId]->name;
#if( !defined(GERMAN) && !defined(FRENCH) && !defined(SPANISH) ) // english
if( rankId>=RANK_GENERAL && unitId==UNIT_MAYA )
str += "n"; // "Mayan"
#endif
if( rankId==RANK_KING )
{
str += " ";
str += translate.process( "King" );
}
else if( rankId==RANK_GENERAL )
{
str += " ";
str += translate.process( "General" );
}
#endif
set_custom_help( x1, y1, x2, y2, str );
}
//---------- End of function Help::set_unit_help ---------//
//--------- Begin of function Help::set_custom_help --------//
//
// x1, y1, x2, y2 - the coordination of the help
// helpTitle - the title of the help
// [char*] helpDetail - the detailed text of the help
//
void Help::set_custom_help(int x1, int y1, int x2, int y2, char* helpTitle, char* helpDetail)
{
if( !mouse.in_area(x1, y1, x2, y2) )
return;
help_x = (x1+x2)/2;
help_y = (y1+y2)/2;
strncpy( custom_help_title, helpTitle, CUSTOM_HELP_TITLE_LEN );
custom_help_title[CUSTOM_HELP_TITLE_LEN] = NULL;
if( helpDetail )
{
strncpy( custom_help_detail, helpDetail, CUSTOM_HELP_DETAIL_LEN );
custom_help_detail[CUSTOM_HELP_DETAIL_LEN] = NULL;
}
else
{
custom_help_detail[0] = NULL;
}
}
//---------- End of function Help::set_custom_help ---------//