123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OTUTOR.CPP
- //Description : Class Tutor
- #include <OVGA.h>
- #include <OSYS.h>
- #include <OAUDIO.h>
- #include <OBATTLE.h>
- #include <OFONT.h>
- #include <OF_MONS.h>
- #include <OMONSRES.h>
- #include <OIMGRES.h>
- #include <OBUTTON.h>
- #include <OBUTT3D.h>
- #include <OGFILE.h>
- #include <OGAME.h>
- #include <OGAMESET.h>
- #include <OWORLD.h>
- #include <OFILETXT.h>
- #include <OTUTOR.h>
- //---------- 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 ; i<tutor_count ; i++ )
- {
- tutorRec = (TutorRec*) dbTutor.read(i+1);
- tutorInfo = tutor_info_array+i;
- m.rtrim_fld( tutorInfo->code, 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 -------------//
- //
- // <int> 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 -------------//
- //
- // <int> tutorId - id. of the tutorial
- //
- // return: <char*> 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 --------//
- //
- // <int> 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[] ------------//
|