bggame.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2000-2004  The Exult Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include "SDL_events.h"
00024 
00025 #include <typeinfo>
00026 #include "files/U7file.h"
00027 #include "files/utils.h"
00028 #include "flic/playfli.h"
00029 #include "gamewin.h"
00030 #include "Audio.h"
00031 #include "bggame.h"
00032 #include "sigame.h"
00033 #include "palette.h"
00034 #include "databuf.h"
00035 #include "font.h"
00036 #include "txtscroll.h"
00037 #include "data/exult_bg_flx.h"
00038 #include "exult.h"
00039 #include "Configuration.h"
00040 #include "shapeid.h"
00041 
00042 #ifndef ALPHA_LINUX_CXX
00043 #  include <cctype>
00044 #  include <cstring>
00045 #endif
00046 
00047 #ifndef UNDER_CE
00048 using std::abs;
00049 using std::rand;
00050 using std::strchr;
00051 using std::strlen;
00052 using std::toupper;
00053 #endif
00054 
00055 enum
00056 {
00057   ultima_text_shp = 0x0D,
00058   butterfly_shp = 0x0E,
00059   lord_british_shp = 0x11,
00060   trees_shp = 0x12,
00061   
00062   guardian_mouth_shp = 0x1E,
00063   guardian_forehead_shp = 0x1F,
00064   guardian_eyes_shp = 0x20
00065 };
00066 
00067 enum
00068 {
00069   bird_song_midi = 0,
00070   home_song_midi = 1,
00071   guardian_midi = 2,
00072   menu_midi = 3,
00073   credits_midi = 4,
00074   quotes_midi = 5
00075 };
00076 
00077 BG_Game::BG_Game()
00078   : shapes(ENDSHAPE_FLX)
00079 {
00080   add_shape("gumps/check",2);
00081   add_shape("gumps/fileio",3);
00082   add_shape("gumps/fntext",4);
00083   add_shape("gumps/loadbtn",5);
00084   add_shape("gumps/savebtn",6);
00085   add_shape("gumps/halo",7);
00086   add_shape("gumps/disk",24);
00087   add_shape("gumps/heart",25);
00088   add_shape("gumps/statatts",28);
00089   add_shape("gumps/musicbtn",29);
00090   add_shape("gumps/speechbtn",30);
00091   add_shape("gumps/soundbtn",31); 
00092   add_shape("gumps/spellbook",43);
00093   add_shape("gumps/statsdisplay",47);
00094   add_shape("gumps/combat",46);
00095   add_shape("gumps/quitbtn",56);
00096   add_shape("gumps/yesnobox",69);
00097   add_shape("gumps/yesbtn",70);
00098   add_shape("gumps/nobtn",71);
00099   add_shape("gumps/book",32);
00100   add_shape("gumps/scroll",55);
00101   add_shape("gumps/combatmode",12);
00102   add_shape("gumps/slider",14);
00103   add_shape("gumps/slider_diamond",15);
00104   add_shape("gumps/slider_right",16);
00105   add_shape("gumps/slider_left",17);
00106 
00107   add_shape("gumps/box", 0);
00108   add_shape("gumps/crate", 1);
00109   add_shape("gumps/barrel", 8);
00110   add_shape("gumps/bag", 9);
00111   add_shape("gumps/backpack", 10);
00112   add_shape("gumps/basket", 11);
00113   add_shape("gumps/chest", 22);
00114   add_shape("gumps/shipshold", 26);
00115   add_shape("gumps/drawer", 27);
00116   add_shape("gumps/woodsign", 49);
00117   add_shape("gumps/tombstone", 50);
00118   add_shape("gumps/goldsign", 51);
00119   add_shape("gumps/body", 53);
00120 
00121   add_shape("sprites/map", 22);
00122   add_shape("sprites/cheatmap", 12);
00123 
00124   add_resource("files/shapes/count", 0, 9);
00125   add_resource("files/shapes/0", "<STATIC>/shapes.vga", 0);
00126   add_resource("files/shapes/1", "<STATIC>/faces.vga", 0);
00127   add_resource("files/shapes/2", "<STATIC>/gumps.vga", 0);
00128   add_resource("files/shapes/3", "<STATIC>/sprites.vga", 0);
00129   add_resource("files/shapes/4", MAINSHP_FLX, 0);
00130   add_resource("files/shapes/5", "<STATIC>/endshape.flx", 0);
00131   add_resource("files/shapes/6", "<STATIC>/fonts.vga", 0);
00132   add_resource("files/shapes/7", "<DATA>/exult.flx", 0);
00133   add_resource("files/shapes/8", "<DATA>/exult_bg.flx", 0);
00134 
00135   add_resource("files/gameflx", "<DATA>/exult_bg.flx", 0);
00136 
00137   add_resource("config/defaultkeys", "<DATA>/exult_bg.flx", 13);
00138 
00139   add_resource("palettes/count", 0, 18);
00140   add_resource("palettes/0", PALETTES_FLX, 0);
00141   add_resource("palettes/1", PALETTES_FLX, 1);
00142   add_resource("palettes/2", PALETTES_FLX, 2);
00143   add_resource("palettes/3", PALETTES_FLX, 3);
00144   add_resource("palettes/4", PALETTES_FLX, 4);
00145   add_resource("palettes/5", PALETTES_FLX, 5);
00146   add_resource("palettes/6", PALETTES_FLX, 6);
00147   add_resource("palettes/7", PALETTES_FLX, 7);
00148   add_resource("palettes/8", PALETTES_FLX, 8);
00149   add_resource("palettes/9", PALETTES_FLX, 10);
00150   add_resource("palettes/10", PALETTES_FLX, 11);
00151   add_resource("palettes/11", PALETTES_FLX, 12);
00152   add_resource("palettes/12", "<STATIC>/intropal.dat", 0);
00153   add_resource("palettes/13", "<STATIC>/intropal.dat", 1);
00154   add_resource("palettes/14", "<STATIC>/intropal.dat", 2);
00155   add_resource("palettes/15", "<STATIC>/intropal.dat", 3);
00156   add_resource("palettes/16", "<STATIC>/intropal.dat", 4);
00157   add_resource("palettes/17", "<STATIC>/intropal.dat", 5);
00158   
00159   add_resource("xforms/count", 0, 20);
00160   add_resource("xforms/0", "<STATIC>/xform.tbl", 0);
00161   add_resource("xforms/1", "<STATIC>/xform.tbl", 1);
00162   add_resource("xforms/2", "<STATIC>/xform.tbl", 2);
00163   add_resource("xforms/3", "<STATIC>/xform.tbl", 3);
00164   add_resource("xforms/4", "<STATIC>/xform.tbl", 4);
00165   add_resource("xforms/5", "<STATIC>/xform.tbl", 5);
00166   add_resource("xforms/6", "<STATIC>/xform.tbl", 6);
00167   add_resource("xforms/7", "<STATIC>/xform.tbl", 7);
00168   add_resource("xforms/8", "<STATIC>/xform.tbl", 8);
00169   add_resource("xforms/9", "<STATIC>/xform.tbl", 9);
00170   add_resource("xforms/10", "<STATIC>/xform.tbl", 10);
00171   add_resource("xforms/11", "<STATIC>/xform.tbl", 11);
00172   add_resource("xforms/12", "<STATIC>/xform.tbl", 12);
00173   add_resource("xforms/13", "<STATIC>/xform.tbl", 13);
00174   add_resource("xforms/14", "<STATIC>/xform.tbl", 14);
00175   add_resource("xforms/15", "<STATIC>/xform.tbl", 15);
00176   add_resource("xforms/16", "<STATIC>/xform.tbl", 16);
00177   add_resource("xforms/17", "<STATIC>/xform.tbl", 17);
00178   add_resource("xforms/18", "<STATIC>/xform.tbl", 18);
00179   add_resource("xforms/19", "<STATIC>/xform.tbl", 19);
00180   
00181   fontManager.add_font("MENU_FONT", MAINSHP_FLX, 9, 1);
00182   fontManager.add_font("END2_FONT", ENDGAME, 4, -1);
00183   fontManager.add_font("END3_FONT", ENDGAME, 5, -2);
00184   fontManager.add_font("NORMAL_FONT", FONTS_VGA, 0, -1);
00185 }
00186 
00187 BG_Game::~BG_Game()
00188 {
00189 }
00190 
00191 class UserSkipException : public UserBreakException
00192 {
00193 };
00194 
00195 
00196 #define WAITDELAY(x) switch(wait_delay(x)) { \
00197       case 1: throw UserBreakException(); break; \
00198       case 2: throw UserSkipException(); break; \
00199       }
00200 
00201 #define WAITDELAYCYCLE(x) switch (wait_delay((x), 16, 78)) { \
00202       case 1: throw UserBreakException(); break; \
00203       case 2: throw UserSkipException(); break; \
00204       }
00205 
00206 #define WAITDELAYCYCLE2(x) switch (wait_delay((x), 250, 5)) { \
00207       case 1: throw UserBreakException(); break; \
00208       case 2: throw UserSkipException(); break; \
00209       }
00210 
00211 #define WAITDELAYCYCLE3(x) switch (wait_delay((x), 240, 15)) { \
00212       case 1: throw UserBreakException(); break; \
00213       case 2: throw UserSkipException(); break; \
00214       }
00215 
00216 void BG_Game::play_intro()
00217 {
00218   gwin->clear_screen(true);
00219 
00220   Audio::get_ptr()->stop_music();
00221 
00222   // TODO: check/fix other resolutions
00223 
00224   // these backups store the area under the guardian shapes being drawn
00225   // the cbackups are 'clean' backups, ie. just background
00226   // the others may have other shapes on them, if those are static
00227   Image_buffer *backup, *backup2, *backup3;
00228   Image_buffer *cbackup, *cbackup2, *cbackup3;
00229 
00230   backup = backup2 = backup3 = 0;
00231   cbackup = cbackup2 = cbackup3 = 0;
00232 
00233   try
00234   {
00235     /********************************************************************
00236      Lord British Presents
00237     ********************************************************************/
00238     
00239     scene_lord_british();
00240 
00241     /********************************************************************
00242      Ultima VII logo w/Trees
00243     ********************************************************************/
00244 
00245     scene_butterfly();
00246 
00247     /********************************************************************
00248      Enter guardian
00249      TODO: reduce sudden facial movements in speech
00250     ********************************************************************/
00251     
00252     scene_guardian();
00253 
00254     // TODO: transition (zoom out to PC) scene missing
00255 
00256     /********************************************************************
00257      PC screen
00258     ********************************************************************/
00259 
00260     scene_desk();
00261 
00262     /********************************************************************
00263      The Moongate
00264     ********************************************************************/
00265     
00266     scene_moongate();
00267   }
00268   catch(const UserBreakException &x)
00269   {
00270     // Waste disposal
00271     FORGET_OBJECT(backup); FORGET_OBJECT(backup2); FORGET_OBJECT(backup3);
00272     FORGET_OBJECT(cbackup); FORGET_OBJECT(cbackup2); FORGET_OBJECT(cbackup3);
00273   }
00274   
00275   // Fade out the palette...
00276   pal->fade_out(c_fade_out_time);
00277   
00278   // ... and clean the screen.
00279   gwin->clear_screen(true);
00280   
00281   // Stop all audio output
00282   Audio::get_ptr()->cancel_streams();
00283 }
00284 
00285 void BG_Game::scene_lord_british()
00286 {
00287   Font *font = fontManager.get_font("END2_FONT");
00288 
00289   const char *txt_msg[] = { "with help from",
00290       "The Exult Team"};
00291 
00292   // Lord British presents...  (sh. 0x11)
00293   pal->load("<STATIC>/intropal.dat",3);
00294   sman->paint_shape(topx,topy,shapes.get_shape(lord_british_shp,0));
00295   
00296   // insert our own intro text
00297   font->center_text(ibuf, centerx, centery+50, txt_msg[0]);
00298   font->center_text(ibuf, centerx, centery+65, txt_msg[1]);
00299 
00300   pal->fade_in(c_fade_in_time);
00301   if(1 == wait_delay(2000))
00302     throw UserBreakException();
00303   pal->fade_out(c_fade_out_time);
00304   gwin->clear_screen(true);
00305 }
00306 
00307 
00308 #define BUTTERFLY_FRAME_DURATION  16
00309 
00310 #define BUTTERFLY_SUB_FRAMES  3
00311 
00312 #define BUTTERFLY(x,y,frame,delay)  do {  \
00313     win->get(backup, topx + (x) - butterfly->get_xleft(), \
00314         topy + (y) - butterfly->get_yabove());  \
00315     sman->paint_shape(topx + x, topy + y, shapes.get_shape(butterfly_shp, frame));  \
00316     win->show();  \
00317     WAITDELAY(delay); \
00318     win->put(backup, topx + (x) - butterfly->get_xleft(), \
00319         topy + (y) - butterfly->get_yabove());  \
00320     } while(0)
00321 
00322 #define BUTTERFLY_FLAP()  do {  \
00323       if ((rand() % 5)<4) { \
00324         if (frame == 3) \
00325           dir = -1; \
00326         else if (frame == 0)  \
00327           dir = +1; \
00328         frame += dir; \
00329       } } while(0)
00330 
00331 static int butterfly_x[] =
00332 {
00333   6,18,30,41,52,62,70,78,86,95,
00334   104,113,122,132,139,146,151,155,157,158,
00335   157,155,151,146,139,132,124,116,108,102,
00336   96,93,93,93,95,99,109,111,118,125,
00337   132,140,148,157,164,171,178,184,190,196,
00338   203,211,219,228,237,246,254,259,262,264,
00339   265,265,263,260,256,251,245,239,232,226,
00340   219,212,208,206,206,209,212,216,220,224,
00341   227,234,231,232,233,233,233,233,234,236,
00342   239,243,247,250,258,265
00343 };
00344 
00345 static int butterfly_y[] =
00346 {
00347   155,153,151,150,149,148,148,148,148,149,
00348   150,150,150,149,147,142,137,131,125,118,
00349   110,103,98,94,92,91,91,91,92,95,
00350   99,104,110,117,123,127,131,134,135,135,
00351   135,135,135,134,132,129,127,123,119,115,
00352   112,109,104,102,101,102,109,109,114,119,
00353   125,131,138,144,149,152,156,158,159,159,
00354   158,155,150,144,137,130,124,118,112,105,
00355   99,93,86,80,73,66,59,53,47,42,
00356   38,35,32,29,26,25
00357 };
00358 
00359 static const int butterfly_num_coords = sizeof(butterfly_x)/sizeof(int);
00360 
00361 static int butterfly_end_frames[] = { 3, 4, 3, 4, 3, 2, 1, 0 };
00362 static int butterfly_end_delay[] = { 167, 416, 250, 416, 416, 416, 416, 333 };
00363 
00364 
00365 void BG_Game::scene_butterfly()
00366 {
00367   Font *font = fontManager.get_font("END2_FONT");
00368   Image_buffer *backup = 0;
00369   Shape_frame *butterfly = 0;
00370   const char *txt_msg = "Driven by Exult";
00371   int i, j, frame, dir;
00372   
00373   try
00374   {
00375     pal->load("<STATIC>/intropal.dat",4);
00376 
00377     // Load the butterfly shape
00378     butterfly = shapes.get_shape(butterfly_shp,0);
00379     backup = win->create_buffer(butterfly->get_width(), butterfly->get_height());
00380     
00381     // Start playing the birdsongs while still faded out
00382     play_midi(bird_song_midi);
00383 
00384     // trees with "Ultima VII" on top of 'em
00385     sman->paint_shape(topx,topy,shapes.get_shape(trees_shp,0));
00386     sman->paint_shape(topx+160,topy+50,shapes.get_shape(ultima_text_shp,0));
00387     
00388     // again display our own text
00389     font->center_text(ibuf, centerx, centery+50, txt_msg);
00390 
00391     // Keep it dark for some more time, playing the music 
00392     WAITDELAY(3500);
00393 
00394     // Finally fade in
00395     pal->fade_in(c_fade_in_time);
00396     WAITDELAY(12500);
00397 
00398     // clear 'Exult' text
00399     sman->paint_shape(topx,topy,shapes.get_shape(trees_shp,0));
00400     sman->paint_shape(topx+160,topy+50,shapes.get_shape(ultima_text_shp,0));
00401     win->show();
00402 
00403     //
00404     // Move the butterfly along its path
00405     //
00406     frame = 0;
00407     Sint32 delay = BUTTERFLY_FRAME_DURATION;
00408     Sint32 ticks = SDL_GetTicks();
00409     for(i=0; i < butterfly_num_coords-1; ++i)
00410     {
00411       for(j=0; j < BUTTERFLY_SUB_FRAMES; ++j)
00412       {
00413 
00414         ticks = SDL_GetTicks();
00415         int x = butterfly_x[i] + j*(butterfly_x[i+1] - butterfly_x[i])/BUTTERFLY_SUB_FRAMES;
00416         int y = butterfly_y[i] + j*(butterfly_y[i+1] - butterfly_y[i])/BUTTERFLY_SUB_FRAMES;
00417         BUTTERFLY(x, y, frame, delay);
00418 
00419         // Flap the wings; but not always, so that the butterfly "glides" from time to time
00420         BUTTERFLY_FLAP();
00421 
00422         // Calculate the difference between the time we wanted to spent and the time
00423         // we actually spent; then adjust 'delay' accordingly
00424         ticks = SDL_GetTicks() - ticks;
00425         delay = (delay + (2*BUTTERFLY_FRAME_DURATION - ticks)) / 2;
00426         
00427         // ... but maybe we also have to skip frames..
00428         if( delay < 0 )
00429         {
00430           // Calculate how many frames we should skip
00431           int frames_to_skip = (-delay) / BUTTERFLY_FRAME_DURATION + 1;
00432           int new_index = i*BUTTERFLY_SUB_FRAMES + j + frames_to_skip;
00433           i = new_index / BUTTERFLY_SUB_FRAMES;
00434           j = new_index % BUTTERFLY_SUB_FRAMES;
00435           
00436           // Did we skip over the end?
00437           if ( i >= butterfly_num_coords-1 )
00438             break;
00439 
00440           while(frames_to_skip--)
00441             BUTTERFLY_FLAP();
00442 
00443           delay = 0;
00444         }
00445       }
00446     }
00447 
00448     // Finally, let it flutter a bit on the end spot
00449     for(i=0; i<8; i++) {
00450       BUTTERFLY(butterfly_x[butterfly_num_coords-1],
00451             butterfly_y[butterfly_num_coords-1],
00452             butterfly_end_frames[i],
00453             butterfly_end_delay[i]);
00454     }
00455     
00456     WAITDELAY(2000);
00457     
00458     // Wait till the music finished playing
00459     while(Audio::get_ptr()->is_track_playing(bird_song_midi))
00460       WAITDELAY(20);
00461   }
00462   catch(const UserSkipException &x)
00463   {
00464   }
00465 }
00466 
00467 #define FLASH_SHAPE(x,y,shape,frame, delay) do {  \
00468     sman->paint_shape(x,y,shapes.get_shape(shape,frame)); \
00469     win->show();  \
00470     WAITDELAYCYCLE(delay);  \
00471     win->put(backup,(x)-s->get_xleft(),(y)-s->get_yabove());  \
00472     } while(0)
00473 
00474 #define EYES_DIST   12
00475 #define FORHEAD_DIST  49
00476 
00477 void BG_Game::scene_guardian()
00478 {
00479   Image_buffer *backup = 0, *backup2 = 0, *backup3 = 0;
00480   Image_buffer *cbackup = 0, *cbackup2 = 0, *cbackup3 = 0;
00481   Image_buffer *plasma;
00482   char *txt = 0;
00483 
00484   try
00485   {
00486     char *txt_ptr, *txt_end, *next_txt;
00487     Shape_frame *s, *s2, *s3;
00488     Uint32 ticks;
00489     int i;
00490 
00491     // Start background music
00492     play_midi(guardian_midi);
00493     
00494     // create buffer containing a blue 'plasma' screen
00495     plasma = win->create_buffer(gwin->get_width(),
00496               gwin->get_height());
00497     gwin->plasma(gwin->get_width(), gwin->get_height(), 0, 0, 16, 16+76);
00498     win->get(plasma, 0, 0);
00499 
00500     pal->load("<STATIC>/intropal.dat",2);
00501     pal->set_color(1,0,0,0); //UGLY hack... set font background to black
00502     pal->apply();
00503 
00504     //play static SFX
00505     Audio::get_ptr()->play_sound_effect(115, MIX_MAX_VOLUME, 0, 0);
00506 
00507     //TODO: timing?
00508     win->show();
00509     WAITDELAYCYCLE(100);
00510     
00511     //
00512     // Show some "static" alternating with the blue plasma
00513     //
00514     ticks = SDL_GetTicks();
00515     while(1)
00516     {
00517       win->get_ibuf()->fill_static(0, 7, 15);
00518       win->show();
00519       WAITDELAY(0);
00520       if (SDL_GetTicks() > ticks + 400)
00521         break;
00522     }
00523 
00524     win->put(plasma,0,0); win->show();
00525     WAITDELAYCYCLE(100);
00526 
00527     ticks = SDL_GetTicks();
00528     while(1)
00529     {
00530       win->get_ibuf()->fill_static(0, 7, 15);
00531       win->show();
00532       WAITDELAY(0);
00533       if (SDL_GetTicks() > ticks + 200)
00534         break;
00535     }
00536 
00537     win->put(plasma,0,0); win->show();
00538     WAITDELAYCYCLE(200);
00539 
00540     ticks = SDL_GetTicks();
00541     while(1)
00542     {
00543       win->get_ibuf()->fill_static(0, 7, 15);
00544       win->show();
00545       WAITDELAY(0);
00546       if (SDL_GetTicks() > ticks + 100)
00547         break;
00548     }
00549     
00550     win->put(plasma,0,0); win->show();
00551 
00552     FORGET_OBJECT(plasma);
00553 
00554     
00555     //
00556     // First 'popup' (sh. 0x21)
00557     //
00558     s = shapes.get_shape(0x21, 0);
00559     backup = win->create_buffer(s->get_width(), s->get_height());
00560     win->get(backup, centerx-53-s->get_xleft(), centery-68-s->get_yabove());
00561     for(i=8; i>=-8; i--)
00562     {
00563       FLASH_SHAPE(centerx-53, centery-68, 0x21, 1+abs(i),70);
00564     }
00565     FORGET_OBJECT(backup);
00566     WAITDELAYCYCLE(800);
00567 
00568 
00569     //
00570     // Second 'popup' (sh. 0x22)
00571     //
00572     s = shapes.get_shape(0x22, 0);
00573     backup = win->create_buffer(s->get_width(), s->get_height());
00574     win->get(backup, centerx - s->get_xleft(), centery-45 - s->get_yabove());
00575     for(i=9; i>=-9; i--)
00576     {
00577       FLASH_SHAPE(centerx, centery-45, 0x22, 9-abs(i),70);
00578     }
00579     FORGET_OBJECT(backup);
00580     WAITDELAYCYCLE(800);
00581 
00582 
00583     //
00584     // Successful 'popup' (sh. 0x23)
00585     //
00586     s = shapes.get_shape(0x23, 0);
00587     backup = win->create_buffer(s->get_width(), s->get_height());
00588     cbackup = win->create_buffer(s->get_width(), s->get_height());
00589 
00590     win->get(cbackup, centerx - s->get_xleft(), centery - s->get_yabove());
00591     sman->paint_shape(centerx,centery,s); // frame 0 is static background
00592     win->get(backup, centerx- s->get_xleft(), centery- s->get_yabove());
00593     for(i=1; i<16; i++)
00594     {
00595       FLASH_SHAPE(centerx, centery, 0x23, i,70);
00596     }
00597     
00598     win->put(cbackup, centerx - s->get_xleft(), centery - s->get_yabove());
00599     FORGET_OBJECT(backup);
00600     FORGET_OBJECT(cbackup);
00601 
00602 
00603     //
00604     // Actual appearance
00605     //
00606 
00607 
00608     // mouth
00609     s = shapes.get_shape(guardian_mouth_shp,0);
00610     backup = win->create_buffer(s->get_width(), s->get_height());
00611     cbackup = win->create_buffer(s->get_width(), s->get_height());
00612     win->get(cbackup, centerx - s->get_xleft(), centery - s->get_yabove());
00613     sman->paint_shape(centerx,centery,s); // frame 0 is background
00614     win->get(backup, centerx - s->get_xleft(), centery - s->get_yabove());
00615     // eyes
00616     s2 = shapes.get_shape(guardian_eyes_shp,0);
00617     backup2 = win->create_buffer(s2->get_width(), s2->get_height());
00618     cbackup2 = win->create_buffer(s2->get_width(), s2->get_height());
00619     win->get(cbackup2, centerx - s2->get_xleft(),
00620        centery-EYES_DIST - s2->get_yabove());
00621     sman->paint_shape(centerx,centery-EYES_DIST,s2); // frame 0 is background
00622     win->get(backup2, centerx - s2->get_xleft(),
00623        centery-EYES_DIST - s2->get_yabove());
00624     // forehead
00625     s3 = shapes.get_shape(guardian_forehead_shp,0);
00626     cbackup3 = win->create_buffer(s3->get_width(), s3->get_height());
00627     win->get(cbackup3, centerx - s3->get_xleft(),
00628        centery-FORHEAD_DIST - s3->get_yabove());
00629           sman->paint_shape(centerx,centery-FORHEAD_DIST,s3); // forehead isn't animated
00630 
00631     // prepare Guardian speech
00632     Font *font = fontManager.get_font("END3_FONT");
00633     U7object textobj(MAINSHP_FLX, 0x0D);
00634     size_t txt_len;
00635     next_txt = txt_ptr = txt = textobj.retrieve(txt_len);
00636     if (Audio::get_ptr()->is_speech_enabled())
00637       Audio::get_ptr()->playfile(INTROSND,false);
00638     int txt_height = font->get_text_height();
00639     int txt_ypos = gwin->get_height()-txt_height-16;
00640 
00641     // backup text area
00642     backup3 = win->create_buffer(gwin->get_width(),txt_height);
00643     win->get(backup3, 0, txt_ypos);
00644 
00645     int speech_delay[] = { 29, 71, 59, 47, 47, 62, 79, 
00646                55, 90, 104, 80, 65, 55, 120 };
00647     // start speech
00648     for(int speech_item=0; speech_item<14; speech_item++)
00649     {
00650       unsigned long ticks = SDL_GetTicks();
00651       unsigned long end_ticks = ticks+speech_delay[speech_item]*50;
00652       i=0;
00653       do
00654       {
00655         // convoluted mess to get eye movement acceptable
00656         int eye_frame = 1 + 3*((i/12) % 4) + ((i%50>47&&(i/12)%4!=3)?i%50-47:0);
00657         sman->paint_shape(centerx,centery-EYES_DIST,
00658             shapes.get_shape(guardian_eyes_shp, eye_frame));
00659     
00660         sman->paint_shape(centerx,centery,
00661               shapes.get_shape(guardian_mouth_shp,1 + i % 13));
00662     
00663         if (i == 0)
00664         {
00665           txt_ptr = next_txt;
00666           txt_end = strchr(txt_ptr, '\r');
00667           *txt_end = '\0';
00668           next_txt = txt_end+2;
00669         }
00670 
00671         font->center_text(win->get_ib8(), centerx, txt_ypos, txt_ptr);
00672     
00673         win->show();
00674         WAITDELAYCYCLE(50);
00675     
00676         win->put(backup3, 0, txt_ypos);
00677         win->put(backup, centerx - s->get_xleft(),
00678                centery - s->get_yabove());
00679         win->put(backup2, centerx - s2->get_xleft(),
00680                centery-EYES_DIST - s2->get_yabove());
00681         ticks = SDL_GetTicks();
00682         ++i;
00683       } while (ticks<end_ticks);
00684     }
00685 
00686     win->put(backup3, 0, txt_ypos);
00687     win->put(cbackup, centerx - s->get_xleft(), centery - s->get_yabove());
00688     win->put(cbackup2, centerx - s2->get_xleft(), 
00689        centery-EYES_DIST - s2->get_yabove());
00690     win->put(cbackup3, centerx - s3->get_xleft(),
00691        centery-FORHEAD_DIST - s3->get_yabove());
00692     
00693     FORGET_ARRAY(txt);
00694     FORGET_OBJECT(backup);
00695     FORGET_OBJECT(backup2);
00696     FORGET_OBJECT(backup3);
00697     FORGET_OBJECT(cbackup);
00698     FORGET_OBJECT(cbackup2);
00699     FORGET_OBJECT(cbackup3);
00700 
00701     // G. disappears again (sp. 0x23 again)
00702     s = shapes.get_shape(0x23, 0);
00703     backup = win->create_buffer(s->get_width(), s->get_height());
00704     cbackup = win->create_buffer(s->get_width(), s->get_height());
00705     win->get(cbackup, centerx- s->get_xleft(), centery- s->get_yabove());
00706     sman->paint_shape(centerx,centery,s); // frame 0 is background
00707     win->get(backup, centerx - s->get_xleft(), centery - s->get_yabove());
00708     for(i=15; i>0; i--)
00709     {
00710       FLASH_SHAPE(centerx, centery, 0x23, i, 70);
00711     }
00712     win->put(cbackup, centerx- s->get_xleft(), centery- s->get_yabove());
00713     FORGET_OBJECT(backup);
00714     FORGET_OBJECT(cbackup);
00715 
00716     win->show();
00717     WAITDELAYCYCLE(1000);
00718     
00719     Audio::get_ptr()->stop_music();
00720     
00721     //
00722     // White dot
00723     //
00724     s = shapes.get_shape(0x14, 0);
00725     backup = win->create_buffer(s->get_width()+2, s->get_height()+2);
00726     win->get(backup, centerx - 1, centery - 1);
00727     ticks = SDL_GetTicks();
00728     for(i = 0; i < 100; i++)
00729     {
00730       int x = centerx + rand()%3 - 1;
00731       int y = centery + rand()%3 - 1;
00732       FLASH_SHAPE(x, y, 0x14, 0, 0);
00733       if (SDL_GetTicks() - ticks > 400)
00734         break;
00735     }
00736     FORGET_OBJECT(backup);
00737   }
00738   catch(const UserBreakException &x)
00739   {
00740     // Waste disposal
00741     FORGET_ARRAY(txt);
00742     FORGET_OBJECT(backup); FORGET_OBJECT(backup2); FORGET_OBJECT(backup3);
00743     FORGET_OBJECT(cbackup); FORGET_OBJECT(cbackup2); FORGET_OBJECT(cbackup3);
00744     FORGET_OBJECT(plasma);
00745     
00746     if(typeid(x) != typeid(UserSkipException))
00747       throw x;
00748   }
00749 }
00750 
00751 void BG_Game::scene_desk()
00752 {
00753   Shape_frame *s;
00754   Image_buffer *backup = 0;
00755   int i;
00756 
00757   try
00758   {
00759     play_midi(home_song_midi);
00760     
00761     gwin->clear_screen();
00762     pal->load("<STATIC>/intropal.dat",1);
00763     pal->apply();
00764 
00765     // draw monitor (sh. 0x07, 0x08, 0x09, 0x0A: various parts of monitor)
00766     sman->paint_shape(centerx, centery, shapes.get_shape(0x07,0));
00767     sman->paint_shape(centerx, centery, shapes.get_shape(0x09,0));
00768     sman->paint_shape(centerx, centery, shapes.get_shape(0x08,0));
00769     sman->paint_shape(centerx, centery, shapes.get_shape(0x0A,0));
00770 
00771     // draw white dot in center of monitor (sh. 0x14)
00772     sman->paint_shape(centerx+12, centery-22, shapes.get_shape(0x14,0));
00773 
00774     // draw arm hitting pc (sh. 0x0C)
00775     s = shapes.get_shape(0x0C, 0);
00776     backup = win->create_buffer(s->get_width(), s->get_height());
00777     for (i=0; i<9; i++) {
00778       win->get(backup, centerx-96-30*abs(i%4-2) - s->get_xleft(),
00779          centery+100 - s->get_yabove());
00780       sman->paint_shape(centerx-96-30*abs(i%4-2), centery+100, s);
00781       win->show();
00782       win->put(backup, centerx-96-30*abs(i%4-2) - s->get_xleft(),
00783          centery+100 - s->get_yabove());
00784       WAITDELAY(1); //just to catch events
00785     }
00786 
00787     // screen comes back up (sh. 0x1D)
00788     sman->paint_shape(centerx+12, centery-22, shapes.get_shape(0x1D,0));
00789     win->show();
00790     FORGET_OBJECT(backup);
00791 
00792     // "Something is obviously amiss"
00793     sman->paint_shape(centerx, centery+50, shapes.get_shape(0x15,0));
00794     win->show();
00795     WAITDELAY(4000);
00796 
00797     // TODO: misaligned?
00798 
00799     // scroll right (sh. 0x06: map to the right of the monitor)
00800     for(i=0;i<194;i+=4) {
00801       sman->paint_shape(centerx-i,centery, shapes.get_shape(0x07,0));
00802       sman->paint_shape(centerx-i,centery, shapes.get_shape(0x09,0));
00803       sman->paint_shape(centerx-i,centery, shapes.get_shape(0x08,0));
00804       sman->paint_shape(centerx-i,centery, shapes.get_shape(0x0A,0));
00805       sman->paint_shape(centerx-i+12, centery-22, 
00806             shapes.get_shape(0x1D,0));
00807       sman->paint_shape(topx+320-i,topy, shapes.get_shape(0x06,0));
00808 
00809       if (i > 20 && i < 175) {
00810         // "It has been a long time..."
00811         sman->paint_shape(centerx, centery+50, 
00812               shapes.get_shape(0x16,0));
00813       }
00814       win->show();
00815       WAITDELAY(30);
00816     }
00817 
00818     // scroll down (sh. 0x0B: mouse + orb of moons, below map)
00819     for(i=0;i<=50;i+=2) {
00820       sman->paint_shape(centerx-194, centery-i,
00821             shapes.get_shape(0x07,0));
00822       sman->paint_shape(centerx-194, centery-i,
00823             shapes.get_shape(0x09,0));
00824       sman->paint_shape(centerx-194, centery-i,
00825             shapes.get_shape(0x08,0));
00826       sman->paint_shape(centerx-194, centery-i,
00827             shapes.get_shape(0x0A,0));
00828       sman->paint_shape(centerx-194+12, centery-22-i,
00829             shapes.get_shape(0x1D,0));
00830       sman->paint_shape(topx+319-194, topy-i,
00831             shapes.get_shape(0x06,0));
00832       sman->paint_shape(topx+319, topy+199-i,
00833             shapes.get_shape(0x0B,0));
00834       // "The mystical Orb beckons you"
00835       sman->paint_shape(centerx, topy, shapes.get_shape(0x17,0));
00836 
00837       win->show();
00838       WAITDELAYCYCLE2(50);
00839     }
00840     WAITDELAYCYCLE2(1000);
00841 
00842     sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x07,0));
00843     sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x09,0));
00844     sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x08,0));
00845     sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x0A,0));
00846     sman->paint_shape(centerx-182, centery-72, shapes.get_shape(0x1D,0));
00847     sman->paint_shape(topx+319-194, topy-50, shapes.get_shape(0x06,0));
00848     sman->paint_shape(topx+319, topy+149, shapes.get_shape(0x0B,0));
00849     // "It has opened gateways to Britannia in the past"
00850     sman->paint_shape(centerx, topy, shapes.get_shape(0x18,0));
00851     win->show();
00852 
00853     WAITDELAYCYCLE2(3000);
00854   }
00855   catch(const UserBreakException &x)
00856   {
00857     // Waste disposal
00858     FORGET_OBJECT(backup);
00859     
00860     throw x;
00861   }
00862 }
00863 
00864 void BG_Game::scene_moongate()
00865 {
00866   // sh. 0x02, 0x03, 0x04, 0x05: various parts of moongate
00867   // sh. 0x00, 0x01: parting trees before clearing
00868 
00869   int i;
00870     
00871   gwin->clear_screen();
00872     pal->load("<STATIC>/intropal.dat",5);
00873   pal->apply();
00874 
00875   // "Behind your house is the circle of stones"
00876   sman->paint_shape(centerx, centery+50, shapes.get_shape(0x19,0));
00877   win->show();
00878 
00879   // TODO: fade in screen while text is onscreen
00880 
00881   WAITDELAY(3000);
00882 
00883   // TODO: misaligned?
00884   for(i=120;i>=-170;i-=6) {
00885     sman->paint_shape(centerx+1,centery+1,
00886           shapes.get_shape(0x02,0));
00887     sman->paint_shape(centerx+1,centery+1,
00888           shapes.get_shape(0x03,0));
00889     sman->paint_shape(centerx+1,centery+1,
00890           shapes.get_shape(0x04,0));
00891     sman->paint_shape(centerx+1,centery+1,
00892           shapes.get_shape(0x05,0));
00893 
00894     sman->paint_shape(centerx+i,topy, shapes.get_shape(0x00,0));
00895     sman->paint_shape(centerx-i,topy, shapes.get_shape(0x01,0));
00896 
00897     // "Why is a moongate already there?"
00898     sman->paint_shape(centerx,centery+50,shapes.get_shape(0x1A,0));
00899     win->show();
00900     WAITDELAYCYCLE3(50);
00901   }
00902 
00903   sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x02,0));
00904   sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x03,0));
00905   sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x04,0));
00906   sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x05,0));
00907 
00908   // "You have but one path to the answer"
00909   sman->paint_shape(centerx, centery+50, shapes.get_shape(0x1C,0));
00910   win->show();
00911 
00912   // TODO: zoom (run) into moongate
00913 
00914   WAITDELAYCYCLE3(3000);
00915 
00916   // Wait till the music finished playing
00917   while(Audio::get_ptr()->is_track_playing(home_song_midi))
00918     WAITDELAYCYCLE3(50);
00919 }
00920 
00921 void BG_Game::top_menu()
00922 {
00923   play_midi(menu_midi, true);
00924     
00925   sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
00926   pal->load("<STATIC>/intropal.dat",0);
00927   pal->fade_in(60); 
00928 }
00929 
00930 void BG_Game::show_journey_failed()
00931 {
00932   pal->fade_out(50);
00933   sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
00934   journey_failed_text();
00935 }
00936   
00937 void BG_Game::end_game(bool success) 
00938 {
00939   int i, j, next = 0;
00940   int starty;
00941   int centerx = gwin->get_width() /2;
00942   int   topy = (gwin->get_height()-200)/2;
00943   Font *font = fontManager.get_font("MENU_FONT");
00944 
00945   if(!success) {
00946     TextScroller text(MAINSHP_FLX, 0x15,
00947           font,0);
00948     gwin->clear_screen();
00949     pal->load("<STATIC>/intropal.dat",0);
00950     for(uint32 i=0; i<text.get_count(); i++) {
00951       text.show_line(gwin, topx, topx+320, topy+20+i*12, i);
00952     }
00953     
00954     pal->fade_in(c_fade_in_time);
00955     wait_delay(10000);
00956     pal->fade_out(c_fade_out_time);
00957     
00958     gwin->clear_screen();
00959     font->center_text(ibuf, centerx, centery-10, "The end of Ultima VII");
00960     pal->fade_in(c_fade_in_time);
00961     wait_delay(4000);
00962       pal->fade_out(c_fade_out_time);
00963     
00964     gwin->clear_screen();
00965     font->center_text(ibuf, centerx, centery-10, "The end of Britannia as you know it!");
00966     pal->fade_in(c_fade_in_time);
00967     wait_delay(4000);
00968     pal->fade_out(c_fade_out_time);
00969     gwin->clear_screen(true);
00970     return;
00971   }
00972 
00973   // Audio buffer
00974   size_t  size;
00975   uint8 *buffer;
00976   
00977   // Fli Buffers
00978   size_t  flisize;
00979   char  *fli_b[3];
00980 
00981   // Clear screen
00982   gwin->clear_screen(true);
00983 
00984   U7object flic1(ENDGAME, 0);
00985   U7object flic2(ENDGAME, 1);
00986   U7object flic3(ENDGAME, 2);
00987   U7object speech1(ENDGAME, 7);
00988   U7object speech2(ENDGAME, 8);
00989   U7object speech3(ENDGAME, 9);
00990 
00991   /* There seems to be something wrong with the shapes. Needs investigating
00992   U7object shapes(ENDGAME, 10);
00993   shapes.retrieve("endgame.shp");
00994   Shape_file sf("endgame.shp");
00995   int x = get_width()/2-160;
00996   int y = get_height()/2-100;
00997   cout << "Shape in Endgame.dat has " << sf.get_num_frames() << endl;
00998   */
00999 
01000   fli_b[0] = flic1.retrieve(flisize);
01001   playfli fli1(fli_b[0]+8, flisize-8);
01002 
01003   fli_b[1] = flic2.retrieve(flisize);
01004   playfli fli2(fli_b[1]+8, flisize-8);
01005 
01006   fli_b[2] = flic3.retrieve(flisize);
01007   playfli fli3(fli_b[2]+8, flisize-8);
01008 
01009   buffer = (uint8 *) speech1.retrieve(size);
01010   
01011   fli1.play(win, 0, 0, 0);
01012   
01013   // Start endgame music.
01014   Audio *audio = Audio::get_ptr();
01015   int music_offset = 0;
01016   if (audio) {
01017     MyMidiPlayer *midi = audio->get_midi();
01018     if (midi) {
01019       midi->load_patches(true);
01020       if (midi->is_fm_synth()) music_offset = 2;
01021     }
01022     audio->start_music(ENDSCORE_XMI,1+music_offset,false);
01023   }
01024   
01025   // A little hack
01026   bool do_break = false;
01027   do {
01028 
01029     for (i = 0; i < 240; i++)
01030     {
01031       next = fli1.play(win, 0, 1, next);
01032       if (wait_delay (0)) { do_break = true; break; }
01033     }
01034     if (do_break) break;
01035     
01036     for (i = 1; i < 150; i++)
01037     {
01038       next = fli1.play(win, i, i+1, next);
01039       if (wait_delay (0)) { do_break = true; break; }
01040     }
01041     if (do_break) break;
01042 
01043     if (audio) audio->play (buffer+8, size-8, false);
01044     FORGET_ARRAY(buffer);
01045     Font *endfont2 = fontManager.get_font("END2_FONT");
01046     Font *endfont3 = fontManager.get_font("END3_FONT");
01047     Font *normal = fontManager.get_font("NORMAL_FONT");
01048 
01049     const char  *message = "No. You cannot do that! You must not!";
01050     int height = topy+200 - endfont2->get_text_height()*2;
01051     int width = (gwin->get_width() - endfont2->get_text_width(message)) / 2;
01052 
01053     for (i = 150; i < 204; i++)
01054     {
01055       next = fli1.play(win, i, i, next);
01056       endfont2->draw_text(ibuf, width, height, message);
01057       
01058       win->show();
01059       if (wait_delay (0)) { do_break = true; break; }
01060     }
01061     if (do_break) break;
01062 
01063     // Set new music
01064     if (audio) audio->start_music(ENDSCORE_XMI,2+music_offset,false);
01065 
01066     // Set speech
01067     
01068     buffer = (uint8 *) speech2.retrieve(size);
01069     if (audio) audio->play (buffer+8, size-8, false);
01070     FORGET_ARRAY(buffer);
01071 
01072     message = "Damn you Avatar!  Damn you!";
01073     width = (gwin->get_width() - endfont2->get_text_width(message)) / 2;
01074 
01075     for (i = 0; i < 100; i++)
01076     {
01077       next = fli2.play(win, i, i, next);
01078       endfont2->draw_text(ibuf, width, height, message);
01079       
01080       win->show();
01081       if (wait_delay (0)) { do_break = true; break; }
01082     }
01083     if (do_break) break;
01084 
01085     Palette *pal = fli2.get_palette();
01086     next = SDL_GetTicks();
01087     for (i = 1000 + next; next < i; next += 10)
01088     {
01089       // Speed related frame skipping detection
01090       int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next;
01091       while (SDL_GetTicks() < next)
01092         ;
01093       if (!skip_frame)
01094       {
01095         pal->set_brightness ((i - next) / 10);
01096         pal->apply();
01097       }
01098       if (wait_delay (0)) { do_break = true; break; }
01099     }
01100     if (do_break) break;
01101 
01102     pal->set_brightness(80);  // Set readable brightness
01103     // Text message 1
01104 
01105     // Paint backgound black
01106     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01107 
01108     // Paint text
01109     message = "The Black Gate is destroyed.";
01110     width = (gwin->get_width() - normal->get_text_width(message)) / 2;
01111     height = (gwin->get_height() - normal->get_text_height()) / 2;
01112     
01113     normal->draw_text (ibuf, width, height, message);
01114 
01115     // Fade in for 1 sec (50 cycles)
01116     pal->fade (50, 1, 0);
01117 
01118     // Display text for 3 seconds
01119     for (i = 0; i < 30; i++) if (wait_delay (100)) { do_break = true; break; }
01120     if (do_break) break;
01121 
01122     // Fade out for 1 sec (50 cycles)
01123     pal->fade (50, 0, 0);
01124 
01125     
01126     // Now the second text message
01127 
01128 
01129     // Paint backgound black
01130     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01131 
01132     // Paint text
01133     message = "The Guardian has been stopped.";
01134     width = (gwin->get_width() - normal->get_text_width(message)) / 2;
01135 
01136     normal->draw_text (ibuf, width, height, message);
01137 
01138     // Fade in for 1 sec (50 cycles)
01139     pal->fade (50, 1, 0);
01140 
01141     // Display text for approx 3 seonds
01142     for (i = 0; i < 30; i++) if (wait_delay (100)) { do_break = true; break; }
01143     if (do_break) break;
01144 
01145     // Fade out for 1 sec (50 cycles)
01146     pal->fade (50, 0, 0);
01147 
01148     next = fli3.play(win, 0, 0, next);
01149     pal = fli3.get_palette();
01150     next = SDL_GetTicks();
01151     for (i = 1000 + next; next < i; next += 10)
01152     {
01153       // Speed related frame skipping detection
01154       int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next;
01155       while (SDL_GetTicks() < next)
01156         ;
01157       if (!skip_frame)
01158       {
01159         pal->set_brightness (100 - (i-next) / 10);
01160         pal->apply();
01161       }
01162       if (wait_delay (0)) { do_break = true; break; }
01163     }
01164     if (do_break) break;
01165     
01166     buffer = (uint8 *) speech3.retrieve(size);
01167     if (audio) audio->play (buffer+8, size-8, false);
01168     FORGET_ARRAY(buffer);
01169 
01170     playfli::fliinfo finfo;
01171     fli3.info (&finfo);
01172     
01173     int m;
01174     const char *txt_screen0[] = {
01175       "Avatar! You think you have won>",
01176       "Think again! You are unable to",
01177       "leave britannia, whereas I am free",
01178       "to enter other worlds",
01179       "Perhaps your puny Earth shall be",
01180       "my NEXT target!."
01181     };
01182 
01183     starty = (gwin->get_height() - endfont3->get_text_height()*8)/2;
01184 
01185     next = SDL_GetTicks();
01186     for (i = next+28000; i > next; )
01187     {
01188       for (j = 0; j < finfo.frames; j++)
01189       {
01190         next = fli3.play(win, j, j, next);
01191         for(m=0; m<6; m++)
01192           endfont3->center_text(ibuf, centerx, starty+endfont3->get_text_height()*m, txt_screen0[m]);
01193 
01194         win->show ();
01195         if (wait_delay (10)) { do_break = true; break; }
01196       }
01197     }
01198     if (do_break) break;
01199 
01200     
01201     next = SDL_GetTicks();
01202     for (i = 1000 + next; next < i; next += 10)
01203     {
01204       // Speed related frame skipping detection
01205       int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next;
01206       while (SDL_GetTicks() < next)
01207         ;
01208       if (!skip_frame)
01209       {
01210         pal->set_brightness ((i - next) / 10);
01211         pal->apply();
01212       }
01213       if (wait_delay (0)) { do_break = true; break; }
01214     }
01215     if (do_break) break;
01216 
01217     // Text Screen 1
01218 
01219     pal->set_brightness(80);  // Set readable brightness
01220     // Paint backgound black
01221     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01222 
01223 
01224     const char *txt_screen1[] = {
01225       "In the months following the climactic",
01226       "battle at The Black Gate, Britannia",
01227       "is set upon the long road to recovery",
01228       "from its various plights.",
01229       " ",
01230       "Upon your return to Britain,",
01231       "Lord British decreed that",
01232       "The Fellowship be outlawed",
01233       "and all of the branches were",
01234       "soon destroyed."
01235     };
01236 
01237     starty = (gwin->get_height() - normal->get_text_height()*10)/2;
01238     
01239     for(i=0; i<10; i++)
01240       normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen1[i])/2, starty+normal->get_text_height()*i, txt_screen1[i]);
01241 
01242     // Fade in for 1 sec (50 cycles)
01243     pal->fade (50, 1, 0);
01244 
01245     // Display text for 20 seonds (only 10 at the moment)
01246     for (i = 0; i < 100; i++) if (wait_delay (100)) { do_break = true; break; }
01247     if (do_break) break;
01248 
01249     // Fade out for 1 sec (50 cycles)
01250     pal->fade (50, 0, 0);
01251 
01252     if (wait_delay (10)) { do_break = true; break; }
01253     if (do_break) break;
01254 
01255     // Text Screen 2
01256 
01257     // Paint backgound black
01258     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01259 
01260     const char *txt_screen2[] = {
01261       "The frustration you feel at having been",
01262       "stranded in Britannia is somewhat",
01263       "alleviated by the satisfaction that you",
01264       "solved the gruesome murders committed",
01265       "by The Fellowship and even avenged the",
01266       "death of Spark's father."
01267     };
01268 
01269     starty = (gwin->get_height() - normal->get_text_height()*6)/2;
01270     
01271     for(i=0; i<6; i++)
01272       normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen2[i])/2, starty+normal->get_text_height()*i, txt_screen2[i]);
01273 
01274 
01275     // Fade in for 1 sec (50 cycles)
01276     pal->fade (50, 1, 0);
01277 
01278     // Display text for 20 seonds (only 8 at the moment)
01279     for (i = 0; i < 80; i++) if (wait_delay (100)) { do_break = true; break; }
01280     if (do_break) break;
01281 
01282     // Fade out for 1 sec (50 cycles)
01283     pal->fade (50, 0, 0);
01284 
01285     if (wait_delay (10)) break;
01286 
01287     // Text Screen 3 
01288 
01289     // Paint backgound black
01290     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01291 
01292     const char *txt_screen3[] = {
01293       "And although you are, at the moment,",
01294       "helpless to do anything about",
01295       "The Guardian's final threat,",
01296       "another thought nags at you...",
01297       "what became of Batlin, the fiend",
01298       "who got away?"
01299     };
01300 
01301     starty = (gwin->get_height() - normal->get_text_height()*6)/2;
01302     
01303     for(i=0; i<6; i++)
01304       normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen3[i])/2, starty+normal->get_text_height()*i, txt_screen3[i]);
01305 
01306     // Fade in for 1 sec (50 cycles)
01307     pal->fade (50, 1, 0);
01308 
01309     // Display text for 20 seonds (only 8 at the moment)
01310     for (i = 0; i < 80; i++) if (wait_delay (100)) { do_break = true; break; }
01311     if (do_break) break;
01312 
01313     // Fade out for 1 sec (50 cycles)
01314     pal->fade (50, 0, 0);
01315 
01316     if (wait_delay (10)) break;
01317 
01318     // Text Screen 4
01319 
01320     // Paint backgound black
01321     win->fill8(0,gwin->get_width(),gwin->get_height(),0,0);
01322 
01323     const char *txt_screen4[] = {
01324       "That is another story...", 
01325       "one that will take you",
01326       "to a place called",
01327       "The Serpent Isle..."
01328     };
01329 
01330     starty = (gwin->get_height() - normal->get_text_height()*4)/2;
01331     
01332     for(i=0; i<4; i++)
01333       normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen4[i])/2, starty+normal->get_text_height()*i, txt_screen4[i]);
01334 
01335 
01336     // Fade in for 1 sec (50 cycles)
01337     pal->fade (50, 1, 0);
01338 
01339     // Display text for 10 seonds (only 5 at the moment)
01340     for (i = 0; i < 50; i++) if (wait_delay (100)) { do_break = true; break; }
01341     if (do_break) break;
01342 
01343     // Fade out for 1 sec (50 cycles)
01344     pal->fade (50, 0, 0);
01345   }
01346   while (0);
01347 
01348   if (audio) {
01349     audio->stop_music();
01350     MyMidiPlayer *midi = audio->get_midi();
01351     if (midi) midi->load_patches(false);
01352   }
01353 
01354   gwin->clear_screen(true);
01355   FORGET_ARRAY(buffer);
01356   FORGET_ARRAY(fli_b[0]);
01357   FORGET_ARRAY(fli_b[1]);
01358   FORGET_ARRAY(fli_b[2]);
01359 }
01360 
01361 void BG_Game::show_quotes()
01362 {
01363   play_midi(quotes_midi);
01364   TextScroller quotes(MAINSHP_FLX, 0x10, 
01365       fontManager.get_font("MENU_FONT"),
01366       menushapes.extract_shape(0x14)
01367       );
01368   gwin->get_pal()->load("<STATIC>/intropal.dat",6);
01369   quotes.run(gwin);
01370   gwin->get_pal()->load("<STATIC>/intropal.dat",0);
01371 }
01372 
01373 void BG_Game::show_credits()
01374 {
01375   
01376   play_midi(credits_midi);
01377   TextScroller credits(MAINSHP_FLX, 0x0E, 
01378       fontManager.get_font("MENU_FONT"),
01379       menushapes.extract_shape(0x14)
01380       );
01381   gwin->get_pal()->load("<STATIC>/intropal.dat",6);
01382   if(credits.run(gwin)) { // Watched through the entire sequence?
01383     std::ofstream quotesflg;
01384     U7open(quotesflg, "<SAVEGAME>/quotes.flg");
01385     quotesflg.close();
01386   }
01387     
01388   gwin->get_pal()->load("<STATIC>/intropal.dat",0);
01389 }
01390 
01391 bool BG_Game::new_game(Vga_file &shapes)
01392 {
01393   SDL_EnableUNICODE(1);
01394 
01395   int menuy = topy+110;
01396   Font *font = fontManager.get_font("MENU_FONT");
01397 
01398   // Need to know if SI is installed
01399   bool si_installed = SI_Game::is_installed();
01400 
01401   U7object faces_u7o("<DATA>/exult_bg.flx", EXULT_BG_FLX_MR_INTRO_SHP);
01402   size_t shapesize;
01403   char *shape_buf = faces_u7o.retrieve(shapesize);
01404   BufferDataSource faces_ds(shape_buf, shapesize);
01405   Shape_file faces_shape(&faces_ds);
01406 
01407   const int max_name_len = 16;
01408   char npc_name[max_name_len+1];
01409   char disp_name[max_name_len+2];
01410   npc_name[0] = 0;
01411   int sex = 0;
01412   int selected = 0;
01413   int num_choices = 4;
01414   gwin->get_pal()->load("<STATIC>/intropal.dat",6);
01415   SDL_Event event;
01416   bool editing = true;
01417   bool redraw = true;
01418   bool ok = true;
01419   do
01420   {
01421     if (redraw)
01422     {
01423       win->fill8(0,gwin->get_width(),90,0,menuy);
01424       sman->paint_shape(topx+10,menuy+10,shapes.get_shape(0xC, selected==0?1:0));
01425 
01426       Shape_frame *sex_shape = shapes.get_shape(0xA, selected==1?1:0);
01427       sman->paint_shape(topx+10,menuy+25,sex_shape);
01428       int sex_width = sex_shape->get_width()+10;
01429       if (sex_width > 35) sex_width += 25; 
01430       else sex_width = 60;
01431 
01432       if (si_installed)
01433       {
01434         sman->paint_shape(topx+sex_width,menuy+25,shapes.get_shape(0xB,sex%2));
01435 
01436         if (sex >= 2)
01437         {
01438           sman->paint_shape(topx+250,menuy+10,faces_shape.get_frame(7-sex));
01439         }
01440         else
01441           sman->paint_shape(topx+250,menuy+10,shapes.get_shape(sex,0));
01442       }
01443       else
01444       {
01445         sman->paint_shape(topx+sex_width,menuy+25,shapes.get_shape(0xB,sex));
01446         sman->paint_shape(topx+250,menuy+10,shapes.get_shape(sex,0));
01447       }
01448 
01449       sman->paint_shape(topx+10,topy+180,shapes.get_shape(0x8,selected==2?1:0));
01450       sman->paint_shape(centerx+10,topy+180,shapes.get_shape(0x7,selected==3?1:0));
01451       if(selected==0)
01452         snprintf(disp_name, max_name_len+2, "%s_", npc_name);
01453       else
01454         snprintf(disp_name, max_name_len+2, "%s", npc_name);
01455       font->draw_text(ibuf, topx+60, menuy+10, disp_name);
01456       gwin->get_pal()->apply();
01457       redraw = false;
01458     }
01459     SDL_WaitEvent(&event);
01460     if(event.type==SDL_KEYDOWN)
01461     {
01462       redraw = true;
01463       switch(event.key.keysym.sym)
01464       {
01465       case SDLK_SPACE:
01466         if(selected==0)
01467         {
01468           int len = strlen(npc_name);
01469           if(len<max_name_len)
01470           {
01471             npc_name[len] = ' ';
01472             npc_name[len+1] = 0;
01473           }
01474         }
01475         else if(selected==1)
01476         {
01477           if (si_installed)
01478           {
01479             sex++;
01480             if (sex >= 8) sex = 0;
01481           }
01482           else
01483             sex = !sex;
01484         }
01485         else if(selected==2)
01486         {
01487           editing=false;
01488           ok = true;
01489         }
01490         else if(selected==3)
01491         {
01492           editing = false;
01493           ok = false;
01494         }
01495         break;
01496       case SDLK_LEFT:
01497         if(selected==1)
01498         {
01499           if (si_installed)
01500           {
01501             sex--;
01502             if (sex < 0) sex = 7;
01503           }
01504           else
01505             sex = !sex;
01506         }
01507         break;
01508 
01509       case SDLK_RIGHT:
01510         if(selected==1)
01511         {
01512           if (si_installed)
01513           {
01514             sex++;
01515             if (sex >= 8) sex = 0;
01516           }
01517           else
01518             sex = !sex;
01519         }
01520         break;
01521       case SDLK_ESCAPE:
01522         editing = false;
01523         ok = false;
01524         break;
01525       case SDLK_TAB:
01526       case SDLK_DOWN:
01527         ++selected;
01528         if(selected==num_choices)
01529           selected = 0;
01530         break;
01531       case SDLK_UP:
01532         --selected;
01533         if(selected<0)
01534           selected = num_choices-1;
01535         break;
01536       case SDLK_RETURN:
01537         if(selected<2) 
01538           ++selected;
01539         else if(selected==2)
01540         {
01541           editing=false;
01542           ok = true;
01543         }
01544         else
01545         {
01546           editing = false;
01547           ok = false;
01548         }
01549         break;
01550       case SDLK_BACKSPACE:
01551         if(selected==0)
01552         {
01553           if(strlen(npc_name)>0)
01554             npc_name[strlen(npc_name)-1] = 0;
01555         }
01556         break;
01557       default:
01558         {
01559           if (selected == 0) // on the text input field?
01560           {
01561             int len = strlen(npc_name);
01562             char chr = 0;
01563 
01564             if ((event.key.keysym.unicode & 0xFF80) == 0)
01565               chr = event.key.keysym.unicode & 0x7F;
01566 
01567             if (chr >= ' ' && len < max_name_len)
01568             {
01569               npc_name[len] = chr;
01570               npc_name[len+1] = 0;
01571             }
01572           }
01573           else
01574           {
01575             redraw = false;
01576           }
01577         }
01578         break;
01579       }
01580     }
01581   }
01582   while(editing);
01583 
01584   FORGET_ARRAY(shape_buf);
01585 
01586   if(ok)
01587   {
01588 #ifdef DEBUG
01589     std::cout << "Skin is: " << (3-(sex/2)) << " Sex is: " << (sex%2) << std::endl;
01590 #endif
01591     set_avskin(3-(sex/2));
01592     set_avname (npc_name);
01593     set_avsex (sex%2);
01594     gwin->get_pal()->fade_out(c_fade_out_time);
01595     gwin->clear_screen(true); 
01596     ok =gwin->init_gamedat(true);
01597   }
01598   win->fill8(0,gwin->get_width(),90,0,menuy);
01599 
01600   SDL_EnableUNICODE(0);
01601 
01602   return ok;
01603 }
01604 
01605 bool BG_Game::is_installed()
01606 {
01607   std::string buf("<BLACKGATE_STATIC>/endgame.dat");
01608   bool foundbg = U7exists(buf);
01609   bool foundbgflx = U7exists("<DATA>/exult_bg.flx");
01610 
01611   if (foundbg)
01612     std::cout << "Black Gate   : found" << std::endl;
01613   else
01614     std::cout << "Black Gate   : not found (" 
01615           << get_system_path(buf) << ")" << std::endl;
01616 
01617   if (foundbgflx)
01618     std::cout << "exult_bg.flx : found" << std::endl;
01619   else
01620     std::cout << "exult_bg.flx : not found (" 
01621           << get_system_path("<DATA>/exult_bg.flx")
01622           << ")" << std::endl;
01623 
01624   return (foundbg && foundbgflx);
01625 }

Generated on Mon Jul 9 14:42:44 2007 for ExultEngine by  doxygen 1.5.1