00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023
00024 #ifndef ALPHA_LINUX_CXX
00025 # include <cstdlib>
00026 # include <cstring>
00027 # include <unistd.h>
00028 #endif
00029 #include "menulist.h"
00030 #include "Audio.h"
00031 #include "Configuration.h"
00032 #include "databuf.h"
00033 #include "exult.h"
00034 #include "exult_flx.h"
00035 #include "files/U7file.h"
00036 #include "files/utils.h"
00037 #include "flic/playfli.h"
00038 #include "font.h"
00039 #include "game.h"
00040 #include "bggame.h"
00041 #include "sigame.h"
00042 #include "devgame.h"
00043 #include "gamewin.h"
00044 #include "keys.h"
00045 #include "mouse.h"
00046 #include "palette.h"
00047 #include "shapeid.h"
00048
00049 #ifndef UNDER_CE
00050 using std::cout;
00051 using std::endl;
00052 using std::ifstream;
00053 using std::strcmp;
00054 using std::strcpy;
00055 using std::strncmp;
00056 using std::string;
00057 #endif
00058
00059 bool Game::new_game_flag = false;
00060 bool Game::editing_flag = false;
00061 Game *game = 0;
00062 Exult_Game Game::game_type = BLACK_GATE;
00063 bool Game::expansion = false;
00064
00065 static char av_name[17] = "";
00066 static int av_sex = -1;
00067 static int av_skin = -1;
00068
00069 std::string Game::gametitle;
00070
00071 unsigned int Game::ticks = 0;
00072
00073 Game::Game() : menushapes()
00074 {
00075 try {
00076 menushapes.load(MAINSHP_FLX);
00077 } catch (const exult_exception &e) {
00078 if (!is_editing())
00079 throw e;
00080 }
00081 jive = false;
00082 gwin = Game_window::get_instance();
00083 win = gwin->get_win();
00084 ibuf = win->get_ib8();
00085 topx = (gwin->get_width()-320)/2;
00086 topy = (gwin->get_height()-200)/2;
00087 centerx = gwin->get_width()/2;
00088 centery = gwin->get_height()/2;
00089 }
00090
00091 Game::~Game()
00092 {
00093 }
00094
00095 Game *Game::create_game(Exult_Game mygame, const char *title)
00096 {
00097 switch(mygame) {
00098 case EXULT_DEVEL_GAME:
00099 assert(title != 0);
00100 gametitle = title;
00101 game_type = mygame;
00102 break;
00103 case SERPENT_ISLE:
00104 gametitle = "serpentisle";
00105 break;
00106 case BLACK_GATE:
00107 default:
00108 gametitle = "blackgate";
00109 break;
00110 }
00111
00112
00113 string d("config/disk/game/" + gametitle + "/editing");
00114 config->value(d.c_str(), editing_flag, false);
00115
00116
00117 string system_path_tag(gametitle);
00118 to_uppercase(system_path_tag);
00119 clone_system_path("<STATIC>", "<" + system_path_tag + "_STATIC>");
00120 clone_system_path("<GAMEDAT>", "<" + system_path_tag + "_GAMEDAT>");
00121 clone_system_path("<SAVEGAME>", "<" + system_path_tag + "_SAVEGAME>");
00122 if (is_system_path_defined("<" + system_path_tag + "_PATCH>"))
00123 clone_system_path("<PATCH>", "<" + system_path_tag + "_PATCH>");
00124 else
00125 clear_system_path("<PATCH>");
00126
00127 U7mkdir("<SAVEGAME>", 0755);
00128
00129
00130
00131 if (game_type != EXULT_DEVEL_GAME) {
00132 char *static_identity = Game_window::get_game_identity(
00133 INITGAME);
00134
00135 if (!strcmp(static_identity," ULTIMA7")) {
00136 game_type = BLACK_GATE;
00137 expansion = false;
00138 } else if (!strcmp(static_identity, "FORGE")) {
00139 game_type = BLACK_GATE;
00140 expansion = true;
00141 } else if (!strcmp(static_identity, "SERPENT ISLE")) {
00142 game_type = SERPENT_ISLE;
00143 expansion = false;
00144 } else if (!strcmp(static_identity, "SILVER SEED")) {
00145 game_type = SERPENT_ISLE;
00146 expansion = true;
00147 }
00148 delete[] static_identity;
00149 }
00150 switch(game_type) {
00151 case BLACK_GATE:
00152 cout << "Starting a BLACK GATE game" << endl;
00153 game = new BG_Game();
00154 break;
00155 case SERPENT_ISLE:
00156 cout << "Starting a SERPENT ISLE game" << endl;
00157 game = new SI_Game();
00158 break;
00159 case EXULT_DEVEL_GAME:
00160 cout << "Starting '" << gametitle << "' game" << endl;
00161 game = new DEV_Game();
00162 break;
00163 default:
00164 game = 0;
00165 }
00166
00167 std::cout << "Game path settings:" << std::endl;
00168 std::cout << "Static : " << get_system_path("<STATIC>") << std::endl;
00169 std::cout << "Gamedat : " << get_system_path("<GAMEDAT>") << std::endl;
00170 std::cout << "Savegame: " << get_system_path("<SAVEGAME>") << std::endl;
00171 if (is_system_path_defined("<PATCH>"))
00172 std::cout << "Patch : " << get_system_path("<PATCH>") << std::endl;
00173 else
00174 std::cout << "Patch : none" << std::endl;
00175 std::cout << std::endl;
00176
00177
00178 Audio *audio = Audio::get_ptr();
00179
00180 if (audio) {
00181 MyMidiPlayer *midi = audio->get_midi();
00182 if (midi) midi->load_patches();
00183 }
00184
00185 return game;
00186 }
00187
00188
00189 void Game::play_flic(const char *archive, int index)
00190 {
00191 char *fli_buf;
00192 size_t len;
00193 U7object flic(archive, index);
00194 fli_buf = flic.retrieve(len);
00195 playfli fli(fli_buf);
00196 fli.play(win);
00197 delete [] fli_buf;
00198 }
00199
00200 void Game::play_audio(const char *archive, int index)
00201 {
00202 U7object speech(archive, index);
00203
00204 speech.retrieve("speech.voc");
00205 Audio::get_ptr()->playfile("speech.voc", false);
00206 }
00207
00208 void Game::play_midi(int track,bool repeat)
00209 {
00210 if (game_type == BLACK_GATE) Audio::get_ptr()->start_music(track,repeat,1);
00211 else if (game_type == SERPENT_ISLE) Audio::get_ptr()->start_music(track,repeat,2);
00212 }
00213
00214 void Game::add_shape(const char *name, int shapenum)
00215 {
00216 shapes[name] = shapenum;
00217 }
00218
00219 int Game::get_shape(const char *name)
00220 {
00221 return shapes[name];
00222 }
00223
00224 void Game::add_resource(const char *name, const char *str, int num)
00225 {
00226 resources[name].str = str;
00227 resources[name].num = num;
00228 }
00229
00230 str_int_pair Game::get_resource(const char *name)
00231 {
00232 return resources[name];
00233 }
00234
00235
00236 bool Game::show_menu(bool skip)
00237 {
00238 int menuy = topy+120;
00239
00240 if (skip || (is_editing() && !U7exists(MAINSHP_FLX)))
00241 {
00242 bool first = !U7exists(IDENTITY);
00243 if (first)
00244 set_avname("Newbie");
00245 if (!gwin->init_gamedat(first))
00246 return false;
00247 return true;
00248 }
00249 ExultDataSource mouse_data(MAINSHP_FLX, 19);
00250 menu_mouse = new Mouse(gwin, mouse_data);
00251
00252 top_menu();
00253 MenuList *menu = 0;
00254
00255
00256 int menuchoices[] = { 0x04, 0x05, 0x08, 0x06, 0x11, 0x12, 0x07 };
00257 int num_choices = sizeof(menuchoices)/sizeof(int);
00258 int *menuentries = new int[num_choices];
00259
00260 Vga_file exult_flx("<DATA>/exult.flx");
00261 char npc_name[16];
00262 snprintf(npc_name, 16, "Exult");
00263 bool play = false;
00264 bool fadeout = true;
00265 bool exitmenu = false;
00266
00267 do {
00268 int entries = 0;
00269 if(!menu) {
00270 entries = 0;
00271 menu = new MenuList();
00272 int offset = 0;
00273 for(int i=0; i<num_choices; i++) {
00274 if((i!=4 && i!=5) || (i==4 && U7exists("<SAVEGAME>/quotes.flg")) || (i==5 && U7exists("<SAVEGAME>/endgame.flg"))) {
00275 menu->add_entry(new MenuEntry(menushapes.get_shape(menuchoices[i],1),
00276 menushapes.get_shape(menuchoices[i],0),
00277 centerx, menuy+offset));
00278 offset += menushapes.get_shape(menuchoices[i],1)->get_ybelow() + 3;
00279 menuentries[entries++]=i;
00280 }
00281 }
00282 menu->set_selection(2);
00283 }
00284
00285 bool created = false;
00286 int choice = menu->handle_events(gwin, menu_mouse);
00287 switch(choice<0?choice:menuentries[choice]) {
00288 case -1:
00289 pal->fade_out(c_fade_out_time);
00290 Audio::get_ptr()->stop_music();
00291 throw quit_exception();
00292 case 0:
00293 pal->fade_out(c_fade_out_time);
00294 play_intro();
00295 gwin->clear_screen(true);
00296 top_menu();
00297 break;
00298 case 2:
00299 created = gwin->init_gamedat(false);
00300 if(!created) {
00301 show_journey_failed();
00302 top_menu();
00303 menu->set_selection(1);
00304 break;
00305 }
00306 exitmenu = true;
00307 fadeout = true;
00308 play = true;
00309 break;
00310 case 1:
00311 if(!created) {
00312 if(new_game(menushapes))
00313 exitmenu = true;
00314 else
00315 break;
00316 } else
00317 exitmenu = true;
00318 fadeout = false;
00319 play = true;
00320 break;
00321 case 3:
00322 pal->fade_out(c_fade_out_time);
00323 show_credits();
00324 delete menu;
00325 menu = 0;
00326 top_menu();
00327 break;
00328 case 4:
00329 pal->fade_out(c_fade_out_time);
00330 show_quotes();
00331 top_menu();
00332 break;
00333 case 5:
00334 pal->fade_out(c_fade_out_time);
00335 end_game(true);
00336 top_menu();
00337 break;
00338 case 6:
00339 play = false;
00340 exitmenu = true;
00341 fadeout = true;
00342 break;
00343 default:
00344 break;
00345 }
00346 } while(!exitmenu);
00347
00348 if (fadeout) {
00349 pal->fade_out(c_fade_out_time);
00350 gwin->clear_screen(true);
00351 }
00352 delete menu;
00353 delete[] menuentries;
00354 Audio::get_ptr()->stop_music();
00355 delete menu_mouse;
00356 return play;
00357 }
00358
00359 void Game::journey_failed_text()
00360 {
00361 Font *font = fontManager.get_font("MENU_FONT");
00362 font->center_text(ibuf, centerx, centery+30, "You must start a new game first.");
00363 pal->fade_in(50);
00364 while (!wait_delay(10))
00365 ;
00366 pal->fade_out(50);
00367 }
00368
00369 const char *Game::get_avname ()
00370 {
00371 if (av_name[0])
00372 return av_name;
00373 else
00374 return NULL;
00375 }
00376
00377 int Game::get_avsex ()
00378 {
00379 return av_sex;
00380 }
00381 int Game::get_avskin ()
00382 {
00383 return av_skin;
00384 }
00385
00386
00387 void Game::set_avname (char *name)
00388 {
00389 strcpy (av_name, name);
00390 }
00391
00392 void Game::set_avsex (int sex)
00393 {
00394 av_sex = sex;
00395 }
00396
00397 void Game::set_avskin (int skin)
00398 {
00399 av_skin = skin;
00400 }
00401
00402 void Game::clear_avname ()
00403 {
00404 av_name[0] = 0;
00405 new_game_flag = false;
00406 }
00407
00408 void Game::clear_avsex ()
00409 {
00410 av_sex = -1;
00411 }
00412
00413 void Game::clear_avskin ()
00414 {
00415 av_skin = -1;
00416 }
00417
00418
00419
00420
00421
00422 int wait_delay(int ms, int startcol, int ncol)
00423 {
00424 SDL_Event event;
00425 int delay;
00426 int loops;
00427 bool mouse_down = false;
00428
00429 int loopinterval = (ncol == 0) ? 50 : 10;
00430 if (!ms) ms = 1;
00431 if(ms <= 2*loopinterval) {
00432 delay = ms;
00433 loops = 1;
00434 } else {
00435 delay = loopinterval;
00436 loops = ms/delay;
00437 }
00438
00439 for(int i=0; i<loops; i++) {
00440 unsigned long ticks1 = SDL_GetTicks();
00441
00442 while(SDL_PollEvent(&event)) {
00443 switch (event.type) {
00444 case SDL_KEYDOWN:
00445 switch (event.key.keysym.sym) {
00446 case SDLK_RSHIFT: case SDLK_LSHIFT:
00447 case SDLK_RCTRL: case SDLK_LCTRL:
00448 case SDLK_RALT: case SDLK_LALT:
00449 case SDLK_RMETA: case SDLK_LMETA:
00450 case SDLK_RSUPER: case SDLK_LSUPER:
00451 case SDLK_NUMLOCK: case SDLK_CAPSLOCK:
00452 case SDLK_SCROLLOCK:
00453 break;
00454 case SDLK_s:
00455 if ((event.key.keysym.mod&KMOD_ALT) &&
00456 (event.key.keysym.mod&KMOD_CTRL))
00457 make_screenshot(true);
00458 break;
00459 case SDLK_RETURN:
00460 case SDLK_KP_ENTER:
00461 return 2;
00462 break;
00463 default:
00464 return 1;
00465 }
00466 break;
00467 case SDL_MOUSEBUTTONDOWN:
00468 mouse_down = true;
00469 break;
00470 case SDL_MOUSEBUTTONUP:
00471
00472 return 1;
00473 break;
00474 default:
00475 break;
00476 }
00477 }
00478 if (ncol > 0) {
00479 Game_window::get_instance()->get_win()
00480 ->rotate_colors(startcol, ncol, 1);
00481 if (ms > 250)
00482 Game_window::get_instance()->get_win()->show();
00483 }
00484 unsigned long ticks2 = SDL_GetTicks();
00485 if (ticks2 - ticks1 > delay)
00486 i+= (ticks2 - ticks1) / delay - 1;
00487 else
00488 SDL_Delay(delay - (ticks2 - ticks1));
00489 }
00490
00491 return 0;
00492 }