sigame.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 #ifndef ALPHA_LINUX_CXX
00024 #  include <cctype>
00025 #endif
00026 
00027 #include "SDL_events.h"
00028 #include "files/U7file.h"
00029 #include "files/utils.h"
00030 #include "flic/playfli.h"
00031 #include "gamewin.h"
00032 #include "Audio.h"
00033 #include "sigame.h"
00034 #include "palette.h"
00035 #include "databuf.h"
00036 #include "font.h"
00037 #include "txtscroll.h"
00038 #include "exult_types.h"
00039 #include "mappatch.h"
00040 #include "shapeid.h"
00041 
00042 #ifndef UNDER_CE
00043 using std::cout;
00044 using std::endl;
00045 using std::rand;
00046 using std::strlen;
00047 using std::toupper;
00048 #endif
00049 
00050 SI_Game::SI_Game()
00051   {
00052     add_shape("gumps/check",2);
00053     add_shape("gumps/fileio",3);
00054     add_shape("gumps/fntext",4);
00055     add_shape("gumps/loadbtn",5);
00056     add_shape("gumps/savebtn",6);
00057     add_shape("gumps/halo",7);
00058     add_shape("gumps/disk",19);
00059     add_shape("gumps/heart",20);
00060     add_shape("gumps/statatts",23);
00061     add_shape("gumps/musicbtn",24);
00062     add_shape("gumps/speechbtn",25);
00063     add_shape("gumps/soundbtn",26);
00064     add_shape("gumps/spellbook",38);
00065     add_shape("gumps/combat",41);
00066     add_shape("gumps/statsdisplay",42);
00067     add_shape("gumps/quitbtn",50);
00068     add_shape("gumps/yesnobox",51);
00069     add_shape("gumps/yesbtn",52);
00070     add_shape("gumps/nobtn",53);
00071     add_shape("gumps/book",27);
00072     add_shape("gumps/scroll",49);
00073     add_shape("gumps/combat_stats",91);
00074     add_shape("gumps/combatmode",12);
00075     add_shape("gumps/slider",14);
00076     add_shape("gumps/slider_diamond",15);
00077     add_shape("gumps/slider_right",16);
00078     add_shape("gumps/slider_left",17);
00079 
00080     add_shape("gumps/box", 0);
00081     add_shape("gumps/crate", 1);
00082     add_shape("gumps/barrel", 8);
00083     add_shape("gumps/bag", 9);
00084     add_shape("gumps/backpack", 10);
00085     add_shape("gumps/basket", 11);
00086     add_shape("gumps/chest", 18);
00087     add_shape("gumps/shipshold", 21);
00088     add_shape("gumps/drawer", 22);
00089     add_shape("gumps/woodsign", 44);
00090     add_shape("gumps/tombstone", 45);
00091     add_shape("gumps/goldsign", 46);
00092     add_shape("gumps/body", 48);
00093     add_shape("gumps/tree", 64);
00094 
00095     add_shape("gumps/cstats/1",58);
00096     add_shape("gumps/cstats/2",59);
00097     add_shape("gumps/cstats/3",60);
00098     add_shape("gumps/cstats/4",61);
00099     add_shape("gumps/cstats/5",62);
00100     add_shape("gumps/cstats/6",63);
00101 
00102     add_shape("sprites/map", 22);
00103     add_shape("sprites/cheatmap", 0);
00104 
00105     // Need to be done
00106     add_shape("gumps/spell_scroll",65);
00107     add_shape("gumps/jawbone", 56);
00108     add_shape("gumps/tooth", 57);
00109 
00110     add_resource("files/shapes/count", 0, 8);
00111     add_resource("files/shapes/0", "<STATIC>/shapes.vga", 0);
00112     add_resource("files/shapes/1", "<STATIC>/faces.vga", 0);
00113     add_resource("files/shapes/2", "<STATIC>/gumps.vga", 0);
00114     add_resource("files/shapes/3", "<STATIC>/sprites.vga", 0);
00115     add_resource("files/shapes/4", MAINSHP_FLX, 0);
00116     add_resource("files/shapes/5", "<STATIC>/paperdol.vga", 0);
00117     add_resource("files/shapes/6", "<DATA>/exult.flx", 0);
00118     add_resource("files/shapes/7", "<STATIC>/fonts.vga", 0);
00119 
00120     add_resource("files/gameflx", "<DATA>/exult_si.flx", 0);
00121   
00122     add_resource("config/defaultkeys", "<DATA>/exult_si.flx", 1);
00123 
00124     add_resource("palettes/count", 0, 14);
00125     add_resource("palettes/0", PALETTES_FLX, 0);
00126     add_resource("palettes/1", PALETTES_FLX, 1);
00127     add_resource("palettes/2", PALETTES_FLX, 2);
00128     add_resource("palettes/3", PALETTES_FLX, 3);
00129     add_resource("palettes/4", PALETTES_FLX, 4);
00130     add_resource("palettes/5", PALETTES_FLX, 5);
00131     add_resource("palettes/6", PALETTES_FLX, 6);
00132     add_resource("palettes/7", PALETTES_FLX, 7);
00133     add_resource("palettes/8", PALETTES_FLX, 8);
00134     add_resource("palettes/9", PALETTES_FLX, 9);
00135     add_resource("palettes/10", PALETTES_FLX, 10);
00136     add_resource("palettes/11", PALETTES_FLX, 11);
00137     add_resource("palettes/12", PALETTES_FLX, 12);
00138     add_resource("palettes/13", MAINSHP_FLX, 1);
00139     add_resource("palettes/14", MAINSHP_FLX, 26);
00140     
00141     fontManager.add_font("MENU_FONT", MAINSHP_FLX, 9, 1);
00142     fontManager.add_font("SIINTRO_FONT", "<STATIC>/intro.dat", 14, 0);
00143     Map_patch_collection *mp = gwin->get_map_patches();
00144           // Egg by "PC pirate" in forest:
00145     mp->add(new Map_patch_remove(Object_spec(
00146         Tile_coord(647, 1899, 0), 275, 7, 1)));
00147           // Carpets above roof in Monitor:
00148     mp->add(new Map_patch_remove(Object_spec(
00149         Tile_coord(1035, 2572, 8), 483, 1, 0), true));
00150     mp->add(new Map_patch_remove(Object_spec(
00151         Tile_coord(1034, 2571, 6), 483, 1, 0)));
00152     mp->add(new Map_patch_remove(Object_spec(
00153         Tile_coord(1034, 2571, 5), 483, 1, 0), true));
00154           // Neyobi under a fur:
00155     mp->add(new Map_patch_modify(Object_spec(
00156         Tile_coord(1012, 873, 0), 867, 13, 0), 
00157           Object_spec(
00158         Tile_coord(1013, 873, 1), 867, 13, 0)));
00159 
00160   }
00161 
00162 SI_Game::~SI_Game()
00163   {
00164   }
00165 
00166 // Little weighted random function for lightning on the castle
00167 static int get_frame (void)
00168 {
00169   int num = rand() % 9;
00170 
00171   if (num >= 8) return 2;
00172   else if (num >= 6) return 1;
00173   return 0;
00174 }
00175 
00176 void SI_Game::play_intro()
00177 {
00178   int next = 0;
00179   size_t  flisize;
00180   char  *fli_b = 0;
00181   uint8 *buffer = 0;
00182   size_t  size;
00183   size_t  shapesize;
00184   char *  shape_buf = 0;
00185   int   i,j;
00186   Font *font = fontManager.get_font("MENU_FONT");
00187   Font *sifont = fontManager.get_font("SIINTRO_FONT");
00188 
00189   bool speech = Audio::get_ptr()->is_speech_enabled();
00190 
00191   gwin->clear_screen(true);
00192   
00193   Audio::get_ptr()->stop_music();
00194 
00195   // Lord British presents...
00196   try
00197   {
00198     U7object lbflic("<STATIC>/intro.dat", 0);
00199     fli_b = lbflic.retrieve(flisize);
00200     playfli fli0(fli_b+8, flisize-8);
00201     fli0.info();
00202 
00203     const char *txt_msg[] = { "with help from",
00204         "The Exult Team", 
00205         "Driven by Exult" };
00206 
00207     for (j = 0; j < 20; j++)
00208     {
00209       next = fli0.play(win, 0, 0, next, j*5);
00210       font->center_text(ibuf, centerx, centery+50, txt_msg[0]);
00211       font->center_text(ibuf, centerx, centery+65, txt_msg[1]);
00212       win->show();
00213     }
00214 
00215 
00216     next = fli0.play(win, 0, 0, next, 100);
00217     font->center_text(ibuf, centerx, centery+50, txt_msg[0]);
00218     font->center_text(ibuf, centerx, centery+65, txt_msg[1]);
00219     win->show();
00220 
00221     if (wait_delay (3000))
00222       throw UserBreakException();
00223 
00224     for (j = 20; j; j--)
00225     {
00226       next = fli0.play(win, 0, 0, next, j*5);
00227       font->center_text(ibuf, centerx, centery+50, txt_msg[0]);
00228       font->center_text(ibuf, centerx, centery+65, txt_msg[1]);
00229       win->show();
00230     }
00231 
00232 
00233     FORGET_ARRAY(fli_b);
00234 
00235     if (wait_delay (0))
00236       throw UserBreakException();
00237 
00238     gwin->clear_screen(true);
00239 
00240     
00241     // Castle Outside
00242 
00243     // Start Music
00244     Audio *audio = Audio::get_ptr();
00245     if (audio) {
00246       const char *fn = "<STATIC>/r_sintro.xmi";
00247       MyMidiPlayer *midi = audio->get_midi();
00248       if (midi && midi->is_fm_synth()) fn = "<STATIC>/a_sintro.xmi";
00249       audio->start_music (fn, 0, false);
00250     }
00251 
00252     // Thunder, note we use the buffer again later so it's not freed here
00253     if (speech)
00254     {
00255       U7object voc_thunder("<STATIC>/intro.dat", 15);
00256       buffer = (uint8 *) voc_thunder.retrieve(size);
00257       Audio::get_ptr()->play (buffer+8, size-8, false);
00258     }
00259 
00260     U7object flic("<STATIC>/intro.dat", 1);
00261     fli_b = flic.retrieve(flisize);
00262     playfli fli1(fli_b+8, flisize-8);
00263     fli1.info();
00264 
00265     fli1.play(win, 0, 1, 0, 0);
00266 
00267     next = SDL_GetTicks();
00268     int prev = -1;
00269     int   num;
00270     
00271     for (j = 0; j < 20; j++)
00272     {
00273       num = get_frame();
00274       if (prev != num)
00275         for (i = 0; i < num+1; i++)
00276           fli1.play(win, i, i, next);
00277 
00278       prev = num;
00279       next += 75;
00280       win->show();
00281       if (wait_delay (1))
00282         throw UserBreakException();
00283 
00284     }
00285 
00286     const char *lb_cas = "Lord British's Castle";
00287     const char *db_cas = "Dick British's Castle";
00288     
00289     for (j = 0; j < 50; j++)
00290     {
00291       num = get_frame();
00292       if (prev != num)
00293         for (i = 0; i < num+1; i++)
00294           fli1.play(win, i, i, next);
00295 
00296       if (jive)
00297         sifont->center_text(ibuf, centerx, centery+50, db_cas);
00298       else 
00299         sifont->center_text(ibuf, centerx, centery+50, lb_cas);
00300 
00301       prev = num;
00302       next += 75;
00303       win->show();
00304       if (wait_delay (1))
00305         throw UserBreakException();
00306 
00307     }
00308 
00309     for (j = 0; j < 10; j++)
00310     {
00311       num = get_frame();
00312       if (prev != num)
00313         for (i = 0; i < num+1; i++)
00314           fli1.play(win, i, i, next);
00315 
00316       // Thunder again, we free the buffer here 
00317       if (speech && j == 5) { 
00318         Audio::get_ptr()->play (buffer+8, size-8, false);
00319         FORGET_ARRAY(buffer);
00320       }
00321 
00322       prev = num;
00323       next += 75;
00324       win->show();
00325       if (wait_delay (1))
00326         throw UserBreakException();
00327 
00328     }
00329 
00330     const char *bg_fellow[] = { "Eighteen months after the destruction", 
00331         "of the Black Gate and the", 
00332         "dismantling of The Fellowship"};
00333 
00334 
00335     for (j = 0; j < 75; j++)
00336     {
00337       num = get_frame();
00338       if (prev != num)
00339         for (i = 0; i < num+1; i++)
00340           fli1.play(win, i, i, next);
00341 
00342       for(i=0; i<3; i++) {
00343         sifont->center_text(ibuf, centerx, centery+50+15*i, bg_fellow[i]);
00344       }
00345 
00346       prev = num;
00347       next += 75;
00348       win->show();
00349       if (wait_delay (1))
00350         throw UserBreakException();
00351 
00352     }
00353 
00354     for (j = 20; j; j--)
00355     {
00356       next = fli1.play(win, 0, 0, next, j*5);
00357       win->show();
00358       if (wait_delay (0))
00359         throw UserBreakException();
00360 
00361     }
00362     FORGET_ARRAY(fli_b);
00363 
00364     if (wait_delay (0))
00365       throw UserBreakException();
00366 
00367     // Do this! Prevents palette corruption
00368     gwin->clear_screen(true);
00369 
00370     // Guard walks in
00371     U7object flic2("<STATIC>/intro.dat", 2);
00372     fli_b = flic2.retrieve(flisize);
00373     playfli fli2(fli_b+8, flisize-8);
00374     fli2.info();
00375 
00376     for (j = 0; j < 20; j++)
00377     {
00378       next = fli2.play(win, 0, 0, next, j*5);
00379       win->show();
00380       if (wait_delay (0))
00381         throw UserBreakException();
00382     }
00383 
00384     // Guard walks in
00385     for (j = 0; j < 37; j++)
00386     {
00387       next = fli2.play(win, j, j, next);
00388       win->show();
00389       if (wait_delay (0))
00390         throw UserBreakException();
00391     }
00392 
00393     // Guard walks in
00394     const char *my_leige = "My leige";
00395     const char *yo_homes = "Yo, homes";
00396 
00397     if (speech && !jive)
00398     {
00399       U7object voc_my_leige("<STATIC>/intro.dat", 16);
00400       buffer = (uint8 *) voc_my_leige.retrieve (size);
00401       Audio::get_ptr()->play (buffer+8, size-8, false);
00402       FORGET_ARRAY(buffer);
00403     }
00404 
00405 
00406     for (; j < 55; j++)
00407     {
00408       next = fli2.play(win, j, j, next);
00409 
00410       if (jive)
00411         sifont->draw_text(ibuf, centerx+30, centery+87, yo_homes);
00412       else if (!speech)
00413         sifont->draw_text(ibuf, centerx+30, centery+87, my_leige);
00414 
00415       win->show();
00416       if (wait_delay (0))
00417         throw UserBreakException();
00418     }
00419 
00420     next = fli2.play(win, j, j, next);
00421     win->show();
00422 
00423     const char *all_we[2] = { "All we found among Batlin's",
00424           "belongings was this enchanted scroll.." };
00425 
00426     if (speech && !jive)
00427     {
00428       U7object voc_all_we("<STATIC>/intro.dat", 17);
00429       buffer = (uint8 *) voc_all_we.retrieve (size);
00430       Audio::get_ptr()->play (buffer+8, size-8, false);
00431       FORGET_ARRAY(buffer);
00432     }
00433 
00434     for (; j < 73; j++)
00435     {
00436       next = fli2.play(win, j, j, next);
00437 
00438       if (!speech || jive)
00439       {
00440         sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(all_we[0]), centery+74, all_we[0]);
00441         sifont->draw_text(ibuf, centerx+160-sifont->get_text_width(all_we[1]), centery+87, all_we[1]);
00442       }
00443 
00444       win->show();
00445       if (wait_delay (0))
00446         throw UserBreakException();
00447     }
00448     for (i = 0; i < 220; i++)
00449       if (wait_delay (10))
00450         throw UserBreakException();
00451 
00452     const char *and_a[2] = { "and a map showing the way to",
00453           "a place called the Serpent Isle" };
00454 
00455     next = fli2.play(win, j, j, next);
00456 
00457     if (!speech || jive)
00458     {
00459       sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(and_a[0]), centery+74, and_a[0]);
00460       sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(and_a[1]), centery+87, and_a[1]);
00461     }
00462 
00463     win->show();
00464     j++;
00465     
00466     for (i = 0; i < 290; i++)
00467       if (wait_delay (10))
00468         throw UserBreakException();
00469 
00470 
00471     fli2.play(win, j, j);
00472     j++;
00473 
00474     for (i = 0; i < 50; i++)
00475       if (wait_delay (10))
00476         throw UserBreakException();
00477 
00478     const char *indeed[2] = { "Indeed.",
00479           "Put it on the table." };
00480 
00481     const char *iree = "Iree. Slap it down there!";
00482 
00483     if (speech && !jive)
00484     {
00485       U7object voc_indeed("<STATIC>/intro.dat", 18);
00486       buffer = (uint8 *) voc_indeed.retrieve(size);
00487       Audio::get_ptr()->play (buffer+8, size-8, false);
00488       FORGET_ARRAY(buffer);
00489     }
00490 
00491     next = fli2.play(win, j, j);
00492     j++;
00493     
00494     for (; j < 81; j++)
00495     {
00496       next = fli2.play(win, j, j, next);
00497 
00498       if (jive)
00499         sifont->draw_text(ibuf, topx+40, centery+74, iree);
00500       else if (!speech)
00501       {
00502         sifont->draw_text(ibuf, topx+40, centery+74, indeed[0]);
00503         sifont->draw_text(ibuf, topx+40, centery+87, indeed[1]);
00504       }
00505 
00506       win->show();
00507       if (wait_delay (0))
00508         throw UserBreakException();
00509     }
00510 
00511     for (i = 0; i < 200; i++)
00512       if (wait_delay (10))
00513         throw UserBreakException();
00514 
00515     FORGET_ARRAY(fli_b);
00516 
00517     // Do this! Prevents palette corruption
00518     gwin->clear_screen(true);
00519 
00520     // Scroll opens
00521     U7object flic3("<STATIC>/intro.dat", 3);
00522     fli_b = flic3.retrieve(flisize);
00523     playfli fli3(fli_b+8, flisize-8);
00524     fli3.info();
00525 
00526     next = 0;
00527 
00528     // Scroll opens
00529     for (j = 0; j < 20; j++)
00530     {
00531       next = fli3.play(win, j, j, next)+20;
00532       win->show();
00533       if (wait_delay (0))
00534         throw UserBreakException();
00535     }
00536 
00537 
00538     // 'Stand Back'
00539     const char *stand_back = "Stand Back!";
00540     const char *jump_back = "Jump Back!";
00541 
00542     if (speech && !jive)
00543     {
00544       U7object voc_stand_back("<STATIC>/intro.dat", 19);
00545       buffer = (uint8 *) voc_stand_back.retrieve(size);
00546       Audio::get_ptr()->play (buffer+8, size-8, false);
00547       FORGET_ARRAY(buffer);
00548     }
00549 
00550     for (; j < 61; j++)
00551     {
00552       next = fli3.play(win, j, j, next)+20;
00553 
00554       if (jive)
00555         sifont->draw_text(ibuf, topx+70, centery+60, jump_back);
00556       else if (!speech) 
00557         sifont->draw_text(ibuf, topx+70, centery+60, stand_back);
00558 
00559       win->show();
00560       if (wait_delay (0))
00561         throw UserBreakException();
00562     }
00563 
00564     FORGET_ARRAY(fli_b);
00565 
00566     // Do this! Prevents palette corruption
00567     gwin->clear_screen(true);
00568 
00569     // Big G speaks
00570     U7object flic4("<STATIC>/intro.dat", 4);
00571     fli_b = flic4.retrieve(flisize);
00572     playfli fli4(fli_b+8, flisize-8);
00573     fli4.info();
00574 
00575     U7object shapes("<STATIC>/intro.dat", 30);
00576     shape_buf = shapes.retrieve(shapesize);
00577     BufferDataSource gshape_ds(shape_buf+8, shapesize-8);
00578     Shape_frame *sf;
00579   
00580     Shape_file gshape(&gshape_ds);
00581     
00582     cout << "Shape in intro.dat has " << gshape.get_num_frames() << endl;
00583 
00584     if (speech && !jive)
00585     {
00586       U7object voc_big_g("<STATIC>/intro.dat", 20);
00587       buffer = (uint8 *) voc_big_g.retrieve ( size);
00588       Audio::get_ptr()->play (buffer+8, size-8, false);
00589       FORGET_ARRAY(buffer);
00590     }
00591 
00592     next = 0;
00593 
00594     // Batlin...
00595     const char *batlin[2] = { "Batlin! In the event that the",
00596           "Avatar destroys the Black Gate" };
00597 
00598     const char *you_shall[2] = { "you shall follow the unwitting",
00599           "human Gwenno to the Serpent Isle" };
00600 
00601     const char *there_i[2] = { "There I shall outline my plan",
00602           "to destroy Britannia!" };
00603 
00604 
00605     const char *batlin2[2] = { "Batlin! Know that my face is most",
00606           "muppet like!" };
00607 
00608     const char *you_must[2] = { "You must go to the Serpent Isle",
00609           "to learn the secret of Acne Medication" };
00610 
00611     const char *soon_i[2] = { "Soon I and my horde of muppets will",
00612           "destroy Britannia!" };
00613 
00614     for (j = 0; j < 320; j++)
00615     {
00616       next = fli4.play(win, j%40, j%40, next);
00617 
00618       if (j < 300)
00619         sf = gshape.get_frame((j/2)%7);
00620       else
00621         sf = gshape.get_frame(0);
00622 
00623       if (sf)
00624         sman->paint_shape (centerx-36, centery, sf);
00625 
00626       if (j < 100 && jive)
00627       {
00628         sifont->center_text(ibuf, centerx, centery+74, batlin2[0]);
00629         sifont->center_text(ibuf, centerx, centery+87, batlin2[1]);
00630       }
00631       else if (j < 200 && jive)
00632       {
00633         sifont->center_text(ibuf, centerx, centery+74, you_must[0]);
00634         sifont->center_text(ibuf, centerx, centery+87, you_must[1]);
00635       }
00636       else if (j < 300 && jive)
00637       {
00638         sifont->center_text(ibuf, centerx, centery+74, soon_i[0]);
00639         sifont->center_text(ibuf, centerx, centery+87, soon_i[1]);
00640       }
00641       else if (j < 100 && !speech)
00642       {
00643         sifont->center_text(ibuf, centerx, centery+74, batlin[0]);
00644         sifont->center_text(ibuf, centerx, centery+87, batlin[1]);
00645       }
00646       else if (j < 200 && !speech)
00647       {
00648         sifont->center_text(ibuf, centerx, centery+74, you_shall[0]);
00649         sifont->center_text(ibuf, centerx, centery+87, you_shall[1]);
00650       }
00651       else if (j < 300 && !speech)
00652       {
00653         sifont->center_text(ibuf, centerx, centery+74, there_i[0]);
00654         sifont->center_text(ibuf, centerx, centery+87, there_i[1]);
00655       }
00656 
00657       win->show();
00658       if (wait_delay (0))
00659         throw UserBreakException();
00660     }
00661     sf = gshape.get_frame(0);
00662 
00663     for (j = 20; j; j--)
00664     {
00665       next = fli4.play(win, 0, 0, next, j*5);
00666       if (sf)
00667         sman->paint_shape (centerx-36, centery, sf);
00668 
00669       win->show();
00670       if (wait_delay (0))
00671         throw UserBreakException();
00672     }
00673 
00674     FORGET_ARRAY(shape_buf);
00675     FORGET_ARRAY(fli_b);
00676     
00677     // Do this! Prevents palette corruption
00678     gwin->clear_screen(true);
00679 
00680     // Tis LBs's Worst fear
00681     U7object flic5("<STATIC>/intro.dat", 5);
00682     fli_b = flic5.retrieve(flisize);
00683     playfli fli5(fli_b+8, flisize-8);
00684     fli5.info();
00685 
00686     for (j=0; j < 20; j++)
00687     {
00688       next = fli5.play(win, 0, 0, next, j*5);
00689 
00690       win->show();
00691       if (wait_delay (0))
00692         throw UserBreakException();
00693     }
00694 
00695 
00696     const char *tis_my[3] = {"'Tis my worst fear!",
00697           "I must send the Avatar through",
00698           "the pillars to the Serpent Isle!" };
00699 
00700 
00701     if (speech && !jive)
00702     {
00703       U7object voc_tis_my("<STATIC>/intro.dat", 21);
00704       buffer = (uint8 *) voc_tis_my.retrieve(size);
00705       Audio::get_ptr()->play (buffer+8, size-8, false);
00706       FORGET_ARRAY(buffer);
00707     }
00708 
00709     for (j=0; j < 61; j++)
00710     {
00711       next = fli5.play(win, j, j, next)+30;
00712 
00713       if (j < 20 && (!speech || jive))
00714       {
00715         sifont->center_text(ibuf, centerx, centery+74, tis_my[0]);
00716       }
00717       else if (j > 22 && (!speech || jive))
00718       {
00719         sifont->center_text(ibuf, centerx, centery+74, tis_my[1]);
00720         sifont->center_text(ibuf, centerx, centery+87, tis_my[2]);
00721       }
00722 
00723       win->show();
00724       if (wait_delay (0))
00725         throw UserBreakException();
00726     }
00727 
00728     FORGET_ARRAY(fli_b);
00729 
00730     // Do this! Prevents palette corruption
00731     gwin->clear_screen(true);
00732 
00733     // Boat 1
00734     U7object flic6("<STATIC>/intro.dat", 6);
00735     fli_b = flic6.retrieve(flisize);
00736     playfli fli6(fli_b+8, flisize-8);
00737     fli6.info();
00738 
00739     for (j=0; j < 61; j++)
00740     {
00741       next = fli6.play(win, j, j, next)+30;
00742 
00743       win->show();
00744       if (wait_delay (0))
00745         throw UserBreakException();
00746     }
00747 
00748     FORGET_ARRAY(fli_b);
00749 
00750     // Do this! Prevents palette corruption
00751     gwin->clear_screen(true);
00752 
00753     // Boat 2
00754     U7object flic7("<STATIC>/intro.dat", 7);
00755     fli_b = flic7.retrieve(flisize);
00756     playfli fli7(fli_b+8, flisize-8);
00757     fli7.info();
00758 
00759     const char *zot = "Zot!";
00760 
00761     for (j=0; j < 61; j++)
00762     {
00763       next = fli7.play(win, j, j, next)+30;
00764 
00765       if (j > 55 && jive)
00766         sifont->center_text(ibuf, centerx, centery+74, zot);
00767 
00768       win->show();
00769       if (wait_delay (0))
00770         throw UserBreakException();
00771     }
00772 
00773     FORGET_ARRAY(fli_b);
00774 
00775     // Do this! Prevents palette corruption
00776     gwin->clear_screen(true);
00777 
00778     // Ultima VII Part 2
00779     U7object flic8("<STATIC>/intro.dat", 8);
00780     fli_b = flic8.retrieve(flisize);
00781     playfli fli8(fli_b+8, flisize-8);
00782     fli8.info();
00783 
00784     for (j = 0; j < 20; j++)
00785     {
00786       next = fli8.play(win, 0, 0, next, j*5);
00787       font->center_text(ibuf, centerx, centery+75, txt_msg[2]);
00788       win->show();
00789     }
00790 
00791 
00792     next = fli8.play(win, 0, 0, next, 100);
00793     font->center_text(ibuf, centerx, centery+75, txt_msg[2]);
00794     win->show();
00795 
00796     for (i = 0; i < 300; i++)
00797       if (wait_delay (10))
00798         throw UserBreakException();
00799 
00800 
00801     for (j = 20; j; j--)
00802     {
00803       next = fli8.play(win, 0, 0, next, j*5);
00804       font->center_text(ibuf, centerx, centery+75, txt_msg[2]);
00805       win->show();
00806     }
00807     
00808     FORGET_ARRAY(fli_b);
00809   }
00810   catch(const UserBreakException &x)
00811   {
00812     FORGET_ARRAY(shape_buf);
00813     FORGET_ARRAY(fli_b);
00814     FORGET_ARRAY(buffer);
00815   }
00816   
00817   // Fade out the palette...
00818 //  pal.fade_out(c_fade_out_time);
00819 // this doesn't work right ATM since the FLIC player has its own palette handling
00820 
00821   
00822   // ... and clean the screen.
00823   gwin->clear_screen(true);
00824   
00825   // Stop all audio output
00826   Audio::get_ptr()->cancel_streams();
00827 }
00828 
00829 void SI_Game::top_menu()
00830 {
00831   play_midi(28, true);
00832   sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
00833   pal->load(MAINSHP_FLX,26);
00834   pal->fade_in(60); 
00835 }
00836 
00837 void SI_Game::show_journey_failed()
00838 {
00839     pal->fade_out(50);
00840   sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
00841   journey_failed_text();
00842 }
00843 
00844 /*
00845  *  ExCineLite
00846  */
00847 
00848 // ExCineEvent
00849 struct ExCineEvent {
00850   uint32      time; // Time to start, In MS
00851   char      *file;
00852   int     index;
00853 
00854   virtual bool  play_it(Image_window *win, int time) = 0;   // Return true if screen updated
00855 
00856   bool can_play() { return file != 0; }
00857 
00858   ExCineEvent(uint32 t, char*f, int i) :
00859     time(t), file(f), index(i)  { }
00860 
00861   virtual ~ExCineEvent() { }
00862 };
00863 
00864 //
00865 // ExCineFlic
00866 //
00867 
00868 struct ExCineFlic : public ExCineEvent {
00869 private:
00870   int start;    // First frame to play
00871   int count;    // Number of frames
00872   bool  repeat;   // Repeat?
00873   int cur;    // Frame currently being displayed (note, it's not the actual frame)
00874   int speed;    // Speed of playback (ms per frame)
00875 
00876   // Data info
00877   U7object  *flic_obj;
00878   size_t    size;
00879   char    *buffer;
00880   playfli   *player;
00881 
00882 public:
00883   virtual bool  play_it(Image_window *win, int t);
00884 
00885   void    load_flic(void);
00886   void    free_flic(void);
00887 
00888   void    fade_out(int cycles);
00889 
00890   ExCineFlic(uint32 time, char *file, int i, int s, int c, bool r, int spd) :
00891     ExCineEvent(time, file, i), start(s), count(c), repeat(r), cur(-1), speed(spd),
00892     flic_obj(0), size(0), buffer(0), player(0) { }
00893 
00894   ExCineFlic(uint32 time) : ExCineEvent(time, 0, 0), start(0), count(0),
00895         repeat(false), cur(0), speed(0),
00896         flic_obj(0), size(0), buffer(0), player(0) { }
00897 
00898   virtual ~ExCineFlic() {
00899     free_flic();
00900   }
00901 };
00902 
00903 void ExCineFlic::load_flic()
00904 {
00905   free_flic();
00906 
00907   if (file) COUT("Loading " << file << ":" << index);
00908 
00909   flic_obj = new U7object(file, index);
00910 
00911   buffer = flic_obj->retrieve(size);
00912 
00913   player = new playfli(buffer+8, size-8);
00914   player->info();
00915 }
00916 
00917 void ExCineFlic::free_flic()
00918 {
00919   if (file) COUT("Freeing " << file << ":" << index);
00920 
00921   FORGET_OBJECT(player);
00922   FORGET_ARRAY(buffer);
00923   size = 0;
00924   FORGET_OBJECT(flic_obj);
00925 }
00926 
00927 bool  ExCineFlic::play_it(Image_window *win, int t)
00928 {
00929   if (t < time) return false;
00930 
00931   if (cur+1 < count || repeat) {
00932 
00933     // Only advance frame if we can
00934     int time_next = time + (cur+1) * speed;
00935     if (time_next <= t) {
00936       cur++;
00937 
00938       // The actual frame number
00939       int actual = start + (cur%count);
00940 
00941       player->play(win, actual, actual, 0);
00942 
00943       return true;
00944     }
00945   }
00946 
00947   player->put_buffer(win);
00948 
00949   return false;
00950 }
00951 
00952 void ExCineFlic::fade_out(int cycles)
00953 {
00954   if (player) player->get_palette()->fade_out(cycles);
00955 }
00956 
00957 //
00958 // ExCineVoc
00959 //
00960 
00961 struct ExCineVoc : public ExCineEvent {
00962 private:
00963   bool    played;
00964 
00965 public:
00966   virtual bool  play_it(Image_window *win, int t);
00967 
00968   ExCineVoc(uint32 time, char *f, int index) :
00969     ExCineEvent(time, file, index), played(false) { }
00970 
00971   virtual ~ExCineVoc() { }
00972 };
00973 
00974 bool ExCineVoc::play_it(Image_window *win, int t)
00975 {
00976   size_t  size;
00977   U7object voc("<STATIC>/intro.dat", index);
00978   uint8 *buffer = (uint8 *) voc.retrieve (size);
00979   Audio::get_ptr()->play (buffer+8, size-8, false);
00980   FORGET_ARRAY(buffer);
00981   played = true;
00982 
00983   return false;
00984 }
00985 
00986 //
00987 // Serpent Isle Endgame
00988 //
00989 void SI_Game::end_game(bool success) 
00990 {
00991   int next = 0;
00992 
00993   Font  *font = fontManager.get_font("MENU_FONT");
00994   Font  *sifont = fontManager.get_font("SIINTRO_FONT");
00995 
00996   bool speech = Audio::get_ptr()->is_speech_enabled();
00997 
00998   gwin->clear_screen(true);
00999   
01000 
01001 /* Endgame General Timings (in ms)
01002 
01003       0 - Avatar floating right
01004    6350 - Begin Serpent Swirling
01005   10850 - Serpent Comes on screen
01006   14643 - Balanced, and "there we are done"
01007   17281 - "balance is restored"
01008   21300 - "serpent isle"
01009   22900 - "briatnnia"
01010   24300 - "your earth"
01011   26000 - "the entire universe"
01012   28600 - "all are phased"
01013   31600 - Avatar floating right, "worry not about your friend dupre"
01014   35100 - "he is one with us"
01015   37000 - "and content"
01016   39800 - "good bye avatar"
01017   42040 - "we thank you"
01018   48550 - "well well well avatar"
01019   48900 - Avatar floating left
01020   51750 - "You have managed to thawt me one again"
01021   55500 - "by restoring balance..."
01022   62500 - floating far, "but now here you are"
01023   64500 - "poised at the edge of eternity"
01024   67000 - "where would you go?"
01025   70250 - floating left, "back to britannia?"
01026   72159 - "to earth?"
01027   74750 - "perhaps you would join me.."
01028   75500 - big g's hand
01029   78000 - "we do have a score to settle"
01030 
01031 Flic Index
01032 9 = Avfloat
01033 10 = snake1
01034 11 = snake2
01035 12 = avfar
01036 13 = xavgrab
01037 
01038 Frame count : 61
01039 Width :       320
01040 Height :      200
01041 Depth :       8
01042 Speed :       5
01043 
01044 Frame count : 156
01045 Width :       320
01046 Height :      200
01047 Depth :       8
01048 Speed :       8
01049 
01050 Frame count : 4
01051 Width :       320
01052 Height :      200
01053 Depth :       8
01054 Speed :       10
01055 
01056 Frame count : 61
01057 Width :       320
01058 Height :      200
01059 Depth :       8
01060 Speed :       5
01061 
01062 Frame count : 121
01063 Width :       320
01064 Height :      200
01065 Depth :       8
01066 Speed :       5
01067 
01068 Sound Index
01069 22 = "there we are done, balance is restored"
01070 23 = "serpent isle...."
01071 24 = "goodbye avatar..."
01072 25 = "well well well avatar..."
01073 26 = "by restoring balance..."
01074 27 = "but now here you are..."
01075 28 = "back to britannia..."
01076 29 = "perhaps you..."
01077 
01078 
01079       0 - Repeat 9
01080    6350 - Play 10
01081   14643 - Repeat 10, Play 22
01082   21300 - Play 23
01083   31600 - Repeat 9
01084   39800 - Repeat 11, Play 24
01085   48550 - Play 25
01086   48900 - Repeat 13
01087   55500 - Play 26
01088   62500 - Repeat 12, play 27
01089   70250 - Play 13, play 28
01090   72159 - "to earth?"
01091   74750 - play 29
01092   75500 - big g's hand
01093   78000 - "we do have a score to settle"
01094 
01095 */
01096 
01097   // Flic List
01098   ExCineFlic flics[] = {
01099     ExCineFlic(0, "<STATIC>/intro.dat", 9, 0, 61, true, 75),
01100     ExCineFlic(6350, "<STATIC>/intro.dat", 10, 0, 156, false, 95),
01101     ExCineFlic(21170, "<STATIC>/intro.dat", 9, 0, 61, true, 75),
01102     ExCineFlic(39800, "<STATIC>/intro.dat", 11, 0, 4, true, 75),
01103     ExCineFlic(48900, "<STATIC>/intro.dat", 13, 0, 61, true, 75),
01104     ExCineFlic(62500, "<STATIC>/intro.dat", 12, 0, 61, true, 75),
01105     ExCineFlic(70250, "<STATIC>/intro.dat", 13, 0, 121, false, 75),
01106     ExCineFlic(82300)
01107   };
01108   int last_flic = 7;
01109   int cur_flic = -1;
01110   ExCineFlic *flic = 0;
01111   ExCineFlic *pal_flic = 0;
01112 
01113   // Voc List
01114   ExCineVoc vocs[] = {
01115     ExCineVoc(14700, "<STATIC>/intro.dat", 22),
01116     ExCineVoc(21300, "<STATIC>/intro.dat", 23),
01117     ExCineVoc(39800, "<STATIC>/intro.dat", 24),
01118     ExCineVoc(47700, "<STATIC>/intro.dat", 25),
01119     ExCineVoc(55400, "<STATIC>/intro.dat", 26),
01120     ExCineVoc(62500, "<STATIC>/intro.dat", 27),
01121     ExCineVoc(70250, "<STATIC>/intro.dat", 28),
01122     ExCineVoc(74750, "<STATIC>/intro.dat", 29)
01123   };
01124   int last_voc = 7;
01125   int cur_voc = -1;
01126 
01127   // Stop previous music
01128   Audio::get_ptr()->stop_music();
01129 
01130   // Start the music
01131   Audio *audio = Audio::get_ptr();
01132   if (audio) {
01133     const char *fn = "<STATIC>/r_send.xmi";
01134     MyMidiPlayer *midi = audio->get_midi();
01135     if (midi && midi->is_fm_synth()) fn = "<STATIC>/a_send.xmi";
01136     audio->start_music (fn, 0, false);
01137   }
01138 
01139 
01140   int start_time = SDL_GetTicks();
01141 
01142   while (1) {
01143 
01144     int time = SDL_GetTicks() - start_time;
01145 
01146     // Need to go to the next flic?
01147     if (cur_flic < last_flic && flics[cur_flic+1].time <= time) {
01148 
01149       bool next_play = flics[cur_flic+1].can_play();
01150 
01151       // Can play the new one, don't need the old one anymore
01152       if(next_play) {
01153         // Free it
01154         if (flic) flic->free_flic();
01155 
01156         // Free the palette too, if we need to
01157         if (pal_flic && pal_flic != flic)
01158           pal_flic->free_flic();
01159 
01160         pal_flic = 0;
01161       }
01162       // Set palette to prev if required
01163       else if (flic && flic->can_play()) {
01164         pal_flic = flic;
01165       }
01166       // Previous flic didn't have a palette, so free it anyway
01167       else if (flic) {
01168         flic->free_flic();
01169       }
01170       
01171       cur_flic++;
01172       flic = flics+cur_flic;
01173 
01174       if (next_play) {
01175         // Clear the screen to prevent palette corruption
01176         gwin->clear_screen(true);
01177 
01178         // Load the flic, and set pal_flic
01179         (pal_flic = flic)->load_flic();
01180       }
01181       else COUT("Teminator ");
01182       COUT("Flic at time: " << flic->time);
01183     }
01184 
01185     // Need to go to the next voc?
01186     if (cur_voc < last_voc && vocs[cur_voc+1].time <= time) {
01187       cur_voc++;
01188       ExCineVoc *voc = vocs+cur_voc;
01189 
01190       // Just play it!
01191       voc->play_it(NULL, time);
01192       //else COUT("Teminator ");
01193       COUT("voc at time: " << voc->time);
01194       
01195     }
01196 
01197     // We've finished
01198     if (cur_flic == last_flic && cur_voc == last_voc) {
01199       // Do a fade out
01200       if (pal_flic && pal_flic->can_play()) pal_flic->fade_out(100);
01201 
01202       COUT("Finished!" << std::endl);
01203       break;
01204     }
01205 
01206     // Play the flic if possible
01207 
01208     bool updated = false;
01209 
01210     if (flic->can_play()) updated = flic->play_it(win, time);
01211 
01212     if (updated) win->show();
01213 
01214     if (wait_delay (0)) {
01215 
01216       // Do a quick fade out
01217       if (pal_flic && pal_flic->can_play()) pal_flic->fade_out(20);
01218       break;
01219     }
01220   }
01221 
01222   gwin->clear_screen(true);
01223 
01224   // Stop all sounds
01225   Audio::get_ptr()->cancel_streams();
01226 
01227   // Stop music
01228   Audio::get_ptr()->stop_music();
01229 }
01230 
01231 void SI_Game::show_quotes()
01232   {
01233     play_midi(32);
01234     TextScroller quotes(MAINSHP_FLX, 0x10, 
01235            fontManager.get_font("MENU_FONT"),
01236            menushapes.extract_shape(0x14)
01237           );
01238     quotes.run(gwin);
01239   }
01240 
01241 void SI_Game::show_credits()
01242   {
01243     play_midi(30);
01244     TextScroller credits(MAINSHP_FLX, 0x0E, 
01245            fontManager.get_font("MENU_FONT"),
01246            menushapes.extract_shape(0x14)
01247           );
01248     if(credits.run(gwin)) { // Watched through the entire sequence?
01249       std::ofstream quotesflg;
01250       U7open(quotesflg, "<SAVEGAME>/quotes.flg");
01251       quotesflg.close();
01252     }
01253   }
01254 
01255 bool SI_Game::new_game(Vga_file &shapes)
01256 {
01257   SDL_EnableUNICODE(1);
01258 
01259   int menuy = topy+110;
01260   Font *font = fontManager.get_font("MENU_FONT");
01261 
01262   Vga_file faces_vga(FACES_VGA);
01263   
01264   const int max_len = 16;
01265   char npc_name[max_len+1];
01266   char disp_name[max_len+2];
01267   npc_name[0] = 0;
01268   int sex = 0;
01269   int selected = 0;
01270   int num_choices = 4;
01271   //pal.load("<STATIC>/intropal.dat",6);
01272   SDL_Event event;
01273   bool editing = true;
01274   bool redraw = true;
01275   bool ok = true;
01276   do
01277   {
01278     if (redraw)
01279     {
01280       gwin->clear_screen();
01281       sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
01282       sman->paint_shape(topx+10,menuy+10,shapes.get_shape(0xC, selected==0?1:0));
01283       sman->paint_shape(topx+10,menuy+25,shapes.get_shape(0x19, selected==1?1:0));
01284       Shape_frame *sh = faces_vga.get_shape(0,sex);
01285       sman->paint_shape(topx+300,menuy+50,sh);
01286       sman->paint_shape(topx+10,topy+180,shapes.get_shape(0x8,selected==2?1:0));
01287       sman->paint_shape(centerx+10,topy+180,shapes.get_shape(0x7,selected==3?1:0));
01288       if(selected==0)
01289         snprintf(disp_name, max_len+2, "%s_", npc_name);
01290       else
01291         snprintf(disp_name, max_len+2, "%s", npc_name);
01292       font->draw_text(ibuf, topx+60, menuy+10, disp_name);
01293       pal->apply();
01294       redraw = false;
01295     }
01296     SDL_WaitEvent(&event);
01297     if(event.type==SDL_KEYDOWN)
01298     {
01299       redraw = true;
01300       switch(event.key.keysym.sym)
01301       {
01302       case SDLK_SPACE:
01303         if(selected==0)
01304         {
01305           int len = strlen(npc_name);
01306           if(len<max_len)
01307           {
01308             npc_name[len] = ' ';
01309             npc_name[len+1] = 0;
01310           }
01311         }
01312         else if(selected==1)
01313         {
01314           ++sex;
01315           if(sex>5)
01316             sex = 0;
01317         }
01318         break;
01319       case SDLK_LEFT:
01320         if(selected==1)
01321         {
01322           --sex;
01323           if(sex<0)
01324             sex = 5;
01325         }
01326         break;
01327       case SDLK_RIGHT:
01328         if(selected==1)
01329         {
01330           ++sex;
01331           if(sex>5)
01332             sex = 0;
01333         }
01334         break;
01335       case SDLK_ESCAPE:
01336         editing = false;
01337         ok = false;
01338         break;
01339       case SDLK_DOWN:
01340         ++selected;
01341         if(selected==num_choices)
01342           selected = 0;
01343         break;
01344       case SDLK_UP:
01345         --selected;
01346         if(selected<0)
01347           selected = num_choices-1;
01348         break;
01349       case SDLK_RETURN:
01350         if(selected<2) 
01351           ++selected;
01352         else if(selected==2)
01353         {
01354           editing=false;
01355           ok = true;
01356         }
01357         else
01358         {
01359           editing = false;
01360           ok = false;
01361         }
01362         break;
01363       case SDLK_BACKSPACE:
01364         if(selected==0)
01365         {
01366           if(strlen(npc_name)>0)
01367             npc_name[strlen(npc_name)-1] = 0;
01368         }
01369         break;
01370       default:
01371         {
01372           if (selected == 0) // on the text input field?
01373           {
01374             int len = strlen(npc_name);
01375             char chr = 0;
01376 
01377             if ((event.key.keysym.unicode & 0xFF80) == 0)
01378               chr = event.key.keysym.unicode & 0x7F;
01379 
01380             if (chr >= ' ' && len < max_len)
01381             {
01382               npc_name[len] = chr;
01383               npc_name[len+1] = 0;
01384             }
01385           }
01386           else
01387           {
01388             redraw = false;
01389           }
01390         }
01391         break;
01392       }
01393     }
01394   }
01395   while(editing);
01396 
01397   gwin->clear_screen();
01398   sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0));
01399 
01400   if(ok)
01401   {
01402     set_avname (npc_name);
01403     set_avsex (1-(sex%2));
01404     set_avskin (sex/2);
01405     pal->fade_out(c_fade_out_time);
01406     gwin->clear_screen(true); 
01407     ok = gwin->init_gamedat(true);
01408   }
01409 
01410   SDL_EnableUNICODE(0);
01411 
01412   return ok;
01413 }
01414 
01415 bool SI_Game::is_installed()
01416 {
01417   std::string buf("<SERPENTISLE_STATIC>/sispeech.spc");
01418   bool foundsi = U7exists(buf);
01419   bool foundsiflx = U7exists("<DATA>/exult_si.flx");
01420 
01421   if (foundsi)
01422     std::cout << "Serpent Isle : found" << std::endl;
01423   else
01424     std::cout << "Serpent Isle : not found (" 
01425           << get_system_path(buf) << ")" << std::endl;
01426 
01427   if (foundsiflx)
01428     std::cout << "exult_si.flx : found" << std::endl;
01429   else
01430     std::cout << "exult_si.flx : not found (" 
01431           << get_system_path("<DATA>/exult_si.flx")
01432           << ")" << std::endl;
01433 
01434   return (foundsi && foundsiflx);
01435 }

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