/* * 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 : OTUTOR.CPP //Description : Class Tutor #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //---------- define constant ------------// #define TUTOR_DB "TUT_LIST.RES" #define TUTOR_TEXT_RES "TUT_TEXT.RES" #define TUTOR_INTRO_RES "TUT_INTR.RES" //---------- define coordinations ------------// enum { TUTOR_X1 = ZOOM_X1, TUTOR_Y1 = ZOOM_Y1, TUTOR_X2 = ZOOM_X2, TUTOR_Y2 = TUTOR_Y1+120 }; enum { TUTOR_BUTTON_X1 = TUTOR_X2-66, TUTOR_BUTTON_Y1 = TUTOR_Y1+20 }; //-------- Define static vars ----------// static Button button_new_tutor, button_quit_tutor; static Button button_restart, button_prev, button_next; static Button3D button_sample; //------- Begin of function Tutor::Tutor -----------// Tutor::Tutor() { memset( this, 0, sizeof(Tutor) ); } //--------- End of function Tutor::Tutor -----------// //------- Begin of function Tutor::~Tutor -----------// Tutor::~Tutor() { deinit(); } //--------- End of function Tutor::~Tutor -----------// //---------- Begin of function Tutor::init -----------// // // This function must be called after a map is generated. // void Tutor::init() { deinit(); //------- allocate text_block_array ----------// text_block_array = (TutorTextBlock*) mem_add( sizeof(TutorTextBlock) * MAX_TUTOR_TEXT_BLOCK ); //----- open tutorial text resource file -------// String str; str = DIR_RES; str += TUTOR_TEXT_RES; res_tutor_text.init(str, 0); // 0-don't read all into buffer //----- open tutorial introduction resource file -------// str = DIR_RES; str += TUTOR_INTRO_RES; res_tutor_intro.init(str, 0); // 0-don't read all into buffer //------- load database information --------// load_tutor_info(); init_flag=1; } //---------- End of function Tutor::init -----------// //---------- Begin of function Tutor::deinit -----------// void Tutor::deinit() { if( init_flag ) { mem_del(tutor_info_array); tutor_info_array = NULL; mem_del(text_block_array); text_block_array = NULL; if( tutor_text_buf ) { mem_del(tutor_text_buf); tutor_text_buf = NULL; } if( tutor_intro_buf ) { mem_del(tutor_intro_buf); tutor_intro_buf = NULL; } res_tutor_text.deinit(); res_tutor_intro.deinit(); init_flag=0; } } //---------- End of function Tutor::deinit -----------// //------- Begin of function Tutor::load_tutor_info -------// // // Read in information of GOD.DBF into memory array // void Tutor::load_tutor_info() { TutorRec *tutorRec; TutorInfo *tutorInfo; String str; str = DIR_RES; str += TUTOR_DB; Database dbTutor(str, 1); tutor_count = (short) dbTutor.rec_count(); tutor_info_array = (TutorInfo*) mem_add( sizeof(TutorInfo)*tutor_count ); //------ read in tutor information array -------// memset( tutor_info_array, 0, sizeof(TutorInfo) * tutor_count ); for( int i=0 ; icode, tutorRec->code, tutorRec->CODE_LEN ); m.rtrim_fld( tutorInfo->des , tutorRec->des , tutorRec->DES_LEN ); #if(defined(GERMAN) || defined(FRENCH) || defined(SPANISH)) translate.multi_to_win(tutorInfo->des, tutorInfo->DES_LEN); #endif } //--- exclude the Fryhtan and Seat of Power tutorials in the demo ---// #ifdef DEMO tutor_count -= 2; #endif } //--------- End of function Tutor::load_tutor_info ---------// //------------ Begin of function Tutor::load -------------// // // tutorId - id. of the tutorial // void Tutor::load(int tutorId) { cur_tutor_id = tutorId; //------- get the tutor msgs from the resource file -------// int dataSize; File* filePtr = res_tutor_text.get_file( tutor[tutorId]->code, dataSize); if( !filePtr ) // if error getting the tutor resource { err_here(); return; } //------ Open the file and allocate buffer -----// FileTxt fileTxt( filePtr, dataSize ); // initialize fileTxt with an existing file stream if( dataSize > tutor_text_buf_size ) { tutor_text_buf = mem_resize( tutor_text_buf, dataSize ); // allocate a buffer larger than we need for the largest size possible tutor_text_buf_size = dataSize; } //-------- read in tutor info one by one --------// TutorTextBlock* tutorTextBlock = text_block_array; char* textPtr = tutor_text_buf; int readLen, totalReadLen=0; // total length of text read into the tutor_text_buf int loopCount=0; char* tokenStr; text_block_count=0; fileTxt.next_line(); // by pass the first two lines of file description fileTxt.next_line(); while( !fileTxt.is_eof() ) { err_when( loopCount++ > 10000 ); tokenStr = fileTxt.get_token(0); // don't advance the pointer if( !tokenStr ) break; //------ read in the display button code of the tutorial segment -------// if( strcmpi( tokenStr, "Button" ) == 0 ) { fileTxt.get_token(1); // advance the pointer tokenStr = fileTxt.get_token(1); strncpy( tutorTextBlock->button_code, tokenStr, tutorTextBlock->BUTTON_CODE_LEN ); tutorTextBlock->button_code[tutorTextBlock->BUTTON_CODE_LEN] = NULL; } else { tutorTextBlock->button_code[0] = NULL; } //------- read in the tutorial text -------// readLen = fileTxt.read_paragraph(textPtr, tutor_text_buf_size-totalReadLen); tutorTextBlock->text_ptr = textPtr; tutorTextBlock->text_len = readLen; textPtr += readLen; totalReadLen += readLen; err_when( totalReadLen>tutor_text_buf_size ); //----------- next tutor block -------------// fileTxt.next_line(); // pass the page break line text_block_count++; tutorTextBlock++; err_when( text_block_count >= MAX_TUTOR_TEXT_BLOCK ); } cur_text_block_id = 1; last_text_block_id = 0; } //------------- End of function Tutor::load -------------// //------------ Begin of function Tutor::get_intro -------------// // // tutorId - id. of the tutorial // // return: return the introduction text of the tutorial. // char* Tutor::get_intro(int tutorId) { //------- get the tutor msgs from the resource file -------// int dataSize; File* filePtr = res_tutor_intro.get_file( tutor[tutorId]->code, dataSize); if( !filePtr ) // if error getting the tutor resource { err_here(); return NULL; } //------ Open the file and allocate buffer -----// FileTxt fileTxt( filePtr, dataSize ); // initialize fileTxt with an existing file stream if( dataSize > tutor_intro_buf_size ) { tutor_intro_buf = mem_resize( tutor_intro_buf, dataSize ); // allocate a buffer larger than we need for the largest size possible tutor_intro_buf_size = dataSize; } // #### begin Gilbert 23/9 #######// fileTxt.read_paragraph(tutor_intro_buf, tutor_intro_buf_size); // #### end Gilbert 23/9 #######// return tutor_intro_buf; } //------------- End of function Tutor::get_intro -------------// //-------- Begin of function Tutor::select_run_tutor --------// // // inGameCall - whether it's called from the main menu or from in-game tutorial. // void Tutor::select_run_tutor(int inGameCall) { if( inGameCall ) select_tutor(-2); int tutorId = select_tutor(1); if( tutorId > 0 ) run(tutorId, inGameCall); if( inGameCall ) select_tutor(-1); } //--------- End of function Tutor::select_run_tutor ---------// //---------- Begin of function Tutor::run -----------// void Tutor::run(int tutorId, int inGameCall) { //--- don't load pre-saved game when selecting a new tutorial in the game ---// if( !inGameCall ) { String str; str = DIR_TUTORIAL; str += tutor[tutorId]->code; str += ".TUT"; if( m.is_file_exist(str) ) { game_file.load_game(str); } else { str = "TUTORIAL\\STANDARD.TUT"; if( m.is_file_exist(str) ) game_file.load_game(str); } //------ fix firm_build_id problem -----// Firm* firmPtr; for( int i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( firmPtr->firm_id != FIRM_MONSTER ) continue; int monsterId = ((FirmMonster*)firmPtr)->monster_id; firmPtr->firm_build_id = firm_res[FIRM_MONSTER]->get_build_id( monster_res[monsterId]->firm_build_code ); } //----- set the gaming speed to normal -----// sys.set_speed(9, COMMAND_AUTO); } //--------- load the tutorial text ------------// tutor.load(tutorId); game.game_mode = GAME_TUTORIAL; //------------------------------------------// if( !inGameCall ) { battle.run_loaded(); game.deinit(); } } //----------- End of function Tutor::run ------------// //------------ Begin of function Tutor::disp ------------// void Tutor::disp() { vga.use_back(); Vga::opaque_flag = config.opaque_report; vga.d3_panel_down( TUTOR_X1, TUTOR_Y1, TUTOR_X2, TUTOR_Y2 ); Vga::opaque_flag = 0; TutorTextBlock* tutorTextBlock = text_block_array+cur_text_block_id-1; //------- display button bitmap ------// int textX2 = TUTOR_X2-10; if( tutorTextBlock->button_code[0] ) { button_sample.paint( TUTOR_BUTTON_X1, TUTOR_BUTTON_Y1, 'A', tutorTextBlock->button_code ); textX2 = TUTOR_BUTTON_X1-16; } //-------- display tutorial text --------// font_san.put_paragraph( TUTOR_X1+10, TUTOR_Y1+10, textX2, TUTOR_Y2-10, tutorTextBlock->text_ptr, 4 ); //--------- display controls ---------// int x=TUTOR_X1+10, y=TUTOR_Y2-22; #ifdef GERMAN button_new_tutor.paint_text( x, y, "Next Training" ); button_quit_tutor.paint_text( x+120, y, "Quit Training" ); #else button_new_tutor.paint_text( x, y, "Next Training" ); button_quit_tutor.paint_text( x+100, y, "Quit Training" ); #endif //---- display current text block position ----// x += 360; String str; str = cur_text_block_id; str += " / "; str += text_block_count; font_san.put( x, y+3, str ); x += 60; //------- display other controls --------// button_restart.paint_text( x, y, "|<<" ); if( cur_text_block_id > 1 ) button_prev.paint_text( x+45, y, " < " ); if( cur_text_block_id < text_block_count ) button_next.paint_text( x+88, y, " > " ); vga.use_front(); //------ play speech of the tutorial -------// if( last_text_block_id != cur_text_block_id ) { last_text_block_id = cur_text_block_id; play_speech(); } } //------------ End of function Tutor::disp ------------// //----------- Begin of function Tutor::play_speech ------------// void Tutor::play_speech() { if( !sys.dir_tutorial[0] ) return; if( cur_speech_wav_id ) stop_speech(); //---------------------------------// String str; str = sys.dir_tutorial; str += tutor[cur_tutor_id]->code; str += "\\TUT"; if( cur_text_block_id < 10 ) // Add a zero. e.g. "TUT01" str += "0"; str += cur_text_block_id; if( !m.is_file_exist(str) ) return; // ##### begin Gilbert 25/9 ######// cur_speech_wav_id = audio.play_long_wav(str, DEF_REL_VOLUME); // cur_speech_wav_id is the WAV id that is needed for stopping playing of the WAV file // ##### end Gilbert 25/9 ######// } //------------ End of function Tutor::play_speech ------------// //----------- Begin of function Tutor::stop_speech ------------// void Tutor::stop_speech() { audio.stop_long_wav(cur_speech_wav_id); cur_speech_wav_id = 0; } //------------ End of function Tutor::stop_speech ------------// //---------- Begin of function Tutor::detect ----------// int Tutor::detect() { if( button_new_tutor.detect() ) { stop_speech(); select_run_tutor(1); // select and run tutorial, 1-called from in-game, not from the main menu return 1; } if( button_quit_tutor.detect() ) { stop_speech(); game.game_mode = GAME_SINGLE_PLAYER; return 1; } if( button_restart.detect() ) { cur_text_block_id = 1; return 1; } if( cur_text_block_id > 1 && button_prev.detect() ) { prev_text_block(); return 1; } if( cur_text_block_id < text_block_count && button_next.detect() ) { next_text_block(); return 1; } return 0; } //----------- End of function Tutor::detect ------------// //---------- Begin of function Tutor::prev_text_block ----------// void Tutor::prev_text_block() { if( cur_text_block_id > 1 ) cur_text_block_id--; } //----------- End of function Tutor::prev_text_block ------------// //---------- Begin of function Tutor::next_text_block ----------// void Tutor::next_text_block() { if( cur_text_block_id < text_block_count ) cur_text_block_id++; } //----------- End of function Tutor::next_text_block ------------// //---------- Begin of function Tutor::operator[] -----------// TutorInfo* Tutor::operator[](int recNo) { err_when( recNo < 1 || recNo > tutor_count ); return tutor_info_array + recNo - 1; } //----------- End of function Tutor::operator[] ------------//