00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #ifndef ALPHA_LINUX_CXX
00031 # include <cstdlib>
00032 # include <cctype>
00033 #endif
00034
00035 #include <SDL.h>
00036
00037 #define Font _XFont_
00038 #include <SDL_syswm.h>
00039 #undef Font
00040
00041 #ifdef USE_EXULTSTUDIO
00042 #if HAVE_SYS_TIME_H
00043 #include <sys/time.h>
00044 #endif
00045 #ifdef WIN32
00046 #include "windrag.h"
00047 #elif defined(XWIN)
00048 #include "xdrag.h"
00049 #endif
00050 #include "server.h"
00051 #include "chunks.h"
00052 #include "chunkter.h"
00053 #endif
00054
00055 #if (defined(USECODE_DEBUGGER) && defined(XWIN))
00056 #include <csignal>
00057 #endif
00058
00059 #include "Audio.h"
00060 #include "Configuration.h"
00061 #include "Gump_manager.h"
00062 #include "Scroll_gump.h"
00063 #include "actors.h"
00064 #include "args.h"
00065 #include "cheat.h"
00066 #include "effects.h"
00067 #include "exult.h"
00068 #include "exultmenu.h"
00069 #include "fnames.h"
00070 #include "font.h"
00071 #include "game.h"
00072 #include "gamewin.h"
00073 #include "gamemap.h"
00074 #include "gump_utils.h"
00075 #include "keyactions.h"
00076 #include "keys.h"
00077 #include "mouse.h"
00078 #include "ucmachine.h"
00079 #include "utils.h"
00080 #include "version.h"
00081 #include "u7drag.h"
00082 #include "drag.h"
00083 #include "palette.h"
00084 #include "glshape.h"
00085 #include "combat_opts.h"
00086
00087 #include "exult_flx.h"
00088 #include "exult_bg_flx.h"
00089 #include "exult_si_flx.h"
00090 #include "crc.h"
00091
00092 #ifndef UNDER_CE
00093 using std::atof;
00094 using std::cerr;
00095 using std::cout;
00096 using std::endl;
00097 using std::atexit;
00098 using std::exit;
00099 using std::toupper;
00100 using std::string;
00101 using std::vector;
00102 #endif
00103
00104 Configuration *config = 0;
00105 KeyBinder *keybinder = 0;
00106
00107
00108
00109
00110 Game_window *gwin = 0;
00111 quitting_time_enum quitting_time = QUIT_TIME_NO;
00112
00113 bool intrinsic_trace = false;
00114 int usecode_trace = 0;
00115
00116 bool combat_trace = false;
00117
00118
00119 int save_compression = 1;
00120 bool ignore_crc = false;
00121
00122 const std::string c_empty_string;
00123
00124 #if 0 && USECODE_DEBUGGER
00125 bool usecode_debugging=false;
00126 extern void initialise_usecode_debugger(void);
00127 #endif
00128
00129 struct resolution {
00130 int x;
00131 int y;
00132 int scale;
00133 } res_list[] = {
00134 { 320, 200, 1 },
00135 { 320, 240, 1 },
00136 { 400, 300, 1 },
00137 { 320, 200, 2 },
00138 { 320, 240, 2 },
00139 { 400, 300, 2 },
00140 { 512, 384, 1 },
00141 { 640, 480, 1 },
00142 { 800, 600, 1 }
00143 };
00144 int num_res = sizeof(res_list)/sizeof(struct resolution);
00145 int current_res = 0;
00146
00147 #ifdef XWIN
00148 int xfd = 0;
00149 static class Xdnd *xdnd = 0;
00150 #elif defined(WIN32)
00151 static HWND hgwin;
00152 static class Windnd *windnd = 0;
00153 #endif
00154
00155
00156
00157
00158
00159 static int exult_main(const char *);
00160 static void Init();
00161 static int Play();
00162 static int Get_click(int& x, int& y, char *chr, bool drag_ok, Paintable *p);
00163 static int find_resolution(int w, int h, int s);
00164 static void set_resolution (int new_res, bool save);
00165 #ifdef USE_EXULTSTUDIO
00166 static void Move_dragged_shape(int shape, int frame, int x, int y,
00167 int prevx, int prevy, bool show);
00168 static void Move_dragged_combo(int xtiles, int ytiles, int tiles_right,
00169 int tiles_below, int x, int y, int prevx, int prevy, bool show);
00170 static void Drop_dragged_shape(int shape, int frame, int x, int y, void *d);
00171 static void Drop_dragged_chunk(int chunknum, int x, int y, void *d);
00172 static void Drop_dragged_combo(int cnt, U7_combo_data *combo,
00173 int x, int y, void *d);
00174 #endif
00175 static void BuildGameMap();
00176 static void Handle_events();
00177 static void Handle_event(SDL_Event& event);
00178 static void get_game_paths(const string &gametitle);
00179
00180
00181
00182
00183
00184
00185 static bool dragging = false;
00186 static bool dragged = false;
00187 static bool run_bg = false;
00188 static bool run_si = false;
00189
00190 static string arg_gamename = "default";
00191 static string arg_configfile = "";
00192 static int arg_buildmap = -1;
00193 static bool arg_nomenu = false;
00194
00195
00196
00197
00198
00199 static void Breakpoint
00200 (
00201 )
00202 {
00203 return;
00204 }
00205
00206 #if (defined(XWIN) && HAVE_SIGNAL_H && HAVE_SYS_WAIT_H)
00207
00208
00209
00210 #include <sys/wait.h>
00211 #include <signal.h>
00212 void sigchld_handler(int sig)
00213 {
00214 waitpid(-1, 0, WNOHANG);
00215 }
00216
00217 #endif
00218
00219
00220
00221
00222
00223
00224 int main
00225 (
00226 int argc,
00227 char *argv[]
00228 )
00229 {
00230
00231 #ifdef BEOS
00232
00233 int counti;
00234 char datapath[256];
00235 for (counti=strlen(argv[0]) ; argv[0][counti]!='/' ; counti--);
00236 strncpy(datapath, argv[0], counti);
00237 chdir(datapath);
00238 #endif
00239
00240 #if (defined(XWIN) && HAVE_SIGNAL_H && HAVE_SYS_WAIT_H)
00241 signal(SIGCHLD, sigchld_handler);
00242 #endif
00243
00244
00245 bool needhelp=false;
00246 bool showversion=false;
00247 int result;
00248 Args parameters;
00249
00250
00251 parameters.declare("-h",&needhelp,true);
00252 parameters.declare("--help",&needhelp,true);
00253 parameters.declare("/?",&needhelp,true);
00254 parameters.declare("/h",&needhelp,true);
00255 parameters.declare("--bg",&run_bg,true);
00256 parameters.declare("--si",&run_si,true);
00257 parameters.declare("--nomenu", &arg_nomenu, true);
00258 parameters.declare("-v",&showversion,true);
00259 parameters.declare("--version",&showversion,true);
00260 parameters.declare("--game",&arg_gamename,"default");
00261 parameters.declare("--buildmap",&arg_buildmap,-1);
00262 parameters.declare("--nocrc",&ignore_crc,true);
00263 parameters.declare("-c",&arg_configfile,"");
00264
00265
00266 parameters.process(argc,argv);
00267
00268 if(needhelp)
00269 {
00270 cerr << "Usage: exult [--help|-h] [-v|--version] [-c configfile]"<<endl
00271 << " [--bg|--si] [--buildmap 0|1|2] [--nocrc]" << endl
00272 << "--help\t\tShow this information" << endl
00273 << "--version\tShow version info" << endl
00274 << " -c configfile\tSpecify alternate config file" << endl
00275 << "--bg\t\tSkip menu and run Black Gate" << endl
00276 << "--si\t\tSkip menu and run Serpent Isle" << endl
00277 << "--nomenu\tSkip BG/SI game menu" << endl
00278 << "--game <game>\tRun original game" << endl
00279 << "--buildmap\tCreate a fullsize map of the game world in u7map??.pcx" << endl
00280 << "\t\t(0 = all roofs, 1 = no level 2 roofs, 2 = no roofs)" << endl
00281 << "\t\tonly valid when used together with --bg or --si" << endl
00282 << "\t\t(WARNING: requires big amounts of RAM, HD space and time!)" << endl
00283 << "--nocrc\t\tDon't check crc's of .flx files" << endl;
00284
00285 exit(1);
00286 }
00287 if (run_bg && run_si) {
00288 cerr << "Error: You may only specify either -bg or -si!" <<
00289 endl;
00290 exit(1);
00291 }
00292
00293 if(showversion) {
00294 getVersionInfo(cerr);
00295 return 0;
00296 }
00297
00298 try
00299 {
00300 result = exult_main(argv[0]);
00301 }
00302 catch( const quit_exception & e )
00303 {
00304 result = 0;
00305 }
00306 catch( const exult_exception & e )
00307 {
00308 cerr << "============================" << endl <<
00309 "An exception occured: " << endl <<
00310 e.what() << endl <<
00311 "errno: " << e.get_errno() << endl;
00312 if( e.get_errno() != 0)
00313 perror("Error Description");
00314 cerr << "============================" << endl;
00315 }
00316
00317 return result;
00318 }
00319
00320
00321
00322
00323
00324
00325 int exult_main(const char *runpath)
00326 {
00327 string data_path;
00328 string music_path;
00329
00330
00331 getVersionInfo(cout);
00332
00333
00334 config = new Configuration;
00335
00336 if (arg_configfile != "") {
00337 config->read_abs_config_file(arg_configfile);
00338 } else {
00339 config->read_config_file(USER_CONFIGURATION_FILE);
00340 }
00341
00342
00343 config->value("config/disk/data_path",data_path,EXULT_DATADIR);
00344 add_system_path("<DATA>", data_path);
00345 if (!U7exists("<DATA>/exult.flx"))
00346 {
00347 add_system_path("<DATA>", EXULT_DATADIR);
00348 if (!U7exists("<DATA>/exult.flx"))
00349 {
00350 add_system_path("<DATA>", "data");
00351 if(!U7exists("<DATA>/exult.flx"))
00352 {
00353 char *sep = std::strrchr(runpath,'/');
00354 if (!sep) sep = std::strrchr(runpath,'\\');
00355 int plen = sep-runpath;
00356 char *dpath = new char[plen+10];
00357 std::strncpy(dpath, runpath, plen+1);
00358 dpath[plen+1] = 0;
00359 std::strcat(dpath,"data");
00360 cerr << "dpath = " << dpath << endl;
00361 add_system_path("<DATA>",dpath);
00362 if(!U7exists("<DATA>/exult.flx"))
00363 {
00364
00365 cerr << "Could not find 'exult.flx' anywhere." << endl;
00366 cerr << "Please make sure Exult is correctly installed," << endl;
00367 cerr << "and the Exult data path is specified in the configuration file." << endl;
00368 cerr << "(See the README file for more information)" << endl;
00369 exit(-1);
00370 }
00371 }
00372 }
00373 }
00374 std::string default_music = get_system_path("<DATA>/music");
00375 config->value("config/disk/music_path",music_path,default_music.c_str());
00376
00377 add_system_path("<MUSIC>", music_path);
00378 add_system_path("<STATIC>", "static");
00379 add_system_path("<GAMEDAT>", "gamedat");
00380 add_system_path("<PATCH>", "patch");
00381
00382 add_system_path("<SAVEGAME>", ".");
00383
00384 std::cout << "Exult path settings:" << std::endl;
00385 std::cout << "Data : " << get_system_path("<DATA>") << std::endl;
00386 std::cout << "Digital music : " << get_system_path("<MUSIC>") << std::endl;
00387 std::cout << std::endl;
00388
00389
00390
00391 bool crc_ok = true;
00392 uint32 crc = crc32_syspath("<DATA>/exult.flx");
00393 if (crc != EXULT_FLX_CRC32) {
00394 crc_ok = false;
00395 cerr << "exult.flx has a wrong checksum!" << endl;
00396 }
00397 if (U7exists("<DATA>/exult_bg.flx")) {
00398 if (crc32_syspath("<DATA>/exult_bg.flx") != EXULT_BG_FLX_CRC32) {
00399 crc_ok = false;
00400 cerr << "exult_bg.flx has a wrong checksum!" << endl;
00401 }
00402 }
00403 if (U7exists("<DATA>/exult_si.flx")) {
00404 if (crc32_syspath("<DATA>/exult_si.flx") != EXULT_SI_FLX_CRC32) {
00405 crc_ok = false;
00406 cerr << "exult_si.flx has a wrong checksum!" << endl;
00407 }
00408 }
00409
00410 bool config_ignore_crc;
00411 config->value("config/disk/no_crc",config_ignore_crc);
00412 ignore_crc |= config_ignore_crc;
00413
00414 if (!ignore_crc && !crc_ok) {
00415 cerr << "This usually means the file(s) mentioned above are "
00416 << "from a different version" << endl
00417 << "of Exult than this one. Please re-install Exult" << endl
00418 << endl
00419 << "(Note: if you modified the .flx files yourself, "
00420 << "you can skip this check" << endl
00421 << "by passing the --nocrc parameter.)" << endl;
00422
00423 return 1;
00424 }
00425
00426
00427
00428 vector<string> vs=config->listkeys("config/disk/game",false);
00429 if(vs.size()==0)
00430 {
00431
00432 string data_directory;
00433 config->value("config/disk/u7path",data_directory,".");
00434 config->set("config/disk/game/blackgate/path",data_directory,true);
00435 const string s("blackgate");
00436 config->set("config/disk/game/blackgate/title",s,true);
00437 vs.push_back(s);
00438 }
00439
00440 get_game_paths("blackgate");
00441 get_game_paths("serpentisle");
00442
00443
00444 config->value("config/debug/trace/intrinsics",intrinsic_trace);
00445
00446
00447 string uctrace;
00448 config->value("config/debug/trace/usecode", uctrace, "no");
00449 to_uppercase(uctrace);
00450 if (uctrace == "YES")
00451 usecode_trace = 1;
00452 else if (uctrace == "VERBOSE")
00453 usecode_trace = 2;
00454 else
00455 usecode_trace = 0;
00456
00457 config->value("config/debug/trace/combat",combat_trace);
00458
00459
00460 config->value("config/disk/save_compression_level", save_compression, 1);
00461 if (save_compression < 0 || save_compression > 2) save_compression = 1;
00462 config->set("config/disk/save_compression_level", save_compression, true);
00463
00464 #if 0 && USECODE_DEBUGGER
00465
00466 config->value("config/debug/debugger/enable",usecode_debugging);
00467 initialise_usecode_debugger();
00468 #endif
00469
00470 #if (defined(USECODE_DEBUGGER) && defined(XWIN))
00471 signal(SIGUSR1, SIG_IGN);
00472 #endif
00473
00474 cheat.init();
00475
00476 #ifdef UNDER_CE
00477 GXOpenInput();
00478
00479 GXKeyList keys = GXGetDefaultKeys(GX_LANDSCAPEKEYS);
00480
00481 std::cout << "Up " << keys.vkUp << std::endl;
00482 std::cout << "Down " << keys.vkDown << std::endl;
00483 std::cout << "Left " << keys.vkLeft << std::endl;
00484 std::cout << "Right " << keys.vkRight << std::endl;
00485 std::cout << "A " << keys.vkA << std::endl;
00486 std::cout << "B " << keys.vkB << std::endl;
00487 std::cout << "C " << keys.vkC << std::endl;
00488 std::cout << "Start " << keys.vkStart << std::endl;
00489 #endif
00490
00491 Init();
00492
00493 cheat.finish_init();
00494
00495 Mouse::mouse = new Mouse(gwin);
00496 Mouse::mouse->set_shape(Mouse::hand);
00497
00498 int result = Play();
00499
00500 #ifdef UNDER_CE
00501 GXCloseInput();
00502 #endif
00503
00504 #if defined(WIN32) && defined(USE_EXULTSTUDIO)
00505
00506
00507
00508
00509
00510 RevokeDragDrop(hgwin);
00511 delete windnd;
00512 #endif
00513
00514 return result;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523 static void get_game_paths(const string &gametitle)
00524 {
00525 std::string data_directory, static_dir, gamedat_dir, savegame_dir,
00526 default_dir, system_path_tag(to_uppercase(gametitle)),
00527 config_path("config/disk/game/" + gametitle + "/path");
00528
00529 config->value(config_path.c_str(), data_directory, ".");
00530 if (data_directory == ".")
00531 config->set(config_path.c_str(), data_directory, true);
00532 #if 0
00533 cout << "setting " << gametitle
00534 << " game directories to: " << data_directory << endl;
00535 #endif
00536
00537 config_path = "config/disk/game/" + gametitle + "/static_path";
00538 default_dir = data_directory + "/static";
00539 config->value(config_path.c_str(), static_dir, default_dir.c_str());
00540 add_system_path("<" + system_path_tag + "_STATIC>", static_dir);
00541 #if 0
00542 cout << "setting " << gametitle
00543 << " static directory to: " << static_dir << endl;
00544 #endif
00545
00546 const char *home = 0;
00547 string home_game("");
00548 config_path = "config/disk/game/" + gametitle + "/gamedat_path";
00549 default_dir = data_directory + "/gamedat";
00550 config->value(config_path.c_str(), gamedat_dir, "");
00551 #if (!defined(WIN32) && !defined(MACOS))
00552 if (gamedat_dir == "" &&
00553
00554 !U7exists(default_dir.c_str()) && (home = getenv("HOME")) != 0)
00555 {
00556 home_game = home;
00557 home_game += "/.exult";
00558
00559 U7mkdir(home_game.c_str(), 0755);
00560 home_game = home_game + '/' + gametitle;
00561 U7mkdir(home_game.c_str(), 0755);
00562
00563 if (U7exists(home_game.c_str()))
00564 {
00565 gamedat_dir = home_game + "/gamedat";
00566 config->set(config_path.c_str(), gamedat_dir.c_str(),
00567 true);
00568 }
00569 else
00570 home_game = "";
00571 }
00572 #endif
00573 if (gamedat_dir == "")
00574 gamedat_dir = default_dir;
00575 add_system_path("<" + system_path_tag + "_GAMEDAT>", gamedat_dir);
00576 #if 0
00577 cout << "setting " << gametitle
00578 << " gamedat directory to: " << gamedat_dir << endl;
00579 #endif
00580
00581 config_path = "config/disk/game/" + gametitle + "/savegame_path";
00582 if (home_game == "")
00583 config->value(config_path.c_str(), savegame_dir,
00584 data_directory.c_str());
00585 else
00586 {
00587 config->value(config_path.c_str(), savegame_dir,
00588 home_game.c_str());
00589 config->set(config_path.c_str(), savegame_dir.c_str(), true);
00590 }
00591 add_system_path("<" + system_path_tag + "_SAVEGAME>", savegame_dir);
00592 #if 0
00593 cout << "setting " << gametitle
00594 << " savegame directory to: " << savegame_dir << endl;
00595 #endif
00596
00597 config_path = "config/disk/game/" + gametitle + "/patch";
00598 string patch_directory;
00599 default_dir = data_directory + "/patch";
00600 config->value(config_path.c_str(), patch_directory,
00601 default_dir.c_str());
00602 add_system_path("<" + system_path_tag + "_PATCH>", patch_directory.c_str());
00603 }
00604
00605 namespace ExultIcon {
00606 #include "exulticon.h"
00607 }
00608
00609 static void SetIcon()
00610 {
00611 SDL_Surface* iconsurface = SDL_CreateRGBSurfaceFrom(ExultIcon::header_data,
00612 ExultIcon::width,
00613 ExultIcon::height,
00614 8,
00615 ExultIcon::width,
00616 0, 0, 0, 0);
00617 SDL_Color iconpal[256];
00618 for (int i = 0; i < 256; ++i) {
00619 iconpal[i].r = ExultIcon::header_data_cmap[i][0];
00620 iconpal[i].g = ExultIcon::header_data_cmap[i][1];
00621 iconpal[i].b = ExultIcon::header_data_cmap[i][2];
00622 }
00623 SDL_SetPalette(iconsurface, SDL_LOGPAL, iconpal, 0, 256);
00624
00625 SDL_SetColorKey(iconsurface, SDL_SRCCOLORKEY, 0);
00626
00627 SDL_WM_SetIcon(iconsurface, 0);
00628
00629 SDL_FreeSurface(iconsurface);
00630 }
00631
00632
00633
00634
00635
00636 static void Init
00637 (
00638 )
00639 {
00640 Uint32 init_flags = SDL_INIT_VIDEO|SDL_INIT_TIMER;
00641 #ifdef NO_SDL_PARACHUTE
00642 init_flags |= SDL_INIT_NOPARACHUTE;
00643 #endif
00644 if (SDL_Init(init_flags) < 0)
00645 {
00646 cerr << "Unable to initialize SDL: " << SDL_GetError() << endl;
00647 exit(-1);
00648 }
00649 std::atexit(SDL_Quit);
00650
00651 SDL_SysWMinfo info;
00652 SDL_GetWMInfo(&info);
00653 #ifdef USE_EXULTSTUDIO
00654
00655 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
00656 #endif
00657
00658 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
00659 SDL_DEFAULT_REPEAT_INTERVAL);
00660 SDL_ShowCursor(0);
00661 SDL_VERSION(&info.version);
00662
00663 SetIcon();
00664
00665 int w, h, sc, sclr;
00666
00667
00668 w = 320;
00669 h = 200;
00670 sc = 2;
00671 sclr = Image_window::SaI;
00672
00673 int sw, sh, scaleval;
00674 string gr, gg, gb, scaler;
00675 config->value("config/video/width", sw, w);
00676 config->value("config/video/height", sh, h);
00677 config->value("config/video/scale_method", scaler, "---");
00678 config->value("config/video/gamma/red", gr, "1.0");
00679 config->value("config/video/gamma/green", gg, "1.0");
00680 config->value("config/video/gamma/blue", gb, "1.0");
00681
00682 config->value("config/video/scale", scaleval, sc);
00683 sclr = Image_window::get_scaler_for_name(scaler);
00684 if (sclr == Image_window::NoScaler) config->set("config/video/scale_method","2xSaI",true);
00685
00686 if (arg_buildmap >= 0)
00687 BuildGameMap();
00688
00689 Image_window8::set_gamma(atof(gr.c_str()), atof(gg.c_str()), atof(gb.c_str()));
00690 gwin = new Game_window(sw, sh, scaleval, sclr);
00691 current_res = find_resolution(sw, sh, scaleval);
00692 Audio::Init();
00693
00694 bool disable_fades;
00695 config->value("config/video/disable_fades", disable_fades, false);
00696 gwin->get_pal()->set_fades_enabled(!disable_fades);
00697
00698
00699 SDL_SetEventFilter(0);
00700
00701 Exult_Game mygame;
00702 game = 0;
00703
00704
00705
00706
00707 if (arg_gamename != "default") {
00708
00709
00710 get_game_paths(arg_gamename);
00711 }
00712
00713 store_system_paths();
00714
00715 do {
00716 reset_system_paths();
00717 fontManager.reset();
00718 U7FileManager::get_ptr()->reset();
00719 const char *title = 0;
00720
00721 if(game)
00722 delete game;
00723
00724 if (run_bg) {
00725 mygame = BLACK_GATE;
00726 run_bg = false;
00727 } else if (run_si) {
00728 mygame = SERPENT_ISLE;
00729 run_si = false;
00730 } else if (arg_buildmap < 0 && arg_gamename != "default") {
00731 mygame = EXULT_DEVEL_GAME;
00732 title = arg_gamename.c_str();
00733 } else {
00734 ExultMenu exult_menu(gwin);
00735 mygame = exult_menu.run();
00736 }
00737 Game::create_game(mygame, title);
00738
00739 Audio::get_ptr()->Init_sfx();
00740
00741
00742 bool skip_splash;
00743 config->value("config/gameplay/skip_splash", skip_splash);
00744 if(!skip_splash &&
00745
00746 (Game::get_game_type() != EXULT_DEVEL_GAME ||
00747 U7exists("<STATIC>/intro.dat")))
00748 game->play_intro();
00749 } while(!game->show_menu(arg_nomenu));
00750 gwin->init_files();
00751 gwin->read_gwin();
00752 gwin->setup_game();
00753
00754 #ifdef USE_EXULTSTUDIO
00755 #ifndef WIN32
00756 SDL_GetWMInfo(&info);
00757 xfd = ConnectionNumber(info.info.x11.display);
00758 Server_init();
00759 xdnd = new Xdnd(info.info.x11.display, info.info.x11.wmwindow,
00760 info.info.x11.window, Move_dragged_shape, Move_dragged_combo,
00761 Drop_dragged_shape, Drop_dragged_chunk,
00762 Drop_dragged_combo);
00763 #elif !defined(UNDER_CE)
00764 SDL_GetWMInfo(&info);
00765 Server_init();
00766 hgwin = info.window;
00767 OleInitialize(NULL);
00768 windnd = new Windnd(hgwin, Move_dragged_shape, Move_dragged_combo,
00769 Drop_dragged_shape, Drop_dragged_chunk,
00770 Drop_dragged_combo);
00771 if (FAILED(RegisterDragDrop(hgwin, windnd))) {
00772 cout << "Something's wrong with OLE2 ..." << endl;
00773 };
00774 #endif
00775 #endif
00776 }
00777
00778
00779
00780
00781
00782 static int Play()
00783 {
00784 do
00785 {
00786 quitting_time = QUIT_TIME_NO;
00787 Handle_events();
00788 if( quitting_time == QUIT_TIME_RESTART )
00789 {
00790 Mouse::mouse->hide();
00791 gwin->read();
00795 }
00796 }
00797 while (quitting_time == QUIT_TIME_RESTART);
00798 delete gwin;
00799 delete Mouse::mouse;
00800
00801 Audio::Destroy();
00802
00803 delete config;
00804 return (0);
00805 }
00806
00807 #ifdef USE_EXULTSTUDIO // Shift-click means 'paint'.
00808
00809
00810
00811
00812 static void Paint_with_shape
00813 (
00814 SDL_Event& event,
00815 bool dragging
00816 )
00817 {
00818 static int lasttx = -1, lastty = -1;
00819 int scale = gwin->get_win()->get_scale();
00820 int x = event.button.x/scale, y = event.button.y/scale;
00821 int tx = (gwin->get_scrolltx() + x/c_tilesize);
00822 int ty = (gwin->get_scrollty() + y/c_tilesize);
00823 if (dragging)
00824 {
00825 if (tx == lasttx && ty == lastty)
00826 return;
00827 }
00828 lasttx = tx; lastty = ty;
00829 int shnum = cheat.get_edit_shape();
00830 int frnum;
00831 SDLMod mod = SDL_GetModState();
00832 if (mod & KMOD_ALT)
00833 {
00834 ShapeID id(shnum, 0);
00835 frnum = std::rand()%id.get_num_frames();
00836 }
00837 else if (mod & KMOD_CTRL)
00838 {
00839 frnum = cheat.get_edit_frame();
00840 ShapeID id(shnum, 0);
00841 int nextframe = (frnum + 1)%id.get_num_frames();
00842 cheat.set_edit_shape(shnum, nextframe);
00843 }
00844 else
00845 frnum = cheat.get_edit_frame();
00846 Drop_dragged_shape(shnum, frnum, event.button.x, event.button.y, 0);
00847 }
00848
00849
00850
00851
00852
00853 static void Paint_with_chunk
00854 (
00855 SDL_Event& event,
00856 bool dragging
00857 )
00858 {
00859 static int lastcx = -1, lastcy = -1;
00860 int scale = gwin->get_win()->get_scale();
00861 int x = event.button.x/scale, y = event.button.y/scale;
00862 int cx = (gwin->get_scrolltx() + x/c_tilesize)/c_tiles_per_chunk;
00863 int cy = (gwin->get_scrollty() + y/c_tilesize)/c_tiles_per_chunk;
00864 if (dragging)
00865 {
00866 if (cx == lastcx && cy == lastcy)
00867 return;
00868 }
00869 lastcx = cx; lastcy = cy;
00870 int chnum = cheat.get_edit_chunknum();
00871 Drop_dragged_chunk(chnum, event.button.x, event.button.y, 0);
00872 }
00873 #endif
00874
00875
00876
00877
00878
00879 static void Handle_events
00880 (
00881 )
00882 {
00883 uint32 last_repaint = 0;
00884 uint32 last_rotate = 0;
00885
00886
00887
00888 while (!quitting_time)
00889 {
00890 #ifdef USE_EXULTSTUDIO
00891 Server_delay();
00892 #else
00893 Delay();
00894 #endif
00895
00896 int scale = gwin->get_fastmouse() ? 1 :
00897 gwin->get_win()->get_scale();
00898
00899 Mouse::mouse->hide();
00900 Mouse::mouse_update = false;
00901
00902
00903 uint32 ticks = SDL_GetTicks();
00904 Game::set_ticks(ticks);
00905
00906 SDL_Event event;
00907 while (!quitting_time && SDL_PollEvent(&event))
00908 Handle_event(event);
00909
00910
00911 if (gwin->have_focus() && !dragging)
00912 gwin->get_tqueue()->activate(ticks);
00913
00914
00915
00916
00917 if (!gwin->is_moving() || gwin->get_step_tile_delta() == 1)
00918 {
00919 int x, y;
00920 int ms = SDL_GetMouseState(&x, &y);
00921 if (SDL_BUTTON(3) & ms)
00922 gwin->start_actor(x/scale, y/scale,
00923 Mouse::mouse->avatar_speed);
00924 else
00925 gwin->get_main_actor()->resting(50);
00926 }
00927
00928
00929 if (ticks > last_repaint + 50 || gwin->was_painted())
00930
00931 {
00932 if (GL_manager::get_instance())
00933 gwin->paint();
00934 else
00935 gwin->paint_dirty();
00936 while (ticks > last_repaint+50)last_repaint += 50;
00937
00938 }
00939
00940 Mouse::mouse->show();
00941
00942
00943
00944 int rot_speed = 100 << (gwin->get_win()->is_palettized() ||
00945 scale==1?0:1);
00946 if (ticks > last_rotate + rot_speed &&
00947 !GL_manager::get_instance())
00948 {
00949 gwin->get_win()->rotate_colors(0xfc, 3, 0);
00950 gwin->get_win()->rotate_colors(0xf8, 4, 0);
00951 gwin->get_win()->rotate_colors(0xf4, 4, 0);
00952 gwin->get_win()->rotate_colors(0xf0, 4, 0);
00953 gwin->get_win()->rotate_colors(0xe8, 8, 0);
00954 gwin->get_win()->rotate_colors(0xe0, 8, 1);
00955 while (ticks > last_rotate + rot_speed)
00956 last_rotate += rot_speed;
00957
00958 if (!gwin->get_win()->is_palettized())
00959 gwin->set_painted();
00960 }
00961 if (!gwin->show() &&
00962 Mouse::mouse_update)
00963 Mouse::mouse->blit_dirty();
00964 }
00965 }
00966
00967
00968
00969
00970
00971
00972 static void Handle_event
00973 (
00974 SDL_Event& event
00975 )
00976 {
00977
00978 int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale();
00979 bool dont_move_mode = gwin->main_actor_dont_move();
00980
00981
00982 Gump_manager *gump_man = gwin->get_gump_man();
00983 static bool right_on_gump = false;
00984 Gump *gump = 0;
00985
00986
00987 static uint32 last_b1_click = 0, last_b3_click = 0;
00988
00989 switch (event.type)
00990 {
00991 case SDL_MOUSEBUTTONDOWN:
00992 {
00993 if (dont_move_mode)
00994 break;
00995 int x = event.button.x/scale, y = event.button.y/scale;
00996 if (event.button.button == 1)
00997 {
00998 #ifdef USE_EXULTSTUDIO
00999 if (cheat.in_map_editor())
01000 {
01001 if (cheat.get_edit_shape() >= 0 &&
01002
01003 (cheat.get_edit_mode() == Cheat::paint ||
01004 (SDL_GetModState() & KMOD_SHIFT)))
01005 {
01006 Paint_with_shape(event, false);
01007 break;
01008 }
01009 else if (cheat.get_edit_chunknum() >= 0 &&
01010 cheat.get_edit_mode() == Cheat::paint_chunks)
01011 {
01012 Paint_with_chunk(event, false);
01013 break;
01014 }
01015
01016 else if (cheat.get_edit_mode() != Cheat::move)
01017 break;
01018 }
01019 #endif
01020 dragging = gwin->start_dragging(x, y);
01021
01022 dragged = false;
01023 }
01024
01025
01026 if (gwin->get_mouse3rd())
01027 if (event.button.button == 2)
01028 {
01029 ActionTarget(0);
01030 }
01031 if (event.button.button == 3) {
01032
01033
01034 gwin->get_tqueue()->remove(gwin->get_main_actor());
01035
01036 if (!dragging &&
01037 gump_man->can_right_click_close() &&
01038 gump_man->gump_mode() &&
01039 gump_man->find_gump(x, y, false)) {
01040 gump = 0;
01041 right_on_gump = true;
01042 }
01043 else
01044 gwin->start_actor(x, y,
01045 Mouse::mouse->avatar_speed);
01046
01047 }
01048 if (event.button.button == 4 || event.button.button == 5)
01049 {
01050 if (!cheat()) break;
01051 SDLMod mod = SDL_GetModState();
01052 if (event.button.button == 4)
01053 if (mod & KMOD_ALT)
01054 ActionScrollLeft(0);
01055 else
01056 ActionScrollUp(0);
01057 else
01058 if (mod & KMOD_ALT)
01059 ActionScrollRight(0);
01060 else
01061 ActionScrollDown(0);
01062 }
01063 break;
01064 }
01065 case SDL_MOUSEBUTTONUP:
01066 {
01067 if (dont_move_mode)
01068 break;
01069 int x = event.button.x/scale, y = event.button.y/scale;
01070 if (event.button.button == 3)
01071 {
01072 uint32 curtime = SDL_GetTicks();
01073
01074 if (gwin->get_allow_double_right_move() && curtime - last_b3_click < 500)
01075 gwin->start_actor_along_path(x, y,
01076 Mouse::mouse->avatar_speed);
01077 else if (right_on_gump &&
01078 (gump = gump_man->find_gump(x, y, false))) {
01079 Rectangle dirty = gump->get_dirty();
01080 gwin->add_dirty(dirty);
01081 gump_man->close_gump(gump);
01082 gump = 0;
01083 right_on_gump = false;
01084 }
01085 else
01086 {
01087 gwin->stop_actor();
01088 if (Combat::is_paused() && gwin->in_combat())
01089 gwin->paused_combat_select(x, y);
01090 }
01091 last_b3_click = curtime;
01092 }
01093 else if (event.button.button == 1)
01094 {
01095 uint32 curtime = SDL_GetTicks();
01096 bool click_handled = false;
01097 if (dragging) {
01098 click_handled = gwin->drop_dragged(x, y,
01099 dragged);
01100 }
01101
01102 if (curtime - last_b1_click < 500)
01103 {
01104 dragging = dragged = false;
01105 gwin->double_clicked(x, y);
01106 Mouse::mouse->set_speed_cursor();
01107 break;
01108 }
01109 if (!dragging || !dragged)
01110 last_b1_click = curtime;
01111
01112 if (!click_handled) {
01113
01114 gwin->show_items(x, y,
01115 (SDL_GetModState() & KMOD_CTRL) != 0);
01116 }
01117 dragging = dragged = false;
01118 }
01119 break;
01120 }
01121 case SDL_MOUSEMOTION:
01122 {
01123 Mouse::mouse->move(event.motion.x / scale,
01124 event.motion.y / scale);
01125 Mouse::mouse->set_speed_cursor();
01126 Mouse::mouse_update = true;
01127 right_on_gump = false;
01128
01129
01130 if (event.motion.state & SDL_BUTTON(1))
01131 {
01132 #ifdef USE_EXULTSTUDIO // Painting?
01133 if (cheat.in_map_editor())
01134 {
01135 if (cheat.get_edit_shape() >= 0 &&
01136 (cheat.get_edit_mode() == Cheat::paint ||
01137 (SDL_GetModState() & KMOD_SHIFT)))
01138 {
01139 Paint_with_shape(event, true);
01140 break;
01141 }
01142 else if (cheat.get_edit_chunknum() >= 0 &&
01143 cheat.get_edit_mode() == Cheat::paint_chunks)
01144 {
01145 Paint_with_chunk(event, true);
01146 break;
01147 }
01148 }
01149 #endif
01150 dragged = gwin->drag(event.motion.x / scale,
01151 event.motion.y / scale);
01152 }
01153
01154 else if ((event.motion.state & SDL_BUTTON(3)))
01155 gwin->start_actor(event.motion.x / scale,
01156 event.motion.y / scale, Mouse::mouse->avatar_speed);
01157 #ifdef USE_EXULTSTUDIO // Painting?
01158 else if (cheat.in_map_editor() &&
01159 cheat.get_edit_shape() >= 0 &&
01160 (cheat.get_edit_mode() == Cheat::paint ||
01161 (SDL_GetModState() & KMOD_SHIFT)))
01162 {
01163 static int prevx = -1, prevy = -1;
01164 Move_dragged_shape(cheat.get_edit_shape(),
01165 cheat.get_edit_frame(),
01166 event.motion.x, event.motion.y,
01167 prevx, prevy, false);
01168 prevx = event.motion.x; prevy = event.motion.y;
01169 }
01170 #endif
01171 break;
01172 }
01173 case SDL_ACTIVEEVENT:
01174
01175 if (event.active.state & SDL_APPMOUSEFOCUS)
01176 {
01177 if (event.active.gain)
01178 {
01179 int x, y;
01180 SDL_GetMouseState(&x, &y);
01181 Mouse::mouse->set_location(x/scale, y/scale);
01182 }
01183 gwin->set_painted();
01184 }
01185
01186 if (event.active.state & SDL_APPINPUTFOCUS)
01187 {
01188 if (event.active.gain)
01189 gwin->get_focus();
01190 else
01191 gwin->lose_focus();
01192 }
01193 #if 0
01194 if (event.active.state & SDL_APPACTIVE)
01195
01196 if (event.active.gain)
01197 gwin->init_actors();
01198 #endif
01199 break;
01200 #if 0
01201 case ConfigureNotify:
01202 gwin->resized(event.xconfigure.window,
01203 event.xconfigure.width, event.xconfigure.height);
01204 break;
01205 #endif
01206 case SDL_QUIT:
01207 gwin->get_gump_man()->okay_to_quit();
01208 break;
01209 case SDL_KEYDOWN:
01210 case SDL_KEYUP:
01211 if (!dragging)
01212 keybinder->HandleEvent(event);
01213 break;
01214 #ifdef USE_EXULTSTUDIO
01215 #ifndef WIN32
01216 case SDL_SYSWMEVENT:
01217 {
01218 XEvent& ev = event.syswm.msg->event.xevent;
01219 if (ev.type == ClientMessage)
01220 xdnd->client_msg((XClientMessageEvent&) ev);
01221 else if (ev.type == SelectionNotify)
01222 xdnd->select_msg((XSelectionEvent&) ev);
01223 break;
01224 }
01225 #endif
01226 #endif
01227 #if 0
01228
01229 case SDL_SYSWMEVENT:
01230
01231 if (event.syswm.msg->msg == MM_MCINOTIFY) {
01232 #if DEBUG
01233 cerr << "MM_MCINOTIFY message received"<<endl;
01234 #endif
01235 ((Windows_MCI*)(Audio::get_ptr()->get_midi()))->callback(event.syswm.msg->wParam,
01236 event.syswm.msg->hwnd);
01237 }
01238 break;
01239 #endif
01240 }
01241 }
01242
01243
01244
01245
01246
01247
01248
01249 static int Get_click
01250 (
01251 int& x, int& y,
01252 char *chr,
01253 bool drag_ok,
01254 Paintable *paint
01255 )
01256 {
01257 dragging = false;
01258 while (1)
01259 {
01260 SDL_Event event;
01261 Delay();
01262
01263 uint32 ticks = SDL_GetTicks();
01264 Game::set_ticks(ticks);
01265 Mouse::mouse->hide();
01266 Mouse::mouse_update = false;
01267
01268
01269 int scale = gwin->get_fastmouse() ? 1
01270 : gwin->get_win()->get_scale();
01271
01272 static bool rightclick;
01273 while (SDL_PollEvent(&event))
01274 switch (event.type)
01275 {
01276 case SDL_MOUSEBUTTONDOWN:
01277 if (event.button.button == 3)
01278 rightclick = true;
01279 else if (drag_ok && event.button.button == 1)
01280 {
01281 x = event.button.x / scale;
01282 y = event.button.y / scale;
01283 dragging = gwin->start_dragging(x, y);
01284 dragged = false;
01285 }
01286 break;
01287 case SDL_MOUSEBUTTONUP:
01288 if (event.button.button == 1)
01289 {
01290 x = event.button.x / scale;
01291 y = event.button.y / scale;
01292 bool drg = dragging, drged = dragged;
01293 dragging = dragged = false;
01294 if (!drg ||
01295 !gwin->drop_dragged(x, y, drged))
01296 {
01297 if (chr) *chr = 0;
01298 return (1);
01299 }
01300 }
01301 else if (event.button.button == 3) {
01302
01303 gwin->get_main_actor()->stop();
01304 if (gwin->get_mouse3rd() && rightclick) {
01305 rightclick = false;
01306 return 0;
01307 }
01308 }
01309 break;
01310 case SDL_MOUSEMOTION:
01311 {
01312 int mx = event.motion.x / scale,
01313 my = event.motion.y / scale;
01314 Mouse::mouse->move(mx, my);
01315 Mouse::mouse_update = true;
01316 if (drag_ok &&
01317 (event.motion.state & SDL_BUTTON(1)))
01318 dragged = gwin->drag(mx, my);
01319 break;
01320 }
01321 case SDL_KEYDOWN:
01322 {
01323
01324 int c = event.key.keysym.sym;
01325 switch(c) {
01326 case SDLK_ESCAPE:
01327 return 0;
01328 case SDLK_RSHIFT: case SDLK_LSHIFT:
01329 case SDLK_RCTRL: case SDLK_LCTRL:
01330 case SDLK_RALT: case SDLK_LALT:
01331 case SDLK_RMETA: case SDLK_LMETA:
01332 case SDLK_RSUPER: case SDLK_LSUPER:
01333 case SDLK_NUMLOCK: case SDLK_CAPSLOCK:
01334 case SDLK_SCROLLOCK:
01335 break;
01336 default:
01337 if ((c == 's') &&
01338 (event.key.keysym.mod & KMOD_ALT) &&
01339 (event.key.keysym.mod & KMOD_CTRL)){
01340 make_screenshot(true);
01341 break;
01342 }
01343 if (chr)
01344 {
01345 *chr = (event.key.keysym.mod &
01346 KMOD_SHIFT)
01347 ? toupper(c) : c;
01348 return (1);
01349 }
01350 break;
01351 }
01352 break;
01353 }
01354 case SDL_ACTIVEEVENT:
01355 if (event.active.state & SDL_APPINPUTFOCUS)
01356 {
01357 if (event.active.gain)
01358 gwin->get_focus();
01359 else
01360 gwin->lose_focus();
01361 }
01362 }
01363 if (GL_manager::get_instance())
01364 {
01365 gwin->paint();
01366 if (paint)
01367 paint->paint();
01368 }
01369 else if (dragging)
01370 gwin->paint_dirty();
01371 Mouse::mouse->show();
01372 if (!gwin->show() &&
01373 Mouse::mouse_update)
01374 Mouse::mouse->blit_dirty();
01375 }
01376 return (0);
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386 int Get_click
01387 (
01388 int& x, int& y,
01389 Mouse::Mouse_shapes shape,
01390 char *chr,
01391 bool drag_ok,
01392 Paintable *paint
01393 )
01394 {
01395 if (chr)
01396 *chr = 0;
01397 Mouse::Mouse_shapes saveshape = Mouse::mouse->get_shape();
01398 if (shape != Mouse::dontchange)
01399 Mouse::mouse->set_shape(shape);
01400 if (paint)
01401 paint->paint();
01402 Mouse::mouse->show();
01403 gwin->show(1);
01404 gwin->get_tqueue()->pause(Game::get_ticks());
01405 int ret = Get_click(x, y, chr, drag_ok, paint);
01406 gwin->get_tqueue()->resume(Game::get_ticks());
01407 Mouse::mouse->set_shape(saveshape);
01408 return (ret);
01409 }
01410
01411
01412
01413
01414
01415
01416 void Wait_for_arrival
01417 (
01418 Actor *actor,
01419 Tile_coord dest,
01420 long maxticks
01421 )
01422 {
01423
01424 int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale();
01425
01426 unsigned char os = Mouse::mouse->is_onscreen();
01427 uint32 last_repaint = 0;
01428 Actor_action *orig_action = actor->get_action();
01429 uint32 stop_time = SDL_GetTicks() + maxticks;
01430 bool timeout = false;
01431 while (actor->is_moving() && actor->get_action() == orig_action &&
01432 actor->get_tile() != dest && !timeout)
01433 {
01434 Delay();
01435
01436 Mouse::mouse->hide();
01437 Mouse::mouse_update = false;
01438
01439 SDL_Event event;
01440 while (SDL_PollEvent(&event))
01441 switch (event.type)
01442 {
01443 case SDL_MOUSEMOTION:
01444 Mouse::mouse->move(event.motion.x / scale,
01445 event.motion.y / scale);
01446 Mouse::mouse_update = true;
01447 break;
01448 }
01449
01450 uint32 ticks = SDL_GetTicks();
01451 Game::set_ticks(ticks);
01452 if (maxticks && ticks > stop_time)
01453 timeout = true;
01454 if (gwin->have_focus())
01455 gwin->get_tqueue()->activate(ticks);
01456
01457 if (ticks > last_repaint + 50 || gwin->was_painted())
01458 {
01459 gwin->paint_dirty();
01460 while (ticks > last_repaint+50)last_repaint += 50;
01461 }
01462
01463 Mouse::mouse->show();
01464 if (!gwin->show() &&
01465 Mouse::mouse_update)
01466 Mouse::mouse->blit_dirty();
01467 }
01468
01469 if (!os)
01470 Mouse::mouse->hide();
01471
01472 }
01473
01474
01475
01476
01477
01478 static void Shift_wizards_eye
01479 (
01480 int mx, int my
01481 )
01482 {
01483
01484 int cx = gwin->get_width()/2, cy = gwin->get_height()/2;
01485 int dy = cy - my, dx = mx - cx;
01486 Direction dir = Get_direction(dy, dx);
01487 static int deltas[16] = {0,-1, 1,-1, 1,0, 1,1, 0,1,
01488 -1,1, -1,0, -1,-1};
01489 int dirx = deltas[2*dir], diry = deltas[2*dir + 1];
01490 if (dirx == 1)
01491 gwin->view_right();
01492 else if (dirx == -1)
01493 gwin->view_left();
01494 if (diry == 1)
01495 gwin->view_down();
01496 else if (diry == -1)
01497 gwin->view_up();
01498 }
01499
01500
01501
01502
01503
01504 void Wizard_eye
01505 (
01506 long msecs
01507 )
01508 {
01509
01510 int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale();
01511
01512 int cx = gwin->get_width()/2, cy = gwin->get_height()/2;
01513
01514 unsigned char os = Mouse::mouse->is_onscreen();
01515 uint32 last_repaint = 0;
01516 uint32 stop_time = SDL_GetTicks() + msecs;
01517 bool timeout = false;
01518 while (!timeout)
01519 {
01520 Delay();
01521
01522 Mouse::mouse->hide();
01523 Mouse::mouse_update = false;
01524
01525 SDL_Event event;
01526 while (SDL_PollEvent(&event))
01527 switch (event.type)
01528 {
01529 case SDL_MOUSEMOTION:
01530 {
01531 int mx = event.motion.x/scale,
01532 my = event.motion.y/scale;
01533 Mouse::mouse->move(mx, my);
01534 Mouse::mouse->set_shape(
01535 Mouse::mouse->get_short_arrow(
01536 Get_direction(cy - my, mx - cx)));
01537 Mouse::mouse_update = true;
01538 break;
01539 }
01540 case SDL_KEYDOWN:
01541 if (event.key.keysym.sym == SDLK_ESCAPE)
01542 timeout = true;
01543 }
01544
01545 uint32 ticks = SDL_GetTicks();
01546 Game::set_ticks(ticks);
01547 if (ticks > stop_time)
01548 timeout = true;
01549 if (gwin->have_focus())
01550 gwin->get_tqueue()->activate(ticks);
01551
01552 if (ticks > last_repaint + 50 || gwin->was_painted())
01553 {
01554 int x, y;
01555 int ms = SDL_GetMouseState(&x, &y);
01556 if (SDL_BUTTON(3) & ms)
01557 Shift_wizards_eye(x/scale, y/scale);
01558 gwin->set_all_dirty();
01559 gwin->paint_dirty();
01560
01561 ShapeID eye(10, 0, SF_SPRITES_VGA);
01562 Shape_frame *spr = eye.get_shape();
01563
01564 int w = gwin->get_width(), h = gwin->get_height();
01565 int sw = spr->get_width(), sh = spr->get_height();
01566 int topx = (w - sw)/2,
01567 topy = (h - sh)/2;
01568 eye.paint_shape(topx + spr->get_xleft(),
01569 topy + spr->get_yabove());
01570 if (topy > 0)
01571 {
01572 gwin->get_win()->fill8(0, w, topy, 0, 0);
01573 gwin->get_win()->fill8(0, w, h - topy - sh,
01574 0, topy + sh);
01575 }
01576 if (topx > 0)
01577 {
01578 gwin->get_win()->fill8(0, topx, sh, 0, topy);
01579 gwin->get_win()->fill8(0, w - topx - sw, sh,
01580 topx + sw, topy);
01581 }
01582 while (ticks > last_repaint+50)last_repaint += 50;
01583 }
01584
01585 Mouse::mouse->show();
01586 if (!gwin->show() &&
01587 Mouse::mouse_update)
01588 Mouse::mouse->blit_dirty();
01589 }
01590
01591 if (!os)
01592 Mouse::mouse->hide();
01593 gwin->center_view(gwin->get_main_actor()->get_tile());
01594 }
01595
01596
01597 int find_resolution(int w, int h, int s)
01598 {
01599 int res = 0;
01600 for(int i=0; i<num_res; i++) {
01601 if(res_list[i].x==w && res_list[i].y==h && res_list[i].scale==s)
01602 res = i;
01603 }
01604 return res;
01605 }
01606
01607
01608 void set_resolution (int new_res, bool save)
01609 {
01610 if(new_res>=0 && new_res<num_res) {
01611 int scaler = gwin->get_win()->get_scaler();
01612 current_res = new_res;
01613 gwin->resized(res_list[current_res].x,
01614 res_list[current_res].y,
01615 res_list[current_res].scale, scaler);
01616 if(save) {
01617 char val[20];
01618 snprintf(val, 20, "%d", res_list[current_res].x);
01619 config->set("config/video/width",val,true);
01620 snprintf(val, 20, "%d", res_list[current_res].y);
01621 config->set("config/video/height",val,true);
01622 snprintf(val, 20, "%d", res_list[current_res].scale);
01623 config->set("config/video/scale",val,true);
01624
01625
01626 if (scaler > Image_window::NoScaler && scaler < Image_window::NumScalers)
01627 config->set("config/video/scale_method",Image_window::get_name_for_scaler(scaler),true);
01628 }
01629 }
01630 }
01631
01632 void increase_resolution()
01633 {
01634 if (!cheat()) return;
01635
01636 current_res++;
01637 if(current_res>=num_res)
01638 current_res = 0;
01639 set_resolution(current_res,false);
01640 }
01641
01642 void decrease_resolution()
01643 {
01644 if (!cheat()) return;
01645
01646 current_res--;
01647 if(current_res<0)
01648 current_res = num_res-1;
01649 set_resolution(current_res,false);
01650 }
01651
01652 void make_screenshot (bool silent)
01653 {
01654 char fn[15];
01655 int i;
01656 FILE *f;
01657 bool namefound = false;
01658 Effects_manager *eman = gwin->get_effects();
01659
01660
01661 for (i = 0; i < 1000 && !namefound; i++) {
01662 snprintf(fn, 15, "exult%03i.pcx", i);
01663 f = fopen(fn, "rb");
01664 if (f) {
01665 fclose(f);
01666 } else {
01667 namefound = true;
01668 }
01669 }
01670
01671 if (!namefound) {
01672 if (!silent) eman->center_text("Too many screenshots");
01673 } else {
01674 SDL_RWops *dst = SDL_RWFromFile(fn, "wb");
01675
01676 if (gwin->get_win()->screenshot(dst)) {
01677 cout << "Screenshot saved in " << fn << endl;
01678 if (!silent) eman->center_text("Screenshot");
01679 } else {
01680 if (!silent) eman->center_text("Screenshot failed");
01681 }
01682 }
01683 }
01684
01685 void change_gamma (bool down)
01686 {
01687 float r,g,b;
01688 char text[256];
01689 float delta = down?0.05:-0.05;
01690 Image_window8::get_gamma(r, g, b);
01691 Image_window8::set_gamma(r+delta, g+delta, b+delta);
01692 gwin->get_pal()->set(-1, -1);
01693
01694
01695 #ifdef HAVE_SNPRINTF
01696 Image_window8::get_gamma(r, g, b);
01697 snprintf (text, 256, "Gamma Set to R: %01.2f G: %01.2f B: %01.2f", r, g, b);
01698 #else
01699 strncpy (text, "Gamma Changed", 256);
01700 #endif
01701 gwin->get_effects()->center_text(text);
01702
01703 int igam = (int) ((r*10000)+0.5);
01704 snprintf (text, 256, "%d.%04d", igam/10000, igam%10000);
01705 config->set("config/video/gamma/red", text, true);
01706
01707 igam = (int) ((b*10000)+0.5);
01708 snprintf (text, 256, "%d.%04d", igam/10000, igam%10000);
01709 config->set("config/video/gamma/green", text, true);
01710
01711 igam = (int) ((g*10000)+0.5);
01712 snprintf (text, 256, "%d.%04d", igam/10000, igam%10000);
01713 config->set("config/video/gamma/blue", text, true);
01714 }
01715
01716 void BuildGameMap()
01717 {
01718 int w, h, sc, sclr;
01719
01720
01721
01722 if (arg_buildmap >= 0) {
01723 int maplift = 16;
01724 Exult_Game gametype;
01725 switch(arg_buildmap) {
01726 case 0: maplift = 16; break;
01727 case 1: maplift = 10; break;
01728 case 2: maplift = 5; break;
01729 }
01730
01731 if (run_bg) {
01732 gametype = BLACK_GATE;
01733 get_game_paths("blackgate");
01734 } else if (run_si) {
01735 gametype = SERPENT_ISLE;
01736 get_game_paths("serpentisle");
01737 } else {
01738 cerr << "You have to specify --bg or --si when using --buildmap" << endl;
01739 exit(1);
01740 }
01741
01742 h = w = c_tilesize * c_tiles_per_schunk; sc = 1, sclr = Image_window::point;
01743 Image_window8::set_gamma(1, 1, 1);
01744
01745 string fullscreenstr;
01746 config->value("config/video/fullscreen",fullscreenstr,"no");
01747
01748 config->set("config/video/fullscreen","no",false);
01749 gwin = new Game_window(w, h, sc, sclr);
01750
01751 config->set("config/video/fullscreen",fullscreenstr,true);
01752 Audio::Init();
01753 current_res = find_resolution(w, h, sc);
01754 Game::create_game(gametype);
01755 gwin->init_files(false);
01756 gwin->get_map()->init();
01757 gwin->get_pal()->set(0);
01758 for (int x = 0; x < c_num_chunks / c_chunks_per_schunk; x++) {
01759 for (int y = 0; y < c_num_chunks / c_chunks_per_schunk; y++) {
01760 gwin->paint_map_at_tile(0,0,w,h,x * c_tiles_per_schunk, y * c_tiles_per_schunk, maplift);
01761 char fn[15];
01762 snprintf(fn, 15, "u7map%x%x.pcx", x, y);
01763 SDL_RWops *dst = SDL_RWFromFile(fn, "wb");
01764 cerr << x << "," << y << ": ";
01765 gwin->get_win()->screenshot(dst);
01766 }
01767 }
01768 Audio::Destroy();
01769 exit(0);
01770 }
01771 }
01772
01773
01774 #ifdef USE_EXULTSTUDIO
01775
01776
01777
01778
01779
01780 static void Move_grid
01781 (
01782 int x, int y,
01783 int prevx, int prevy,
01784 bool ireg,
01785 int xtiles, int ytiles,
01786 int tiles_right, int tiles_below
01787
01788 )
01789 {
01790 int scale = gwin->get_win()->get_scale();
01791 x /= scale;
01792 y /= scale;
01793 int lift = cheat.get_edit_lift();
01794 x += lift*4 - 1;
01795 y += lift*4 - 1;
01796 int tx = x/c_tilesize;
01797 int ty = y/c_tilesize;
01798 tx += tiles_right;
01799 ty += tiles_below;
01800 if (prevx != -1)
01801 {
01802 prevx /= scale;
01803 prevy /= scale;
01804 prevx += lift*4 - 1;
01805 prevy += lift*4 - 1;
01806 int ptx = prevx/c_tilesize, pty = prevy/c_tilesize;
01807 if (tx == ptx && ty == pty)
01808 return;
01809
01810 const int pad = 8;
01811 Rectangle r((ptx - xtiles + 1)*c_tilesize - pad,
01812 (pty - ytiles + 1)*c_tilesize - pad,
01813 xtiles*c_tilesize + 2*pad,
01814 ytiles*c_tilesize + 2*pad);
01815 r = gwin->clip_to_win(r);
01816 gwin->add_dirty(r);
01817 gwin->paint_dirty();
01818 }
01819
01820 if (ireg && gwin->get_gump_man()->find_gump(x, y))
01821 return;
01822 tx -= xtiles - 1;
01823 ty -= ytiles - 1;
01824
01825 int pix = Shape_manager::get_instance()->get_special_pixel(
01826 POISON_PIXEL);
01827 Image_window8 *win = gwin->get_win();
01828 win->set_clip(0, 0, win->get_width(), win->get_height());
01829 for (int Y = 0; Y <= ytiles; Y++)
01830 win->fill8(pix, xtiles*c_tilesize, 1,
01831 tx*c_tilesize, (ty + Y)*c_tilesize);
01832 for (int X = 0; X <= xtiles; X++)
01833 win->fill8(pix, 1, ytiles*c_tilesize,
01834 (tx + X)*c_tilesize, ty*c_tilesize);
01835 win->clear_clip();
01836 gwin->set_painted();
01837 }
01838
01839
01840
01841
01842
01843
01844 static void Move_dragged_shape
01845 (
01846 int shape, int frame,
01847
01848 int x, int y,
01849 int prevx, int prevy,
01850 bool show
01851 )
01852 {
01853 if (shape == -1)
01854 {
01855 gwin->set_all_dirty();
01856 return;
01857 }
01858 Shape_info& info = ShapeID::get_info(shape);
01859
01860 int xtiles = info.get_3d_xtiles(frame),
01861 ytiles = info.get_3d_ytiles(frame);
01862 int sclass = info.get_shape_class();
01863
01864 bool ireg = (sclass != Shape_info::unusable &&
01865 sclass != Shape_info::building);
01866 Move_grid(x, y, prevx, prevy, ireg, xtiles, ytiles, 0, 0);
01867 if (show)
01868 gwin->show();
01869 }
01870
01871
01872
01873
01874
01875 static void Move_dragged_combo
01876 (
01877 int xtiles, int ytiles,
01878 int tiles_right,
01879 int tiles_below,
01880 int x, int y,
01881 int prevx, int prevy,
01882 bool show
01883 )
01884 {
01885 Move_grid(x, y, prevx, prevy, false, xtiles, ytiles, tiles_right,
01886 tiles_below);
01887 if (show)
01888 gwin->show();
01889 }
01890
01891
01892
01893
01894
01895 static Game_object *Create_object
01896 (
01897 int shape, int frame,
01898 bool& ireg
01899 )
01900 {
01901 Shape_info& info = ShapeID::get_info(shape);
01902 int sclass = info.get_shape_class();
01903
01904 ireg = (sclass != Shape_info::unusable &&
01905 sclass != Shape_info::building);
01906 Game_object *newobj;
01907 if (ireg)
01908 newobj = gwin->get_map()->create_ireg_object(
01909 info, shape, frame, 0, 0, 0);
01910 else
01911 newobj = gwin->get_map()->create_ifix_object(shape, frame);
01912 return newobj;
01913 }
01914
01915
01916
01917
01918
01919
01920 static void Drop_dragged_shape
01921 (
01922 int shape, int frame,
01923 int x, int y,
01924 void *data
01925 )
01926 {
01927 int scale = gwin->get_win()->get_scale();
01928 if (!cheat.in_map_editor())
01929 cheat.toggle_map_editor();
01930 cheat.clear_selected();
01931 gwin->get_map()->set_map_modified();
01932 x /= scale;
01933 y /= scale;
01934 ShapeID sid(shape, frame);
01935 if (gwin->skip_lift == 0)
01936 {
01937 int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles;
01938 int ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles;
01939 int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk;
01940 Map_chunk *chunk = gwin->get_map()->get_chunk(cx, cy);
01941 Chunk_terrain *ter = chunk->get_terrain();
01942 tx %= c_tiles_per_chunk; ty %= c_tiles_per_chunk;
01943 ShapeID curid = ter->get_flat(tx, ty);
01944 if (sid.get_shapenum() != curid.get_shapenum() ||
01945 sid.get_framenum() != curid.get_framenum())
01946 {
01947 ter->set_flat(tx, ty, sid);
01948 gwin->set_all_dirty();
01949 }
01950 return;
01951 }
01952 Shape_frame *sh = sid.get_shape();
01953 if (!sh || !sh->is_rle())
01954 return;
01955 cout << "Last drag pos: (" << x << ", " << y << ')' << endl;
01956 cout << "Create shape (" << shape << '/' << frame << ')' <<
01957 endl;
01958 bool ireg;
01959 Game_object *newobj = Create_object(shape, frame, ireg);
01960 Dragging_info drag(newobj);
01961 drag.drop(x, y, true);
01962 }
01963
01964
01965
01966
01967
01968
01969 static void Drop_dragged_chunk
01970 (
01971 int chunknum,
01972 int x, int y,
01973 void *data
01974 )
01975 {
01976 int scale = gwin->get_win()->get_scale();
01977 if (!cheat.in_map_editor())
01978 cheat.toggle_map_editor();
01979 x /= scale;
01980 y /= scale;
01981 cout << "Last drag pos: (" << x << ", " << y << ')' << endl;
01982 cout << "Set chunk (" << chunknum << ')' << endl;
01983
01984 int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles,
01985 ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles;
01986 int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk;
01987 gwin->get_map()->set_chunk_terrain(cx, cy, chunknum);
01988 gwin->paint();
01989 }
01990
01991
01992
01993
01994
01995 void Drop_dragged_combo
01996 (
01997 int cnt,
01998 U7_combo_data *combo,
01999 int x, int y,
02000 void *data
02001 )
02002 {
02003 int scale = gwin->get_win()->get_scale();
02004 if (!cheat.in_map_editor())
02005 cheat.toggle_map_editor();
02006 cheat.clear_selected();
02007 x /= scale;
02008 y /= scale;
02009 int at_lift = cheat.get_edit_lift();
02010 x += at_lift*4 - 1;
02011 y += at_lift*4 - 1;
02012
02013 int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles,
02014 ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles;
02015 for (int i = 0; i < cnt; i++)
02016 {
02017 U7_combo_data& elem = combo[i];
02018
02019 int ntx = (tx + elem.tx)%c_num_tiles,
02020 nty = (ty + elem.ty)%c_num_tiles,
02021 ntz = at_lift + elem.tz;
02022 if (ntz < 0)
02023 ntz = 0;
02024 ShapeID sid(elem.shape, elem.frame);
02025 if (gwin->skip_lift == 0)
02026 {
02027 int cx = ntx/c_tiles_per_chunk,
02028 cy = nty/c_tiles_per_chunk;
02029 Map_chunk *chunk = gwin->get_map()->get_chunk(cx, cy);
02030 Chunk_terrain *ter = chunk->get_terrain();
02031 ntx %= c_tiles_per_chunk; nty %= c_tiles_per_chunk;
02032 ter->set_flat(ntx, nty, sid);
02033 continue;
02034 }
02035 bool ireg;
02036 Game_object *newobj = Create_object(elem.shape,
02037 elem.frame, ireg);
02038 newobj->set_invalid();
02039 newobj->move(ntx, nty, ntz);
02040
02041 cheat.append_selected(newobj);
02042 }
02043 gwin->set_all_dirty();
02044 }
02045
02046 #endif