GUIApp.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2002-2007 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (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 #include "pent_include.h"
00020 
00021 #include "GUIApp.h"
00022 
00023 #include <SDL.h>
00024 
00026 #include "Kernel.h"
00027 #include "FileSystem.h"
00028 #include "SettingManager.h"
00029 #include "ConfigFileManager.h"
00030 #include "ObjectManager.h"
00031 #include "GameInfo.h"
00032 #include "FontManager.h"
00033 #include "MemoryManager.h"
00034 
00035 #include "HIDManager.h"
00036 #include "Joystick.h"
00037 
00038 #include "RenderSurface.h"
00039 #include "Texture.h"
00040 #include "FixedWidthFont.h"
00041 #include "PaletteManager.h"
00042 #include "Palette.h"
00043 #include "GameData.h"
00044 #include "World.h"
00045 #include "Direction.h"
00046 #include "Game.h"
00047 #include "getObject.h"
00048 
00049 #include "SavegameWriter.h"
00050 #include "Savegame.h"
00051 #include <ctime>
00052 
00053 #include "Gump.h"
00054 #include "DesktopGump.h"
00055 #include "ConsoleGump.h"
00056 #include "GameMapGump.h"
00057 #include "InverterGump.h"
00058 #include "ScalerGump.h"
00059 #include "FastAreaVisGump.h"
00060 #include "MiniMapGump.h"
00061 #include "QuitGump.h"
00062 #include "MenuGump.h"
00063 #include "PentagramMenuGump.h"
00064 
00065 // For gump positioning... perhaps shouldn't do it this way....
00066 #include "BarkGump.h"
00067 #include "AskGump.h"
00068 #include "ModalGump.h"
00069 
00070 
00071 #include "QuickAvatarMoverProcess.h"
00072 #include "Actor.h"
00073 #include "ActorAnimProcess.h"
00074 #include "TargetedAnimProcess.h"
00075 #include "u8intrinsics.h"
00076 #include "remorseintrinsics.h"
00077 #include "Egg.h"
00078 #include "CurrentMap.h"
00079 #include "InverterProcess.h"
00080 #include "HealProcess.h"
00081 #include "SchedulerProcess.h"
00082 
00083 #include "EggHatcherProcess.h" // for a hack
00084 #include "UCProcess.h" // more hacking
00085 #include "GumpNotifyProcess.h" // guess
00086 #include "ActorBarkNotifyProcess.h" // guess
00087 #include "DelayProcess.h"
00088 #include "AvatarGravityProcess.h"
00089 #include "MissileProcess.h"
00090 #include "TeleportToEggProcess.h"
00091 #include "ItemFactory.h"
00092 #include "PathfinderProcess.h"
00093 #include "AvatarMoverProcess.h"
00094 #include "ResurrectionProcess.h"
00095 #include "SplitItemProcess.h"
00096 #include "ClearFeignDeathProcess.h"
00097 #include "LoiterProcess.h"
00098 #include "AvatarDeathProcess.h"
00099 #include "GrantPeaceProcess.h"
00100 #include "CombatProcess.h"
00101 #include "FireballProcess.h"
00102 #include "DestroyItemProcess.h"
00103 #include "AmbushProcess.h"
00104 #include "Pathfinder.h"
00105 
00106 #include "MovieGump.h"
00107 #include "ShapeViewerGump.h"
00108 
00109 #include "AudioMixer.h"
00110 
00111 #ifdef WIN32
00112 #include <windows.h>
00113 #endif
00114 
00115 #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
00116 #include "Shape.h"
00117 #include "ShapeFrame.h"
00118 #include "SoftRenderSurface.h"
00119 #include "SDL_syswm.h"
00120 
00121 struct HWMouseCursor {
00122         HICON hCursor;
00123 };
00124 
00125 #endif
00126 
00127 #include "XFormBlend.h"
00128 
00129 #include "MusicProcess.h"
00130 #include "AudioProcess.h"
00131 
00132 #include "util.h"
00133 
00134 using std::string;
00135 
00136 DEFINE_RUNTIME_CLASSTYPE_CODE(GUIApp,CoreApp);
00137 
00138 GUIApp::GUIApp(int argc, const char* const* argv)
00139         : CoreApp(argc, argv), save_count(0), game(0), kernel(0), objectmanager(0),
00140           hidmanager(0), ucmachine(0), screen(0), fullscreen(false), palettemanager(0), 
00141           gamedata(0), world(0), desktopGump(0), consoleGump(0), gameMapGump(0),
00142           avatarMoverProcess(0), runSDLInit(false),
00143           frameSkip(false), frameLimit(true), interpolate(false),
00144           animationRate(100), avatarInStasis(false), paintEditorItems(false),
00145           painting(false), showTouching(false), mouseX(0), mouseY(0),
00146           defMouse(0), flashingcursor(0), 
00147           mouseOverGump(0), dragging(DRAG_NOT), dragging_offsetX(0),
00148           dragging_offsetY(0), inversion(0), timeOffset(0), has_cheated(false),
00149           drawRenderStats(false), ttfoverrides(false), audiomixer(0)
00150 {
00151         application = this;
00152 
00153         for (int i = 0; i < MOUSE_LAST; ++i) {
00154                 mouseButton[i].downGump = 0;
00155                 mouseButton[i].lastDown = 0;
00156                 mouseButton[i].state = MBS_HANDLED;
00157         }
00158 
00159         con.AddConsoleCommand("quit", ConCmd_quit);
00160         con.AddConsoleCommand("GUIApp::quit", ConCmd_quit);
00161         con.AddConsoleCommand("QuitGump::verifyQuit", QuitGump::ConCmd_verifyQuit);
00162         con.AddConsoleCommand("ShapeViewerGump::U8ShapeViewer", ShapeViewerGump::ConCmd_U8ShapeViewer);
00163         con.AddConsoleCommand("MenuGump::showMenu", MenuGump::ConCmd_showMenu);
00164         con.AddConsoleCommand("GUIApp::drawRenderStats", ConCmd_drawRenderStats);
00165         con.AddConsoleCommand("GUIApp::engineStats", ConCmd_engineStats);
00166 
00167         con.AddConsoleCommand("GUIApp::changeGame",ConCmd_changeGame);
00168         con.AddConsoleCommand("GUIApp::listGames",ConCmd_listGames);
00169 
00170         con.AddConsoleCommand("GUIApp::setVideoMode",ConCmd_setVideoMode);
00171         con.AddConsoleCommand("GUIApp::toggleFullscreen",ConCmd_toggleFullscreen);
00172 
00173         con.AddConsoleCommand("GUIApp::toggleAvatarInStasis",ConCmd_toggleAvatarInStasis);
00174         con.AddConsoleCommand("GUIApp::togglePaintEditorItems",ConCmd_togglePaintEditorItems);
00175         con.AddConsoleCommand("GUIApp::toggleShowTouchingItems",ConCmd_toggleShowTouchingItems);
00176 
00177         con.AddConsoleCommand("GUIApp::closeItemGumps",ConCmd_closeItemGumps);
00178 
00179         con.AddConsoleCommand("HIDManager::bind", HIDManager::ConCmd_bind);
00180         con.AddConsoleCommand("HIDManager::unbind", HIDManager::ConCmd_unbind);
00181         con.AddConsoleCommand("HIDManager::listbinds",
00182                                                   HIDManager::ConCmd_listbinds);
00183         con.AddConsoleCommand("HIDManager::save", HIDManager::ConCmd_save);
00184         con.AddConsoleCommand("Kernel::processTypes", Kernel::ConCmd_processTypes);
00185         con.AddConsoleCommand("Kernel::processInfo", Kernel::ConCmd_processInfo);
00186         con.AddConsoleCommand("Kernel::listProcesses",
00187                                                   Kernel::ConCmd_listProcesses);
00188         con.AddConsoleCommand("Kernel::toggleFrameByFrame",
00189                                                   Kernel::ConCmd_toggleFrameByFrame);
00190         con.AddConsoleCommand("Kernel::advanceFrame", Kernel::ConCmd_advanceFrame);
00191         con.AddConsoleCommand("ObjectManager::objectTypes",
00192                                                   ObjectManager::ConCmd_objectTypes);
00193         con.AddConsoleCommand("ObjectManager::objectInfo",
00194                                                   ObjectManager::ConCmd_objectInfo);
00195         con.AddConsoleCommand("MemoryManager::MemInfo",
00196                                                   MemoryManager::ConCmd_MemInfo);
00197         con.AddConsoleCommand("MemoryManager::test",
00198                                                   MemoryManager::ConCmd_test);
00199 
00200         con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveUp",
00201                                                   QuickAvatarMoverProcess::ConCmd_startMoveUp);
00202         con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveDown",
00203                                                   QuickAvatarMoverProcess::ConCmd_startMoveDown);
00204         con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveLeft",
00205                                                   QuickAvatarMoverProcess::ConCmd_startMoveLeft);
00206         con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveRight",
00207                                                   QuickAvatarMoverProcess::ConCmd_startMoveRight);
00208         con.AddConsoleCommand("QuickAvatarMoverProcess::startAscend",
00209                                                   QuickAvatarMoverProcess::ConCmd_startAscend);
00210         con.AddConsoleCommand("QuickAvatarMoverProcess::startDescend",
00211                                                   QuickAvatarMoverProcess::ConCmd_startDescend);
00212         con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveUp",
00213                                                   QuickAvatarMoverProcess::ConCmd_stopMoveUp);
00214         con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveDown",
00215                                                   QuickAvatarMoverProcess::ConCmd_stopMoveDown);
00216         con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveLeft",
00217                                                   QuickAvatarMoverProcess::ConCmd_stopMoveLeft);
00218         con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveRight",
00219                                                   QuickAvatarMoverProcess::ConCmd_stopMoveRight);
00220         con.AddConsoleCommand("QuickAvatarMoverProcess::stopAscend",
00221                                                   QuickAvatarMoverProcess::ConCmd_stopAscend);
00222         con.AddConsoleCommand("QuickAvatarMoverProcess::stopDescend",
00223                                                   QuickAvatarMoverProcess::ConCmd_stopDescend);
00224         con.AddConsoleCommand("QuickAvatarMoverProcess::toggleQuarterSpeed",
00225                                                   QuickAvatarMoverProcess::ConCmd_toggleQuarterSpeed);
00226         con.AddConsoleCommand("QuickAvatarMoverProcess::toggleClipping",
00227                                                   QuickAvatarMoverProcess::ConCmd_toggleClipping);
00228 
00229         con.AddConsoleCommand("GameMapGump::toggleHighlightItems",
00230                                                   GameMapGump::ConCmd_toggleHighlightItems);
00231         con.AddConsoleCommand("GameMapGump::dumpMap",
00232                                                   GameMapGump::ConCmd_dumpMap);
00233 
00234         con.AddConsoleCommand("AudioProcess::listSFX", AudioProcess::ConCmd_listSFX);
00235         con.AddConsoleCommand("AudioProcess::playSFX", AudioProcess::ConCmd_playSFX);
00236         con.AddConsoleCommand("AudioProcess::stopSFX", AudioProcess::ConCmd_stopSFX);
00237 
00238         // Game related console commands are now added in startupGame
00239 }
00240 
00241 GUIApp::~GUIApp()
00242 {
00243         shutdown();
00244 
00245         con.RemoveConsoleCommand(GUIApp::ConCmd_quit);
00246         con.RemoveConsoleCommand(QuitGump::ConCmd_verifyQuit);
00247         con.RemoveConsoleCommand(ShapeViewerGump::ConCmd_U8ShapeViewer);
00248         con.RemoveConsoleCommand(MenuGump::ConCmd_showMenu);
00249         con.RemoveConsoleCommand(GUIApp::ConCmd_drawRenderStats);
00250         con.RemoveConsoleCommand(GUIApp::ConCmd_engineStats);
00251 
00252         con.RemoveConsoleCommand(GUIApp::ConCmd_changeGame);
00253         con.RemoveConsoleCommand(GUIApp::ConCmd_listGames);
00254 
00255         con.RemoveConsoleCommand(GUIApp::ConCmd_setVideoMode);
00256         con.RemoveConsoleCommand(GUIApp::ConCmd_toggleFullscreen);
00257 
00258         con.RemoveConsoleCommand(GUIApp::ConCmd_toggleAvatarInStasis);
00259         con.RemoveConsoleCommand(GUIApp::ConCmd_togglePaintEditorItems);
00260         con.RemoveConsoleCommand(GUIApp::ConCmd_toggleShowTouchingItems);
00261 
00262         con.RemoveConsoleCommand(GUIApp::ConCmd_closeItemGumps);
00263 
00264         con.RemoveConsoleCommand(HIDManager::ConCmd_bind);
00265         con.RemoveConsoleCommand(HIDManager::ConCmd_unbind);
00266         con.RemoveConsoleCommand(HIDManager::ConCmd_listbinds);
00267         con.RemoveConsoleCommand(HIDManager::ConCmd_save);
00268         con.RemoveConsoleCommand(Kernel::ConCmd_processTypes);
00269         con.RemoveConsoleCommand(Kernel::ConCmd_processInfo);
00270         con.RemoveConsoleCommand(Kernel::ConCmd_listProcesses);
00271         con.RemoveConsoleCommand(Kernel::ConCmd_toggleFrameByFrame);
00272         con.RemoveConsoleCommand(Kernel::ConCmd_advanceFrame);
00273         con.RemoveConsoleCommand(ObjectManager::ConCmd_objectTypes);
00274         con.RemoveConsoleCommand(ObjectManager::ConCmd_objectInfo);
00275         con.RemoveConsoleCommand(MemoryManager::ConCmd_MemInfo);
00276         con.RemoveConsoleCommand(MemoryManager::ConCmd_test);
00277 
00278         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveUp);
00279         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveDown);
00280         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveLeft);
00281         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveRight);
00282         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startAscend);
00283         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startDescend);
00284         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveUp);
00285         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveDown);
00286         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveLeft);
00287         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveRight);
00288         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopAscend);
00289         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopDescend);
00290         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_toggleQuarterSpeed);
00291         con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_toggleClipping);
00292 
00293         con.RemoveConsoleCommand(GameMapGump::ConCmd_toggleHighlightItems);
00294         con.RemoveConsoleCommand(GameMapGump::ConCmd_dumpMap);
00295 
00296         con.RemoveConsoleCommand(AudioProcess::ConCmd_listSFX);
00297         con.RemoveConsoleCommand(AudioProcess::ConCmd_stopSFX);
00298         con.RemoveConsoleCommand(AudioProcess::ConCmd_playSFX);
00299 
00300         // Game related console commands are now removed in shutdownGame
00301 
00302         FORGET_OBJECT(kernel);
00303         FORGET_OBJECT(defMouse);
00304         FORGET_OBJECT(objectmanager);
00305         FORGET_OBJECT(hidmanager);
00306         FORGET_OBJECT(audiomixer);
00307         FORGET_OBJECT(ucmachine);
00308         FORGET_OBJECT(palettemanager);
00309         FORGET_OBJECT(gamedata);
00310         FORGET_OBJECT(world);
00311         FORGET_OBJECT(ucmachine);
00312         FORGET_OBJECT(fontmanager);
00313         FORGET_OBJECT(screen);
00314 }
00315 
00316 // Init sdl
00317 void GUIApp::SDLInit()
00318 {
00319         con.Print(MM_INFO, "Initialising SDL...\n");
00320         SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
00321         atexit(SDL_Quit);
00322 }
00323 
00324 void GUIApp::startup()
00325 {
00326         SDLInit();
00327 
00328         // Set the console to auto paint, till we have finished initing
00329         con.SetAutoPaint(conAutoPaint);
00330 
00331         pout << "-- Initializing Pentagram -- " << std::endl;
00332 
00333         // parent's startup first
00334         CoreApp::startup();
00335 
00336         bool dataoverride;
00337         if (!settingman->get("dataoverride", dataoverride,
00338                                                  SettingManager::DOM_GLOBAL))
00339                 dataoverride = false;
00340         filesystem->initBuiltinData(dataoverride);
00341 
00342         kernel = new Kernel();
00343 
00345         kernel->addProcessLoader("DelayProcess",
00346                                                          ProcessLoader<DelayProcess>::load);
00347         kernel->addProcessLoader("GravityProcess",
00348                                                          ProcessLoader<GravityProcess>::load);
00349         kernel->addProcessLoader("AvatarGravityProcess",
00350                                                          ProcessLoader<AvatarGravityProcess>::load);
00351         kernel->addProcessLoader("PaletteFaderProcess",
00352                                                          ProcessLoader<PaletteFaderProcess>::load);
00353         kernel->addProcessLoader("TeleportToEggProcess",
00354                                                          ProcessLoader<TeleportToEggProcess>::load);
00355         kernel->addProcessLoader("ActorAnimProcess",
00356                                                          ProcessLoader<ActorAnimProcess>::load);
00357         kernel->addProcessLoader("TargetedAnimProcess",
00358                                                          ProcessLoader<TargetedAnimProcess>::load);
00359         kernel->addProcessLoader("AvatarMoverProcess",
00360                                                          ProcessLoader<AvatarMoverProcess>::load);
00361         kernel->addProcessLoader("QuickAvatarMoverProcess",
00362                                                          ProcessLoader<QuickAvatarMoverProcess>::load);
00363         kernel->addProcessLoader("PathfinderProcess",
00364                                                          ProcessLoader<PathfinderProcess>::load);
00365         kernel->addProcessLoader("SpriteProcess",
00366                                                          ProcessLoader<SpriteProcess>::load);
00367         kernel->addProcessLoader("MissileProcess",
00368                                                          ProcessLoader<MissileProcess>::load);
00369         kernel->addProcessLoader("CameraProcess",
00370                                                          ProcessLoader<CameraProcess>::load);
00371         kernel->addProcessLoader("MusicProcess",
00372                                                          ProcessLoader<MusicProcess>::load);
00373         kernel->addProcessLoader("AudioProcess",
00374                                                          ProcessLoader<AudioProcess>::load);
00375         kernel->addProcessLoader("EggHatcherProcess",
00376                                                          ProcessLoader<EggHatcherProcess>::load);
00377         kernel->addProcessLoader("UCProcess",
00378                                                          ProcessLoader<UCProcess>::load);
00379         kernel->addProcessLoader("GumpNotifyProcess",
00380                                                          ProcessLoader<GumpNotifyProcess>::load);
00381         kernel->addProcessLoader("ResurrectionProcess",
00382                                                          ProcessLoader<ResurrectionProcess>::load);
00383         kernel->addProcessLoader("DeleteActorProcess",
00384                                                          ProcessLoader<DestroyItemProcess>::load);      // YES, this is intentional
00385         kernel->addProcessLoader("DestroyItemProcess",
00386                                                          ProcessLoader<DestroyItemProcess>::load);
00387         kernel->addProcessLoader("SplitItemProcess",
00388                                                          ProcessLoader<SplitItemProcess>::load);
00389         kernel->addProcessLoader("ClearFeignDeathProcess",
00390                                                          ProcessLoader<ClearFeignDeathProcess>::load);
00391         kernel->addProcessLoader("LoiterProcess",
00392                                                          ProcessLoader<LoiterProcess>::load);
00393         kernel->addProcessLoader("AvatarDeathProcess",
00394                                                          ProcessLoader<AvatarDeathProcess>::load);
00395         kernel->addProcessLoader("GrantPeaceProcess",
00396                                                          ProcessLoader<GrantPeaceProcess>::load);
00397         kernel->addProcessLoader("CombatProcess",
00398                                                          ProcessLoader<CombatProcess>::load);
00399         kernel->addProcessLoader("FireballProcess",
00400                                                          ProcessLoader<FireballProcess>::load);
00401         kernel->addProcessLoader("HealProcess",
00402                                                          ProcessLoader<HealProcess>::load);
00403         kernel->addProcessLoader("SchedulerProcess",
00404                                                          ProcessLoader<SchedulerProcess>::load);
00405         kernel->addProcessLoader("InverterProcess",
00406                                                          ProcessLoader<InverterProcess>::load);
00407         kernel->addProcessLoader("ActorBarkNotifyProcess",
00408                                                          ProcessLoader<ActorBarkNotifyProcess>::load);
00409         kernel->addProcessLoader("JoystickCursorProcess",
00410                                                          ProcessLoader<JoystickCursorProcess>::load);
00411         kernel->addProcessLoader("AmbushProcess",
00412                                                          ProcessLoader<AmbushProcess>::load);
00413 
00414         objectmanager = new ObjectManager();
00415 
00416         GraphicSysInit();
00417 
00418         SDL_ShowCursor(SDL_DISABLE);
00419         SDL_GetMouseState(&mouseX, &mouseY);
00420 
00421         hidmanager = new HIDManager();
00422 
00423         // Audio Mixer
00424         audiomixer = new Pentagram::AudioMixer(22050,true,8);
00425 
00426         pout << "-- Pentagram Initialized -- " << std::endl << std::endl;
00427 
00428         // We Attempt to startup game
00429         setupGameList();
00430         GameInfo* info = getDefaultGame();
00431         if (setupGame(info))
00432                 startupGame();
00433         else
00434                 startupPentagramMenu();
00435 
00436         // Unset the console auto paint, since we have finished initing
00437         con.SetAutoPaint(0);
00438 
00439 //      pout << "Paint Initial display" << std::endl;
00440         paint();
00441 }
00442 
00443 void GUIApp::startupGame()
00444 {
00445         con.SetAutoPaint(conAutoPaint);
00446 
00447         pout  << std::endl << "-- Initializing Game: " << gameinfo->name << " --" << std::endl;
00448 
00449         GraphicSysInit();
00450 
00451         // set window title to current game
00452         std::string title = "Pentagram - ";
00453         title += getGameInfo()->getGameTitle();
00454         SDL_WM_SetCaption(title.c_str(), "");
00455 
00456         // Generic Commands
00457         con.AddConsoleCommand("GUIApp::saveGame", ConCmd_saveGame);
00458         con.AddConsoleCommand("GUIApp::loadGame", ConCmd_loadGame);
00459         con.AddConsoleCommand("GUIApp::newGame", ConCmd_newGame);
00460 #ifdef DEBUG
00461         con.AddConsoleCommand("Pathfinder::visualDebug",
00462                                                   Pathfinder::ConCmd_visualDebug);
00463 #endif
00464 
00465         // U8 Game commands
00466         con.AddConsoleCommand("MainActor::teleport", MainActor::ConCmd_teleport);
00467         con.AddConsoleCommand("MainActor::mark", MainActor::ConCmd_mark);
00468         con.AddConsoleCommand("MainActor::recall", MainActor::ConCmd_recall);
00469         con.AddConsoleCommand("MainActor::listmarks", MainActor::ConCmd_listmarks);
00470         con.AddConsoleCommand("Cheat::maxstats", MainActor::ConCmd_maxstats);
00471         con.AddConsoleCommand("Cheat::heal", MainActor::ConCmd_heal);
00472         con.AddConsoleCommand("Cheat::toggleInvincibility", MainActor::ConCmd_toggleInvincibility);
00473         con.AddConsoleCommand("MainActor::name", MainActor::ConCmd_name);
00474         con.AddConsoleCommand("MovieGump::play", MovieGump::ConCmd_play);
00475         con.AddConsoleCommand("MusicProcess::playMusic", MusicProcess::ConCmd_playMusic);
00476         con.AddConsoleCommand("InverterProcess::invertScreen",
00477                                                   InverterProcess::ConCmd_invertScreen);
00478         con.AddConsoleCommand("FastAreaVisGump::toggle",
00479                                                   FastAreaVisGump::ConCmd_toggle);
00480         con.AddConsoleCommand("MiniMapGump::toggle",
00481                                                   MiniMapGump::ConCmd_toggle);
00482         con.AddConsoleCommand("MainActor::useBackpack",
00483                                                   MainActor::ConCmd_useBackpack);
00484         con.AddConsoleCommand("MainActor::useInventory",
00485                                                   MainActor::ConCmd_useInventory);
00486         con.AddConsoleCommand("MainActor::useRecall",
00487                                                   MainActor::ConCmd_useRecall);
00488         con.AddConsoleCommand("MainActor::useBedroll",
00489                                                   MainActor::ConCmd_useBedroll);
00490         con.AddConsoleCommand("MainActor::useKeyring",
00491                                                   MainActor::ConCmd_useKeyring);
00492         con.AddConsoleCommand("MainActor::toggleCombat",
00493                                                   MainActor::ConCmd_toggleCombat);
00494 
00495         gamedata = new GameData();
00496 
00497         std::string bindingsfile;
00498         if (GAME_IS_U8) {
00499                 bindingsfile = "@data/u8bindings.ini";
00500         } else if (GAME_IS_REMORSE) {
00501                 bindingsfile = "@data/remorsebindings.ini";
00502         }
00503         if (!bindingsfile.empty()) {
00504                 // system-wide config
00505                 if (configfileman->readConfigFile(bindingsfile,
00506                                                                                   "bindings", true))
00507                         con.Printf(MM_INFO, "%s... Ok\n", bindingsfile.c_str());
00508                 else
00509                         con.Printf(MM_MINOR_WARN, "%s... Failed\n", bindingsfile.c_str());
00510         }
00511 
00512         hidmanager->loadBindings();
00513         
00514         if (GAME_IS_U8) {
00515                 ucmachine = new UCMachine(U8Intrinsics, 256);
00516         } else if (GAME_IS_REMORSE) {
00517                 ucmachine = new UCMachine(RemorseIntrinsics, 308);
00518         } else {
00519                 CANT_HAPPEN_MSG("Invalid game type.");
00520         }
00521 
00522         inBetweenFrame = 0;
00523         lerpFactor = 256;
00524 
00525         // Initialize world
00526         world = new World();
00527         world->initMaps();
00528 
00529         game = Game::createGame(getGameInfo());
00530 
00531         settingman->setDefault("ttf", false);
00532         settingman->get("ttf", ttfoverrides);
00533 
00534         game->loadFiles();
00535         gamedata->setupFontOverrides();
00536 
00537         // Unset the console auto paint (can't have it from here on)
00538         con.SetAutoPaint(0);
00539 
00540         // Create Midi Driver for Ultima 8
00541         if (getGameInfo()->type == GameInfo::GAME_U8) 
00542                 audiomixer->openMidiOutput();
00543 
00544 #if 1
00545         newGame();
00546 #else
00547         loadGame("@save/quicksave");
00548 #endif
00549 
00550         consoleGump->HideConsole();
00551 
00552         pout << "-- Game Initialized --" << std::endl << std::endl;
00553 }
00554 
00555 void GUIApp::startupPentagramMenu()
00556 {
00557         con.SetAutoPaint(conAutoPaint);
00558 
00559         pout << std::endl << "-- Initializing Pentagram Menu -- " << std::endl;
00560 
00561         setupGame(getGameInfo("pentagram"));
00562         assert(gameinfo);
00563 
00564         GraphicSysInit();
00565 
00566         // Unset the console auto paint, since we have finished initing
00567         con.SetAutoPaint(0);
00568         consoleGump->HideConsole();
00569 
00570         Pentagram::Rect dims;
00571         desktopGump->GetDims(dims);
00572 
00573         Gump* menugump = new PentagramMenuGump(0,0,dims.w,dims.h);
00574         menugump->InitGump(0, true);
00575 }
00576 
00577 void GUIApp::shutdown()
00578 {
00579         shutdownGame(false);
00580 }
00581 
00582 void GUIApp::shutdownGame(bool reloading)
00583 {
00584         pout << "-- Shutting down Game -- " << std::endl;
00585 
00586         // Save config here....
00587 
00588         SDL_WM_SetCaption("Pentagram", "");
00589 
00590         textmodes.clear();
00591 
00592         // reset mouse cursor
00593         while (!cursors.empty()) cursors.pop();
00594         pushMouseCursor();
00595 
00596         if (audiomixer) {
00597                 audiomixer->closeMidiOutput();
00598                 audiomixer->reset();
00599         }
00600 
00601         FORGET_OBJECT(world);
00602         objectmanager->reset();
00603         FORGET_OBJECT(ucmachine);
00604         kernel->reset();
00605         palettemanager->reset();
00606         fontmanager->resetGameFonts();
00607 
00608         FORGET_OBJECT(game);
00609         FORGET_OBJECT(gamedata);
00610 
00611         desktopGump = 0;
00612         consoleGump = 0;
00613         gameMapGump = 0;
00614         scalerGump = 0;
00615         inverterGump = 0;
00616 
00617         timeOffset = -(sint32)Kernel::get_instance()->getFrameNum();
00618         inversion = 0;
00619         save_count = 0;
00620         has_cheated = false;
00621 
00622         // Generic Game 
00623         con.RemoveConsoleCommand(GUIApp::ConCmd_saveGame);
00624         con.RemoveConsoleCommand(GUIApp::ConCmd_loadGame);
00625         con.RemoveConsoleCommand(GUIApp::ConCmd_newGame);
00626 #ifdef DEBUG
00627         con.RemoveConsoleCommand(Pathfinder::ConCmd_visualDebug);
00628 #endif
00629 
00630         // U8 Only kind of
00631         con.RemoveConsoleCommand(MainActor::ConCmd_teleport);
00632         con.RemoveConsoleCommand(MainActor::ConCmd_mark);
00633         con.RemoveConsoleCommand(MainActor::ConCmd_recall);
00634         con.RemoveConsoleCommand(MainActor::ConCmd_listmarks);
00635         con.RemoveConsoleCommand(MainActor::ConCmd_maxstats);
00636         con.RemoveConsoleCommand(MainActor::ConCmd_heal);
00637         con.RemoveConsoleCommand(MainActor::ConCmd_toggleInvincibility);
00638         con.RemoveConsoleCommand(MainActor::ConCmd_name);
00639         con.RemoveConsoleCommand(MovieGump::ConCmd_play);
00640         con.RemoveConsoleCommand(MusicProcess::ConCmd_playMusic);
00641         con.RemoveConsoleCommand(InverterProcess::ConCmd_invertScreen);
00642         con.RemoveConsoleCommand(FastAreaVisGump::ConCmd_toggle);
00643         con.RemoveConsoleCommand(MiniMapGump::ConCmd_toggle);
00644         con.RemoveConsoleCommand(MainActor::ConCmd_useBackpack);
00645         con.RemoveConsoleCommand(MainActor::ConCmd_useInventory);
00646         con.RemoveConsoleCommand(MainActor::ConCmd_useRecall);
00647         con.RemoveConsoleCommand(MainActor::ConCmd_useBedroll);
00648         con.RemoveConsoleCommand(MainActor::ConCmd_useKeyring);
00649         con.RemoveConsoleCommand(MainActor::ConCmd_toggleCombat);
00650 
00651 
00652         // Kill Game
00653         CoreApp::killGame();
00654 
00655         pout << "-- Game Shutdown -- " << std::endl;
00656 
00657         if (reloading) {
00658                 Pentagram::Rect dims;
00659                 screen->GetSurfaceDims(dims);
00660 
00661                 con.Print(MM_INFO, "Creating Desktop...\n");
00662                 desktopGump = new DesktopGump(0,0, dims.w, dims.h);
00663                 desktopGump->InitGump(0);
00664                 desktopGump->MakeFocus();
00665 
00666                 con.Print(MM_INFO, "Creating Graphics Console...\n");
00667                 consoleGump = new ConsoleGump(0, 0, dims.w, dims.h);
00668                 consoleGump->InitGump(0);
00669 
00670                 enterTextMode(consoleGump);
00671         }
00672 }
00673 
00674 void GUIApp::changeGame(Pentagram::istring newgame)
00675 {
00676         change_gamename = newgame;
00677 }
00678 
00679 void GUIApp::DeclareArgs()
00680 {
00681         // parent's arguments first
00682         CoreApp::DeclareArgs();
00683 
00684         // anything else?
00685 }
00686 
00687 void GUIApp::run()
00688 {
00689         isRunning = true;
00690 
00691         sint32 next_ticks = SDL_GetTicks()*3;   // Next time is right now!
00692         
00693         // Ok, the theory is that if this is set to true then we must do a repaint
00694         // At the moment only it's ignored
00695         bool repaint;
00696 
00697         SDL_Event event;
00698         while (isRunning) {
00699                 inBetweenFrame = true;  // Will get set false if it's not an inBetweenFrame
00700 
00701                 if (!frameLimit) {
00702                         repaint = false;
00703                         
00704                         if (kernel->runProcesses()) repaint = true;
00705                         desktopGump->Run(kernel->getFrameNum());
00706                         inBetweenFrame = false;
00707                         next_ticks = animationRate + SDL_GetTicks()*3;
00708                         lerpFactor = 256;
00709                 }
00710                 else 
00711                 {
00712                         sint32 ticks = SDL_GetTicks()*3;
00713                         sint32 diff = next_ticks - ticks;
00714                         repaint = false;
00715 
00716                         while (diff < 0) {
00717                                 next_ticks += animationRate;
00718                                 if (kernel->runProcesses()) repaint = true;
00719                                 desktopGump->Run(kernel->getFrameNum());
00720 #if 0
00721                                 perr << "--------------------------------------" << std::endl;
00722                                 perr << "NEW FRAME" << std::endl;
00723                                 perr << "--------------------------------------" << std::endl;
00724 #endif
00725                                 inBetweenFrame = false;
00726 
00727                                 ticks = SDL_GetTicks()*3;
00728 
00729                                 // If frame skipping is off, we will only recalc next
00730                                 // ticks IF the frames are taking up 'way' too much time. 
00731                                 if (!frameSkip && diff <= -animationRate*2) next_ticks = animationRate + ticks;
00732 
00733                                 diff = next_ticks - ticks;
00734                                 if (!frameSkip) break;
00735                         }
00736 
00737                         // Calculate the lerp_factor
00738                         lerpFactor = ((animationRate-diff)*256)/animationRate;
00739                         //pout << "lerpFactor: " << lerpFactor << " framenum: " << framenum << std::endl;
00740                         if (!interpolate || kernel->isPaused() || lerpFactor > 256)
00741                                 lerpFactor = 256;
00742                 }
00743 
00744 
00745                 repaint = true;
00746 
00747                 // get & handle all events in queue
00748                 while (isRunning && SDL_PollEvent(&event)) {
00749                         handleEvent(event);
00750                 }
00751                 handleDelayedEvents();
00752                 hidmanager->handleDelayedEvents();
00753 
00754                 // Paint Screen
00755                 paint();
00756 
00757                 if (!change_gamename.empty()) {
00758                         pout << "Changing Game to: " << change_gamename << std::endl;
00759 
00760                         GameInfo* info = getGameInfo(change_gamename);
00761 
00762                         if (info) {
00763                                 shutdownGame();
00764 
00765                                 change_gamename.clear();
00766 
00767                                 if (setupGame(info))
00768                                         startupGame();
00769                                 else
00770                                         startupPentagramMenu();
00771                         }
00772                         else {
00773                                 perr << "Game '" << change_gamename << "' not found" << std::endl;
00774                                 change_gamename.clear();
00775                         }
00776                 }
00777 
00778                 // Do a delay
00779                 SDL_Delay(5);
00780         }
00781 }
00782 
00783 
00784 // conAutoPaint hackery
00785 void GUIApp::conAutoPaint(void)
00786 {
00787         GUIApp *app = GUIApp::get_instance();
00788         if (app && !app->isPainting()) app->paint();
00789 }
00790 
00791 #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
00792 
00793 WNDPROC oldWindowProc = 0;
00794 bool allow_set_cursor = true;
00795 
00796 LRESULT CALLBACK GUIApp::myWindowProc(
00797   HWND hwnd,      // handle to window
00798   UINT uMsg,      // message identifier
00799   WPARAM wParam,  // first message parameter
00800   LPARAM lParam   // second message parameter
00801   )
00802 {
00803         if (uMsg == WM_SETCURSOR) {
00804                 if ( allow_set_cursor = (LOWORD(lParam) == HTCLIENT) ) {
00805                         GUIApp *app = GUIApp::get_instance();
00806                         GameData *gamedata = app->gamedata;
00807 
00808                         if (gamedata) {
00809                                 Shape* mouse = gamedata->getMouse();
00810                                 if (mouse) {
00811                                         int frame = app->getMouseFrame();
00812                                         if (frame >= 0)
00813                                                 SetCursor(app->hwcursors[frame].hCursor);
00814                                 }
00815                         }
00816                         return TRUE;
00817                 }
00818         }
00819 
00820         return CallWindowProc(oldWindowProc, hwnd, uMsg, wParam, lParam);
00821 }
00822 
00823 void GUIApp::CreateHWCursors()
00824 {
00825         Shape* mouse = gamedata->getMouse();
00826         hwcursors = new HWMouseCursor[mouse->frameCount()];
00827         std::memset (hwcursors, 0, sizeof(HWMouseCursor) * mouse->frameCount());
00828 
00829         for (uint32 frame = 0; frame < mouse->frameCount(); frame++)
00830         {
00831                 ShapeFrame *f = mouse->getFrame(frame);
00832                 uint32 bpp = BaseSoftRenderSurface::format.s_bpp;
00833                 int buf_width = f->width;
00834                 int buf_height = f->height;
00835 
00836                 // DIB must be dword aligned
00837                 if (bpp != 32) buf_width = (buf_width+1)&~1;    
00838 
00839                 uint8 *buf = new uint8 [bpp/8 * buf_width * buf_height];
00840 
00841                 RenderSurface *surf;
00842 
00843                 if (bpp == 32)
00844                         surf = new SoftRenderSurface<uint32>(buf_width, buf_height, buf);
00845                 else
00846                         surf = new SoftRenderSurface<uint16>(buf_width, buf_height, buf);
00847 
00848                 surf->BeginPainting();
00849                 surf->Fill32(0x00FF00FF, 0, 0, buf_width, buf_height);
00850                 surf->Paint(mouse, frame, f->xoff, f->yoff);
00851                 surf->EndPainting();
00852 
00853                 int clear_col = PACK_RGB8(0xFF,0x00,0xFF);
00854 
00855                 //
00856                 // Mask
00857                 //
00858 
00859                 // 1 bit bitmap must be word aligned 
00860                 uint32 bit_width = (buf_width+15)&~15;
00861                 uint8 *buf_mask = new uint8 [bit_width/8 * buf_height*2];
00862 
00863                 // Clear it
00864                 std::memset(buf_mask, 0x00, bit_width/8 * buf_height * 2);
00865 
00866 
00867                 if (bpp == 32)
00868                 {
00869                         uint32 *buf32 = (uint32*)buf;
00870                         for (int y = 0; y < buf_height; y++)
00871                         {
00872                                 for (int x = 0; x < buf_width; x++)
00873                                 {
00874                                         bool black = (x & 1) == (y & 1);
00875                                         uint32 bit = y * bit_width + x;
00876                                         uint32 byte = bit/8;
00877                                         bit = 7-(bit % 8);
00878 
00879                                         // If background is clear colour, mask it out
00880                                         if (buf32[buf_width*y + x] == clear_col)
00881                                         {
00882                                                 buf32[buf_width*y + x] = 0;
00883                                                 buf_mask[byte] |=   1<< bit;
00884                                         }
00885                                         // Make any non black make white
00886                                         else if (buf32[buf_width*y + x])
00887                                                 buf_mask[byte+((buf_height*bit_width)/8)] |= 1<<bit;
00888                                 }
00889                         }
00890                 }
00891                 else
00892                 {
00893                         uint16 *buf16 = (uint16*)buf;
00894                         for (int y = 0; y < buf_height; y++)
00895                         {
00896                                 for (int x = 0; x < buf_width; x++)
00897                                 {
00898                                         bool black = (x & 1) == (y & 1);
00899                                         uint32 bit = y * bit_width + x;
00900                                         uint32 byte = bit/8;
00901                                         bit = 7-(bit % 8);
00902 
00903                                         // If background is clear colour, mask it out
00904                                         if (buf16[buf_width*y + x] == clear_col)
00905                                         {
00906                                                 buf16[buf_width*y + x] = 0;
00907                                                 buf_mask[byte] |=   1<< bit;
00908                                         }
00909                                         // Make any non black make white
00910                                         else if (buf16[buf_width*y + x])
00911                                                 buf_mask[byte+((buf_height*bit_width)/8)] |= 1<<bit;
00912                                 }
00913                         }
00914                 }
00915 
00916                 // Create an icon for our cursor
00917                 ICONINFO iconinfo;
00918                 iconinfo.fIcon = FALSE;
00919                 iconinfo.xHotspot = f->xoff;
00920                 iconinfo.yHotspot = f->yoff;
00921                 iconinfo.hbmMask = CreateBitmap(buf_width, buf_height, 1, 1, buf_mask);
00922                 iconinfo.hbmColor = CreateBitmap(buf_width, buf_height, 1, bpp, buf);
00923 
00924                 hwcursors[frame].hCursor = CreateIconIndirect (&iconinfo);
00925 
00926                 DeleteObject(iconinfo.hbmMask);
00927                 DeleteObject(iconinfo.hbmColor);
00928 
00929                 delete [] buf;
00930                 delete [] buf_mask;
00931                 delete surf;
00932         }
00933 
00934         // Lets screw with the window class
00935         SDL_SysWMinfo info;
00936         info.version.major = SDL_MAJOR_VERSION;
00937         info.version.minor = SDL_MINOR_VERSION;
00938         info.version.patch = SDL_PATCHLEVEL;
00939         SDL_GetWMInfo(&info);
00940         oldWindowProc = (WNDPROC) GetWindowLongPtr(info.window, GWLP_WNDPROC);
00941         SetWindowLongPtr(info.window, GWLP_WNDPROC, (LONG) myWindowProc);
00942         
00943 }
00944 #endif
00945 
00946 // Paint the screen
00947 void GUIApp::paint()
00948 {
00949         if(!screen) // need to worry if the graphics system has been started. Need nicer way.
00950                 return;
00951 
00952         painting = true;
00953 
00954         // Begin painting
00955         screen->BeginPainting();
00956 
00957         // We need to get the dims
00958         Pentagram::Rect dims;
00959         screen->GetSurfaceDims(dims);
00960 
00961         long before_gumps = SDL_GetTicks();
00962         desktopGump->Paint(screen, lerpFactor, false);
00963         long after_gumps = SDL_GetTicks();
00964 
00965         // Mouse
00966         if (gamedata) {
00967                 Shape* mouse = gamedata->getMouse();
00968                 if (mouse) {
00969                         int frame = getMouseFrame();
00970                         if (frame >= 0)
00971                         {
00972 #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
00973                                 if (allow_set_cursor) SetCursor(hwcursors[frame].hCursor);
00974 #else
00975                                 screen->Paint(mouse, frame, mouseX, mouseY, true);
00976 #endif
00977                         }
00978                 }
00979         }
00980         else {
00981                 if (getMouseFrame() != -1) 
00982                         screen->Blit(defMouse, 0, 0, defMouse->width, defMouse->height, mouseX, mouseY);
00983         }
00984 
00985         static long prev = 0;
00986         long now = SDL_GetTicks();
00987         long diff = now - prev;
00988         if (diff == 0) diff = 1;
00989         prev = now;
00990 
00991         char buf[256];
00992         FixedWidthFont *confont = con.GetConFont();
00993         int v_offset = 0;
00994         int char_w = confont->width;
00995 
00996         if (drawRenderStats)
00997         {
00998                 snprintf(buf, 255, "Rendering time %li ms %li FPS ", diff, 1000/diff);
00999                 screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
01000                 v_offset += confont->height;
01001 
01002                 snprintf(buf, 255, "Paint Gumps %li ms ", after_gumps-before_gumps);
01003                 screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
01004                 v_offset += confont->height;
01005 
01006                 snprintf(buf, 255, "t %02d:%02d gh %i ", I_getTimeInMinutes(0,0), I_getTimeInSeconds(0,0)%60, I_getTimeInGameHours(0,0));
01007                 screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
01008                 v_offset += confont->height;
01009         }
01010 
01011         // End painting
01012         screen->EndPainting();
01013 
01014         painting = false;
01015 }
01016 
01017 bool GUIApp::isMouseDown(MouseButton button)
01018 {
01019         return (mouseButton[button].state & MBS_DOWN);
01020 }
01021 
01022 int GUIApp::getMouseLength(int mx, int my)
01023 {
01024         Pentagram::Rect dims;
01025         screen->GetSurfaceDims(dims);
01026         // For now, reference point is (near) the center of the screen
01027         int dx = mx - dims.w/2;
01028         int dy = (dims.h/2+14) - my; 
01029 
01030         int shortsq = (dims.w / 8);
01031         if (dims.h / 6 < shortsq)
01032                 shortsq = (dims.h / 6);
01033         shortsq = shortsq*shortsq;
01034         
01035         int mediumsq = ((dims.w * 4) / 10);
01036         if (((dims.h * 4) / 10) < mediumsq)
01037                 mediumsq = ((dims.h * 4) / 10);
01038         mediumsq = mediumsq * mediumsq;
01039         
01040         int dsq = dx*dx+dy*dy;
01041         
01042         // determine length of arrow
01043         if (dsq <= shortsq) {
01044                 return 0;
01045         } else if (dsq <= mediumsq) {
01046                 return 1;
01047         } else {
01048                 return 2;
01049         }
01050 }
01051 
01052 int GUIApp::getMouseDirection(int mx, int my)
01053 {
01054         Pentagram::Rect dims;
01055         screen->GetSurfaceDims(dims);
01056         // For now, reference point is (near) the center of the screen
01057         int dx = mx - dims.w/2;
01058         int dy = (dims.h/2+14) - my; 
01059 
01060         return ((Get_direction(dy*2, dx))+1)%8;
01061 }
01062 
01063 int GUIApp::getMouseFrame()
01064 {
01065         // Ultima 8 mouse cursors:
01066 
01067         // 0-7 = short (0 = up, 1 = up-right, 2 = right, ...)
01068         // 8-15 = medium
01069         // 16-23 = long
01070         // 24 = blue dot
01071         // 25-32 = combat
01072         // 33 = red dot
01073         // 34 = target
01074         // 35 = pentagram
01075         // 36 = skeletal hand
01076         // 38 = quill
01077         // 39 = magnifying glass
01078         // 40 = red cross
01079 
01080         MouseCursor cursor = cursors.top();
01081 
01082         if (flashingcursor > 0) {
01083                 if (SDL_GetTicks() < flashingcursor + 250)
01084                         cursor = MOUSE_CROSS;
01085                 else
01086                         flashingcursor = 0;
01087         }
01088 
01089 
01090         switch (cursor) {
01091         case MOUSE_NORMAL:
01092         {
01093                 bool combat = false;
01094                 MainActor* av = getMainActor();
01095                 if (av) { combat = av->isInCombat(); }
01096 
01097                 // Calculate frame based on direction
01098                 int frame = getMouseDirection(mouseX, mouseY);
01099 
01106                 int offset = getMouseLength(mouseX, mouseY) * 8;
01107                 if (combat && offset != 16) //combat mouse is off if running
01108                         offset = 25;
01109                 return frame + offset;
01110         }
01112         case MOUSE_NONE: return -1;
01113         case MOUSE_TARGET: return 34;
01114         case MOUSE_PENTAGRAM: return 35;
01115         case MOUSE_HAND: return 36;
01116         case MOUSE_QUILL: return 38;
01117         case MOUSE_MAGGLASS: return 39;
01118         case MOUSE_CROSS: return 40;
01119         default: return -1;
01120         }
01121 
01122 }
01123 
01124 void GUIApp::setMouseCoords(int mx, int my)
01125 {
01126         Pentagram::Rect dims;
01127         screen->GetSurfaceDims(dims);
01128 
01129         if (mx < dims.x)
01130                 mx = dims.x;
01131         else if (mx > dims.w)
01132                 mx = dims.w;
01133 
01134         if (my < dims.y)
01135                 my = dims.y;
01136         else if (my > dims.h)
01137                 my = dims.h;
01138 
01139         mouseX = mx; mouseY = my;
01140         Gump * gump = desktopGump->OnMouseMotion(mx, my);
01141         if (gump && mouseOverGump != gump->getObjId())
01142         {
01143                 Gump * oldGump = getGump(mouseOverGump);
01144                 std::list<Gump*> oldgumplist;
01145                 std::list<Gump*> newgumplist;
01146 
01147                 // create lists of parents of old and new 'mouseover' gumps
01148                 if (oldGump) {
01149                         while (oldGump) {
01150                                 oldgumplist.push_front(oldGump);
01151                                 oldGump = oldGump->GetParent();
01152                         }
01153                 }
01154                 Gump* newGump = gump;
01155                 while (newGump) {
01156                         newgumplist.push_front(newGump);
01157                         newGump = newGump->GetParent();
01158                 }
01159 
01160                 std::list<Gump*>::iterator olditer = oldgumplist.begin();
01161                 std::list<Gump*>::iterator newiter = newgumplist.begin();
01162 
01163                 // strip common prefix from lists
01164                 while (olditer != oldgumplist.end() &&
01165                            newiter != newgumplist.end() &&
01166                            *olditer == *newiter)
01167                 {
01168                         ++olditer; ++newiter;
01169                 }
01170 
01171                 // send events to remaining gumps
01172                 for (; olditer != oldgumplist.end(); ++olditer)
01173                         (*olditer)->OnMouseLeft();
01174 
01175                 mouseOverGump = gump->getObjId();
01176 
01177                 for (; newiter != newgumplist.end(); ++newiter)
01178                         (*newiter)->OnMouseOver();
01179         }
01180 
01181         if (dragging == DRAG_NOT) {
01182                 if (mouseButton[BUTTON_LEFT].state & MBS_DOWN) {
01183                         int startx = mouseButton[BUTTON_LEFT].downX;
01184                         int starty = mouseButton[BUTTON_LEFT].downY;
01185                         if (abs(startx - mx) > 2 ||
01186                                 abs(starty - my) > 2)
01187                         {
01188                                 startDragging(startx, starty);
01189                         }
01190                 }
01191         }
01192 
01193         if (dragging == DRAG_OK || dragging == DRAG_TEMPFAIL) {
01194                 moveDragging(mx, my);
01195         }
01196 }
01197 
01198 void GUIApp::setMouseCursor(MouseCursor cursor)
01199 {
01200         cursors.pop();
01201         cursors.push(cursor);
01202 }
01203 
01204 void GUIApp::flashCrossCursor()
01205 {
01206         flashingcursor = SDL_GetTicks();
01207 }
01208 
01209 void GUIApp::pushMouseCursor()
01210 {
01211         cursors.push(MOUSE_NORMAL);
01212 }
01213 
01214 void GUIApp::popMouseCursor()
01215 {
01216         cursors.pop();
01217 }
01218 
01219 void GUIApp::GraphicSysInit()
01220 {
01221         settingman->setDefault("fullscreen", false);
01222         settingman->setDefault("width", 640);
01223         settingman->setDefault("height", 480);
01224         settingman->setDefault("bpp", 32);
01225 
01226         bool new_fullscreen;
01227         int width, height, bpp;
01228         settingman->get("fullscreen", new_fullscreen);
01229         settingman->get("width", width);
01230         settingman->get("height", height);
01231         settingman->get("bpp", bpp);
01232 
01233 #ifdef UNDER_CE
01234         width = 240;
01235         height = 320;
01236 #endif
01237 
01238 #if 0
01239         // store values in user's config file
01240         settingman->set("width", width);
01241         settingman->set("height", height);
01242         settingman->set("bpp", bpp);
01243         settingman->set("fullscreen", new_fullscreen);
01244 #endif
01245 
01246         if (screen) {
01247                 Pentagram::Rect old_dims;
01248                 screen->GetSurfaceDims(old_dims);
01249                 if (new_fullscreen == fullscreen && width == old_dims.w && height == old_dims.h) return;
01250                 bpp = RenderSurface::format.s_bpp;
01251 
01252                 delete screen;
01253         }
01254         screen = 0;
01255 
01256         fullscreen = new_fullscreen;
01257 
01258         // Set Screen Resolution
01259         con.Printf(MM_INFO, "Setting Video Mode %ix%ix%i %s...\n", width, height, bpp, fullscreen?"fullscreen":"windowed");
01260 
01261         RenderSurface *new_screen = RenderSurface::SetVideoMode(width, height, bpp, fullscreen, false);
01262 
01263         if (!new_screen)
01264         {
01265                 perr << "Unable to set new video mode. Trying 640x480x32 windowed" << std::endl;
01266                 new_screen = RenderSurface::SetVideoMode(640, 480, 32, fullscreen=false, false);
01267         }
01268 
01269         if (!new_screen)
01270         {
01271                 perr << "Unable to set video mode. Exiting." << std::endl;
01272                 std::exit(-1);
01273         }
01274 
01275         if (desktopGump) {
01276                 palettemanager->RenderSurfaceChanged(new_screen);
01277                 static_cast<DesktopGump*>(desktopGump)->RenderSurfaceChanged(new_screen);
01278                 screen = new_screen;
01279                 paint();
01280                 return;
01281         }
01282 
01283         // set window title
01284         SDL_WM_SetCaption("Pentagram", "");
01285 
01286         // setup normal mouse cursor
01287         con.Print(MM_INFO, "Loading Default Mouse Cursor...\n");
01288         IDataSource *dm = filesystem->ReadFile("@data/mouse.tga");
01289         if (dm) defMouse = Texture::Create(dm, "@data/mouse.tga");
01290         else defMouse = 0;
01291         if (!defMouse)
01292         {
01293                 perr << "Unable to load '@data/mouse.tga'" << ". Exiting" << std::endl;
01294                 std::exit(-1);
01295         }
01296         delete dm;
01297         pushMouseCursor();
01298 
01299         std::string alt_confont;
01300         bool confont_loaded = false;
01301 
01302         if (settingman->get("console_font", alt_confont)) {
01303                 con.Print(MM_INFO, "Alternate console font found...\n");
01304                 confont_loaded = LoadConsoleFont(alt_confont);
01305     }
01306 
01307         if (!confont_loaded) {
01308                 con.Print(MM_INFO, "Loading default console font...\n");
01309                 if (!LoadConsoleFont("@data/fixedfont.ini")) {
01310                         perr << "Failed to load console font. Exiting" << std::endl;
01311                         std::exit(-1);
01312                 }
01313         }
01314 
01315         desktopGump = new DesktopGump(0,0, width, height);
01316         desktopGump->InitGump(0);
01317         desktopGump->MakeFocus();
01318 
01319         consoleGump = new ConsoleGump(0, 0, width, height);
01320         consoleGump->InitGump(0);
01321 
01322         screen = new_screen;
01323 
01324         bool ttf_antialiasing = true;
01325         settingman->setDefault("ttf_antialiasing", true);
01326         settingman->get("ttf_antialiasing", ttf_antialiasing);
01327 
01328         fontmanager = new FontManager(ttf_antialiasing);
01329         palettemanager = new PaletteManager(new_screen);
01330 
01331         // TODO: assign names to these fontnumbers somehow
01332         fontmanager->loadTTFont(0, "Vera.ttf", 18, 0xFFFFFF, 0);
01333         fontmanager->loadTTFont(1, "VeraBd.ttf", 12, 0xFFFFFF, 0);
01334         // GameWidget's version number information:
01335         fontmanager->loadTTFont(2, "Vera.ttf", 8, 0xA0A0A0, 0);
01336 
01337         paint();
01338 }
01339 
01340 void GUIApp::changeVideoMode(int width, int height, int new_fullscreen)
01341 {
01342         if (new_fullscreen == -2) settingman->set("fullscreen", !fullscreen);
01343         else if (new_fullscreen == 0) settingman->set("fullscreen", false);
01344         else if (new_fullscreen == 1) settingman->set("fullscreen", true);
01345 
01346         if (width > 0) settingman->set("width", width);
01347         if (height > 0) settingman->set("height", height);
01348 
01349         GraphicSysInit();
01350 }
01351 
01352 bool GUIApp::LoadConsoleFont(std::string confontini)
01353 {
01354         // try to load the file
01355         con.Printf(MM_INFO, "Loading console font config: %s... ", confontini.c_str());
01356         if(configfileman->readConfigFile(confontini, "confont", true))
01357                 pout << "Ok" << std::endl;
01358         else {
01359                 pout << "Failed" << std::endl;
01360                 return false;
01361         }
01362 
01363         FixedWidthFont *confont = FixedWidthFont::Create("confont");
01364 
01365         if (!confont) {
01366                 perr << "Failed to load Console Font." << std::endl;
01367                 return false;
01368         }
01369 
01370         con.SetConFont(confont);
01371 
01372         return true;
01373 }
01374 
01375 void GUIApp::enterTextMode(Gump *gump)
01376 {
01377         if (!textmodes.empty()) {
01378                 textmodes.remove(gump->getObjId());
01379         } else {
01380                 SDL_EnableUNICODE(1);
01381                 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
01382                                                         SDL_DEFAULT_REPEAT_INTERVAL);
01383         }
01384         textmodes.push_front(gump->getObjId());
01385 }
01386 
01387 void GUIApp::leaveTextMode(Gump *gump)
01388 {
01389         if (textmodes.empty()) return;
01390         textmodes.remove(gump->getObjId());
01391         if (textmodes.empty()) {
01392                 SDL_EnableUNICODE(0);
01393                 SDL_EnableKeyRepeat(0, 0);
01394         }
01395 }
01396 
01397 void GUIApp::handleEvent(const SDL_Event& event)
01398 {
01399         uint32 now = SDL_GetTicks();
01400         bool handled = false;
01401 
01402         // Text mode input. A few hacks here
01403         if (!textmodes.empty()) {
01404                 Gump *gump = 0;
01405 
01406                 while (!textmodes.empty())
01407                 {
01408                         gump = p_dynamic_cast<Gump*>(objectmanager->getObject(textmodes.front()));
01409                         if (gump) break;
01410 
01411                         textmodes.pop_front();
01412                 }
01413 
01414                 if (gump) {
01415                         switch (event.type) {
01416                                 case SDL_KEYDOWN:
01417                                         // Break if console Key
01418                                         // FIXME: make console key configurable
01419                                         if (event.key.keysym.sym == SDLK_BACKQUOTE ||
01420                                                 event.key.keysym.sym == SDLK_F5)
01421                                                 break;
01422 
01423 #ifdef WIN32 
01424                                         // Paste from Clip-Board on Ctrl-V - Note this should be a flag of some sort
01425                                         if (event.key.keysym.sym == SDLK_v && event.key.keysym.mod & KMOD_CTRL)
01426                                         {
01427                                                 if (!IsClipboardFormatAvailable(CF_TEXT)) 
01428                                                         return ; 
01429                                                 if (!OpenClipboard(NULL)) 
01430                                                         return; 
01431 
01432                                                 HGLOBAL hglb = GetClipboardData(CF_TEXT); 
01433                                                 if (hglb != NULL) 
01434                                                 { 
01435                                                         LPTSTR lptstr = reinterpret_cast<LPTSTR>(GlobalLock(hglb)); 
01436                                                         if (lptstr != NULL) 
01437                                                         { 
01438                                                                 // Only read the first line of text
01439                                                                 while (*lptstr >= ' ') gump->OnTextInput(*lptstr++);
01440 
01441                                                                 GlobalUnlock(hglb); 
01442                                                         } 
01443                                                 } 
01444                                                 CloseClipboard(); 
01445                                                 return;
01446                                         }
01447 #endif
01448 
01449                                         if (event.key.keysym.unicode >= ' ' &&
01450                                                 event.key.keysym.unicode <= 255 &&
01451                                                 !(event.key.keysym.unicode >= 0x7F && // control chars
01452                                                   event.key.keysym.unicode <= 0x9F))
01453                                         {
01454                                                 gump->OnTextInput(event.key.keysym.unicode);
01455                                         }
01456 
01457                                         gump->OnKeyDown(event.key.keysym.sym, event.key.keysym.mod);
01458                                         return;
01459 
01460                                 case SDL_KEYUP:
01461                                         // Break if console Key
01462                                         // FIXME: make this configurable
01463                                         if (event.key.keysym.sym == SDLK_BACKQUOTE ||
01464                                                 event.key.keysym.sym == SDLK_F5)
01465                                                 break;
01466 //                                      if (event.key.keysym.sym == SDLK_BACKQUOTE || 
01467 //                                              hidmanager->isToggleConsole(event)) break;
01468                                         gump->OnKeyUp(event.key.keysym.sym);
01469                                         return;
01470 
01471                                 default: break;
01472                         }
01473                 }
01474         }
01475         
01476         // Old style input begins here
01477         switch (event.type) {
01478 
01480 
01481         case SDL_QUIT:
01482         {
01483                 isRunning = false;
01484         }
01485         break;
01486 
01487         case SDL_ACTIVEEVENT:
01488         {
01489                 // pause when lost focus?
01490         }
01491         break;
01492 
01493 
01494         // most of these events will probably be passed to a gump manager,
01495         // since almost all (all?) user input will be handled by a gump
01496 
01497         case SDL_MOUSEBUTTONDOWN:
01498         {
01499                 int button = event.button.button;
01500                 int mx = event.button.x;
01501                 int my = event.button.y;
01502 
01503                 if (button >= MOUSE_LAST)
01504                         break;
01505 
01506                 Gump *mousedowngump = desktopGump->OnMouseDown(button, mx, my);
01507                 if (mousedowngump)
01508                 {
01509                         mouseButton[button].downGump = mousedowngump->getObjId();
01510                         handled = true;
01511                 }
01512                 else
01513                         mouseButton[button].downGump = 0;
01514 
01515                 mouseButton[button].curDown = now;
01516                 mouseButton[button].downX = mx;
01517                 mouseButton[button].downY = my;
01518                 mouseButton[button].state |= MBS_DOWN;
01519                 mouseButton[button].state &= ~MBS_HANDLED;
01520 
01521                 if (now - mouseButton[button].lastDown < DOUBLE_CLICK_TIMEOUT) {
01522                         if (dragging == DRAG_NOT) {
01523                                 Gump* gump = getGump(mouseButton[button].downGump);
01524                                 if (gump)
01525                                 {
01526                                         int mx2 = mx, my2 = my;
01527                                         Gump *parent = gump->GetParent();
01528                                         if (parent) parent->ScreenSpaceToGump(mx2,my2);
01529                                         gump->OnMouseDouble(button, mx2, my2);
01530                                 }
01531                                 mouseButton[button].state |= MBS_HANDLED;
01532                                 mouseButton[button].lastDown = 0;
01533                         }
01534                 }
01535                 mouseButton[button].lastDown = now;
01536         }
01537         break;
01538 
01539         case SDL_MOUSEBUTTONUP:
01540         {
01541                 int button = event.button.button;
01542                 int mx = event.button.x;
01543                 int my = event.button.y;
01544 
01545                 if (button >= MOUSE_LAST)
01546                         break;
01547 
01548                 mouseButton[button].state &= ~MBS_DOWN;
01549 
01550                 // Need to store the last down position of the mouse
01551                 // when the button is released.
01552                 mouseButton[button].downX = mx;
01553                 mouseButton[button].downY = my;
01554 
01555                 // Always send mouse up to the gump
01556                 Gump* gump = getGump(mouseButton[button].downGump);
01557                 if (gump)
01558                 {
01559                         int mx2 = mx, my2 = my;
01560                         Gump *parent = gump->GetParent();
01561                         if (parent)
01562                                 parent->ScreenSpaceToGump(mx2,my2);
01563                         gump->OnMouseUp(button, mx2, my2);
01564                         handled = true;
01565                 }
01566 
01567                 if (button == BUTTON_LEFT && dragging != DRAG_NOT) {
01568                         stopDragging(mx, my);
01569                         handled = true;
01570                         break;
01571                 }
01572         }
01573         break;
01574 
01575         case SDL_MOUSEMOTION:
01576         {
01577                 int mx = event.button.x;
01578                 int my = event.button.y;
01579                 setMouseCoords(mx, my);
01580         }
01581         break;
01582 
01583         case SDL_KEYDOWN:
01584         {
01585                 if (dragging != DRAG_NOT) break;
01586 
01587                 /*
01588                 switch (event.key.keysym.sym) {
01589                         case SDLK_KP_PLUS: {
01590                                 midi_volume+=8;
01591                                 if (midi_volume>255) midi_volume =255;
01592                                 pout << "Midi Volume is now: " << midi_volume << std::endl; 
01593                                 if (midi_driver) midi_driver->setGlobalVolume(midi_volume);
01594                         } break;
01595                         case SDLK_KP_MINUS: {
01596                                 midi_volume-=8;
01597                                 if (midi_volume<0) midi_volume = 0;
01598                                 pout << "Midi Volume is now: " << midi_volume << std::endl; 
01599                                 if (midi_driver) midi_driver->setGlobalVolume(midi_volume);
01600                         } break;
01601                         default:
01602                                 break;
01603                 }
01604                 */
01605         }
01606         break;
01607 
01608         case SDL_KEYUP:
01609         {
01610                 if (dragging != DRAG_NOT) break;
01611 
01612                 switch (event.key.keysym.sym) {
01613                 case SDLK_q: // Quick quit
01614                         if (event.key.keysym.mod & KMOD_CTRL)
01615                                 ForceQuit();
01616                         break;
01617                 case SDLK_LEFTBRACKET: gameMapGump->IncSortOrder(-1); break;
01618                 case SDLK_RIGHTBRACKET: gameMapGump->IncSortOrder(+1); break;
01619 
01620                 default: break;
01621                 }
01622         }
01623         break;
01624 
01625         // any more useful events?
01626 
01627         default:
01628                 break;
01629         }
01630 
01631         if (dragging == DRAG_NOT && ! handled) {
01632                 if (hidmanager->handleEvent(event))
01633                         return;
01634         }
01635 
01636 }
01637 
01638 void GUIApp::handleDelayedEvents()
01639 {
01640         uint32 now = SDL_GetTicks();
01641         for (int button = 0; button < MOUSE_LAST; ++button) {
01642                 if (!(mouseButton[button].state & (MBS_HANDLED | MBS_DOWN)) &&
01643                         now - mouseButton[button].lastDown > DOUBLE_CLICK_TIMEOUT)
01644                 {
01645                         Gump* gump = getGump(mouseButton[button].downGump);
01646                         if (gump)
01647                         {
01648                                 int mx = mouseButton[button].downX;
01649                                 int my = mouseButton[button].downY;
01650                                 Gump *parent = gump->GetParent();
01651                                 if (parent) parent->ScreenSpaceToGump(mx,my);
01652                                 gump->OnMouseClick(button, mx, my);
01653                         }
01654 
01655                         mouseButton[button].downGump = 0;
01656                         mouseButton[button].state |= MBS_HANDLED;
01657                 }
01658         }
01659 
01660 }
01661 
01662 void GUIApp::startDragging(int startx, int starty)
01663 {
01664         setDraggingOffset(0,0); // initialize
01665 
01666         dragging_objid = desktopGump->TraceObjId(startx, starty);
01667         
01668         Gump *gump = getGump(dragging_objid);
01669         Item *item = getItem(dragging_objid);
01670         
01671         // for a Gump, notify the Gump's parent that we started
01672         // dragging:
01673         if (gump) {
01674                 Gump *parent = gump->GetParent();
01675                 assert(parent); // can't drag root gump
01676                 int px = startx, py = starty;
01677                 parent->ScreenSpaceToGump(px, py);
01678                 if (gump->IsDraggable() && parent->StartDraggingChild(gump, px, py))
01679                         dragging = DRAG_OK;
01680                 else {
01681                         dragging_objid = 0;
01682                         return;
01683                 }
01684         } else
01685         // for an Item, notify the gump the item is in that we started dragging
01686         if (item) {
01687                 // find gump item was in
01688                 gump = desktopGump->FindGump(startx, starty);
01689                 int gx = startx, gy = starty;
01690                 gump->ScreenSpaceToGump(gx, gy);
01691                 bool ok = !isAvatarInStasis() &&
01692                         gump->StartDraggingItem(item,gx,gy);
01693                 if (!ok) {
01694                         dragging = DRAG_INVALID;
01695                 } else {
01696                         dragging = DRAG_OK;
01697                         
01698                         // this is the gump that'll get StopDraggingItem
01699                         dragging_item_startgump = gump->getObjId();
01700                         
01701                         // this is the gump the item is currently over
01702                         dragging_item_lastgump = gump->getObjId();
01703                 }
01704         } else {
01705                 dragging = DRAG_INVALID;
01706         }
01707 
01708 #if 0
01709         Object* obj = ObjectManager::get_instance()->getObject(dragging_objid);
01710         perr << "Dragging object " << dragging_objid << " (class=" << (obj ? obj->GetClassType().class_name : "NULL") << ")" << std::endl;
01711 #endif
01712 
01713         pushMouseCursor();
01714         setMouseCursor(MOUSE_NORMAL);
01715         
01716         // pause the kernel
01717         kernel->pause();
01718         
01719         mouseButton[BUTTON_LEFT].state |= MBS_HANDLED;
01720 
01721         if (dragging == DRAG_INVALID) {
01722                 setMouseCursor(MOUSE_CROSS);
01723         }
01724 }
01725 
01726 void GUIApp::moveDragging(int mx, int my)
01727 {
01728         Gump* gump = getGump(dragging_objid);
01729         Item *item = getItem(dragging_objid);
01730 
01731         setMouseCursor(MOUSE_NORMAL);
01732         
01733         // for a gump, notify Gump's parent that it was dragged
01734         if (gump) {
01735                 Gump *parent = gump->GetParent();
01736                 assert(parent); // can't drag root gump
01737                 int px = mx, py = my;
01738                 parent->ScreenSpaceToGump(px, py);
01739                 parent->DraggingChild(gump, px, py);
01740         } else
01741         // for an item, notify the gump it's on
01742         if (item) {
01743                 gump = desktopGump->FindGump(mx, my);
01744                 assert(gump);
01745                         
01746                 if (gump->getObjId() != dragging_item_lastgump) {
01747                         // item switched gump, so notify previous gump item left
01748                         Gump *last = getGump(dragging_item_lastgump);
01749                         if (last) last->DraggingItemLeftGump(item);
01750                 }
01751                 dragging_item_lastgump = gump->getObjId();
01752                 int gx = mx, gy = my;
01753                 gump->ScreenSpaceToGump(gx, gy);
01754                 bool ok = gump->DraggingItem(item,gx,gy);
01755                 if (!ok) {
01756                         dragging = DRAG_TEMPFAIL;
01757                 } else {
01758                         dragging = DRAG_OK;
01759                 }
01760         } else {
01761                 CANT_HAPPEN();
01762         }
01763 
01764         if (dragging == DRAG_TEMPFAIL) {
01765                 setMouseCursor(MOUSE_CROSS);
01766         }
01767 }
01768 
01769 
01770 void GUIApp::stopDragging(int mx, int my)
01771 {
01772 //      perr << "Dropping object " << dragging_objid << std::endl;
01773         
01774         Gump *gump = getGump(dragging_objid);
01775         Item *item = getItem(dragging_objid);
01776         // for a Gump: notify parent
01777         if (gump) {
01778                 Gump *parent = gump->GetParent();
01779                 assert(parent); // can't drag root gump
01780                 parent->StopDraggingChild(gump);
01781         } else 
01782         // for an item: notify gumps
01783         if (item) {
01784                 if (dragging != DRAG_INVALID) {
01785                         Gump *startgump = getGump(dragging_item_startgump);
01786                         assert(startgump); // can't have disappeared
01787                         bool moved = (dragging == DRAG_OK);
01788 
01789                         if (dragging != DRAG_OK) {
01790                                 Gump *last = getGump(dragging_item_lastgump);
01791                                 if (last && last != startgump)
01792                                         last->DraggingItemLeftGump(item);
01793                         }
01794 
01795                         startgump->StopDraggingItem(item, moved);
01796                 }
01797                 
01798                 if (dragging == DRAG_OK) {
01799                         item->movedByPlayer();
01800 
01801                         gump = desktopGump->FindGump(mx, my);
01802                         int gx = mx, gy = my;
01803                         gump->ScreenSpaceToGump(gx, gy);
01804                         gump->DropItem(item,gx,gy);
01805                 }
01806         } else {
01807                 assert(dragging == DRAG_INVALID);
01808         }
01809 
01810         dragging = DRAG_NOT;
01811 
01812         kernel->unpause();
01813 
01814         popMouseCursor();
01815 }
01816 
01817 void GUIApp::writeSaveInfo(ODataSource* ods)
01818 {
01819         time_t t = std::time(0);
01820         struct tm *timeinfo = localtime (&t);
01821         ods->write2(static_cast<uint16>(timeinfo->tm_year + 1900));
01822         ods->write1(static_cast<uint8>(timeinfo->tm_mon+1));
01823         ods->write1(static_cast<uint8>(timeinfo->tm_mday));
01824         ods->write1(static_cast<uint8>(timeinfo->tm_hour));
01825         ods->write1(static_cast<uint8>(timeinfo->tm_min));
01826         ods->write1(static_cast<uint8>(timeinfo->tm_sec));
01827         ods->write4(save_count);
01828         ods->write4(getGameTimeInSeconds());
01829 
01830         uint8 c = (has_cheated ? 1 : 0);
01831         ods->write1(c);
01832 
01833         // write game-specific info
01834         game->writeSaveInfo(ods);
01835 }
01836 
01837 bool GUIApp::saveGame(std::string filename, std::string desc,
01838                                           bool ignore_modals)
01839 {
01840         // Don't allow saving with Modals open
01841         if (!ignore_modals && desktopGump->FindGump<ModalGump>()) {
01842                 pout << "Can't save: modal gump open." << std::endl;
01843                 return false;
01844         }
01845 
01846         // Don't allow saving when avatar is dead.
01847         // (Avatar is flagged dead by usecode when you finish the game as well.)
01848         MainActor* av = getMainActor();
01849         if (!av || (av->getActorFlags() & Actor::ACT_DEAD)) {
01850                 pout << "Can't save: game over." << std::endl;
01851                 return false;
01852         }
01853 
01854         pout << "Saving..." << std::endl;
01855 
01856         pout << "Savegame file: " << filename << std::endl;
01857         pout << "Description: " << desc << std::endl;
01858 
01859         // Hack - don't save mouse over status for gumps
01860         Gump * gump = getGump(mouseOverGump);
01861         if (gump) gump->OnMouseLeft();
01862 
01863         ODataSource* ods = filesystem->WriteFile(filename);
01864         if (!ods) return false;
01865 
01866         save_count++;
01867 
01868         SavegameWriter* sgw = new SavegameWriter(ods);
01869         sgw->writeVersion(Pentagram::savegame_version);
01870         sgw->writeDescription(desc);
01871 
01872         // We'll make it 2KB initially
01873         OAutoBufferDataSource buf(2048);
01874 
01875         gameinfo->save(&buf);
01876         sgw->writeFile("GAME", &buf);
01877         buf.clear();
01878 
01879         writeSaveInfo(&buf);
01880         sgw->writeFile("INFO", &buf);
01881         buf.clear();
01882 
01883         kernel->save(&buf);
01884         sgw->writeFile("KERNEL", &buf);
01885         buf.clear();
01886 
01887         objectmanager->save(&buf);
01888         sgw->writeFile("OBJECTS", &buf);
01889         buf.clear();
01890 
01891         world->save(&buf);
01892         sgw->writeFile("WORLD", &buf);
01893         buf.clear();
01894 
01895         world->saveMaps(&buf);
01896         sgw->writeFile("MAPS", &buf);
01897         buf.clear();
01898 
01899         world->getCurrentMap()->save(&buf);
01900         sgw->writeFile("CURRENTMAP", &buf);
01901         buf.clear();
01902 
01903         ucmachine->saveStrings(&buf);
01904         sgw->writeFile("UCSTRINGS", &buf);
01905         buf.clear();
01906 
01907         ucmachine->saveGlobals(&buf);
01908         sgw->writeFile("UCGLOBALS", &buf);
01909         buf.clear();
01910 
01911         ucmachine->saveLists(&buf);
01912         sgw->writeFile("UCLISTS", &buf);
01913         buf.clear();
01914 
01915         save(&buf);
01916         sgw->writeFile("APP", &buf);
01917         buf.clear();
01918 
01919         sgw->finish();
01920 
01921         delete sgw;
01922 
01923         // Restore mouse over
01924         if (gump) gump->OnMouseOver();
01925 
01926         pout << "Done" << std::endl;
01927 
01928         return true;
01929 }
01930 
01931 void GUIApp::resetEngine()
01932 {
01933         con.Print(MM_INFO, "-- Resetting Engine --\n");
01934 
01935         // kill music
01936         if (audiomixer) audiomixer->reset();
01937 
01938         // now, reset everything (order matters)
01939         world->reset();
01940         ucmachine->reset();
01941         // ObjectManager, Kernel have to be last, because they kill
01942         // all processes/objects
01943         objectmanager->reset();
01944         kernel->reset();
01945         palettemanager->resetTransforms();
01946 
01947         // Reset thet gumps
01948         desktopGump = 0;
01949         consoleGump = 0;
01950         gameMapGump = 0;
01951         scalerGump = 0;
01952         inverterGump = 0;
01953 
01954         textmodes.clear();
01955 
01956         // reset mouse cursor
01957         while (!cursors.empty()) cursors.pop();
01958         pushMouseCursor();
01959 
01960         kernel->addProcess(new JoystickCursorProcess(JOY1, 0, 1));
01961 
01962         timeOffset = -(sint32)Kernel::get_instance()->getFrameNum();
01963         inversion = 0;
01964         save_count = 0;
01965         has_cheated = false;
01966 
01967         con.Print(MM_INFO, "-- Engine Reset --\n");
01968 }
01969 
01970 void GUIApp::setupCoreGumps()
01971 {
01972         con.Print(MM_INFO, "Setting up core game gumps...\n");
01973 
01974         Pentagram::Rect dims;
01975         screen->GetSurfaceDims(dims);
01976 
01977         con.Print(MM_INFO, "Creating Desktop...\n");
01978         desktopGump = new DesktopGump(0,0, dims.w, dims.h);
01979         desktopGump->InitGump(0);
01980         desktopGump->MakeFocus();
01981 
01982         con.Print(MM_INFO, "Creating ScalerGump...\n");
01983         scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
01984         scalerGump->InitGump(0);
01985 
01986         Pentagram::Rect scaled_dims;
01987         scalerGump->GetDims(scaled_dims);
01988 
01989         con.Print(MM_INFO, "Creating Graphics Console...\n");
01990         consoleGump = new ConsoleGump(0, 0, dims.w, dims.h);
01991         consoleGump->InitGump(0);
01992         consoleGump->HideConsole();
01993         
01994         con.Print(MM_INFO, "Creating Inverter...\n");
01995         inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
01996         inverterGump->InitGump(0);
01997 
01998         con.Print(MM_INFO, "Creating GameMapGump...\n");
01999         gameMapGump = new GameMapGump(0, 0, scaled_dims.w, scaled_dims.h);
02000         gameMapGump->InitGump(0);
02001 
02002 
02003         // TODO: clean this up
02004         assert(desktopGump->getObjId() == 256);
02005         assert(scalerGump->getObjId() == 257);
02006         assert(consoleGump->getObjId() == 258);
02007         assert(inverterGump->getObjId() == 259);
02008         assert(gameMapGump->getObjId() == 260);
02009 
02010 
02011         for (uint16 i = 261; i < 384; ++i)
02012                 objectmanager->reserveObjId(i);
02013 }
02014 
02015 bool GUIApp::newGame()
02016 {
02017         con.Print(MM_INFO, "Starting New Game...\n");
02018 
02019         resetEngine();
02020 
02021         setupCoreGumps();
02022 
02023         game->startGame();
02024 
02025         con.Print(MM_INFO, "Create Camera...\n");
02026         CameraProcess::SetCameraProcess(new CameraProcess(1)); // Follow Avatar
02027 
02028         con.Print(MM_INFO, "Create persistent Processes...\n");
02029         avatarMoverProcess = new AvatarMoverProcess();
02030         kernel->addProcess(avatarMoverProcess);
02031 
02032         kernel->addProcess(new HealProcess());
02033 
02034         kernel->addProcess(new SchedulerProcess());
02035 
02036         if (audiomixer) audiomixer->createProcesses();
02037 
02038 //      av->teleport(40, 16240, 15240, 64); // central Tenebrae
02039 //      av->teleport(3, 11391, 1727, 64); // docks, near gate
02040 //      av->teleport(39, 16240, 15240, 64); // West Tenebrae
02041 //      av->teleport(41, 12000, 15000, 64); // East Tenebrae
02042 //      av->teleport(8, 14462, 15178, 48); // before entrance to Mythran's house
02043 //      av->teleport(40, 13102,9474,48); // entrance to Mordea's throne room
02044 //      av->teleport(54, 14783,5959,8); // shrine of the Ancient Ones; Hanoi
02045 //      av->teleport(5, 5104,22464,48); // East road (tenebrae end)
02046 
02047         game->startInitialUsecode();
02048 
02049         return true;
02050 }
02051 
02052 bool GUIApp::loadGame(std::string filename)
02053 {
02054         con.Print(MM_INFO, "Loading...\n");
02055 
02056         IDataSource* ids = filesystem->ReadFile(filename);
02057         if (!ids) {
02058                 perr << "Can't find file: " << filename << std::endl;
02059                 return false;
02060         }
02061 
02062         Savegame* sg = new Savegame(ids);
02063         uint32 version = sg->getVersion();
02064         if (version == 0) {
02065                 perr << "Invalid or corrupt savegame." << std::endl;
02066                 return false;
02067         }
02068 
02069         if (version == 1 || version > Pentagram::savegame_version) {
02070                 perr << "Unsupported savegame version (" << version << ")"
02071                          << std::endl;
02072                 return false;
02073         }
02074         IDataSource* ds;
02075         GameInfo saveinfo;
02076         ds = sg->getDataSource("GAME");
02077         bool ok = saveinfo.load(ds, version);
02078 
02079         if (!ok) {
02080                 perr << "Invalid or corrupt savegame: missing GameInfo" << std::endl;
02081                 return false;
02082         }
02083 
02084         if (!gameinfo->match(saveinfo)) {
02085                 perr << "Game mismatch:" << std::endl;
02086                 perr << "Running game: " << gameinfo->getPrintDetails() << std::endl;
02087                 perr << "Savegame    : " << saveinfo.getPrintDetails() << std::endl;
02088 
02089 #ifdef DEBUG
02090                 bool ignore;
02091                 settingman->setDefault("ignore_savegame_mismatch", false);
02092                 settingman->get("ignore_savegame_mismatch", ignore);
02093 
02094                 if (!ignore)
02095                         return false;
02096 #else
02097                 return false;
02098 #endif
02099         }
02100 
02101         resetEngine();
02102 
02103         setupCoreGumps();
02104 
02105         // and load everything back (order matters)
02106         bool totalok = true;
02107 
02108 
02109         // UCSTRINGS, UCGLOBALS, UCLISTS don't depend on anything else,
02110         // so load these first
02111         ds = sg->getDataSource("UCSTRINGS");
02112         ok = ucmachine->loadStrings(ds, version);
02113         totalok &= ok;
02114         perr << "UCSTRINGS: " << (ok ? "ok" : "failed") << std::endl;
02115         delete ds;
02116 
02117         ds = sg->getDataSource("UCGLOBALS");
02118         ok = ucmachine->loadGlobals(ds, version);
02119         totalok &= ok;
02120         perr << "UCGLOBALS: " << (ok ? "ok" : "failed") << std::endl;
02121         delete ds;
02122 
02123         ds = sg->getDataSource("UCLISTS");
02124         ok = ucmachine->loadLists(ds, version);
02125         totalok &= ok;
02126         perr << "UCLISTS: " << (ok ? "ok" : "failed")<< std::endl;
02127         delete ds;
02128 
02129         // KERNEL must be before OBJECTS, for the egghatcher
02130         // KERNEL must be before APP, for the avatarMoverProcess
02131         ds = sg->getDataSource("KERNEL");
02132         ok = kernel->load(ds, version);
02133         totalok &= ok;
02134         perr << "KERNEL: " << (ok ? "ok" : "failed") << std::endl;
02135         delete ds;
02136 
02137         ds = sg->getDataSource("APP");
02138         ok = load(ds, version);
02139         totalok &= ok;
02140         perr << "APP: " << (ok ? "ok" : "failed") << std::endl;
02141         delete ds;
02142 
02143         // WORLD must be before OBJECTS, for the egghatcher
02144         ds = sg->getDataSource("WORLD");
02145         ok = world->load(ds, version);
02146         totalok &= ok;
02147         perr << "WORLD: " << (ok ? "ok" : "failed") << std::endl;
02148         delete ds;
02149 
02150         ds = sg->getDataSource("CURRENTMAP");
02151         ok = world->getCurrentMap()->load(ds, version);
02152         totalok &= ok;
02153         perr << "CURRENTMAP: " << (ok ? "ok" : "failed") << std::endl;
02154         delete ds;
02155 
02156         ds = sg->getDataSource("OBJECTS");
02157         ok = objectmanager->load(ds, version);
02158         totalok &= ok;
02159         perr << "OBJECTS: " << (ok ? "ok" : "failed") << std::endl;
02160         delete ds;
02161 
02162         ds = sg->getDataSource("MAPS");
02163         ok = world->loadMaps(ds, version);
02164         totalok &= ok;
02165         perr << "MAPS: " << (ok ? "ok" : "failed") << std::endl;
02166         delete ds;
02167 
02168         if (!ok) {
02169                 perr << "Loading failed!" << std::endl;
02170                 exit(1);
02171         }
02172 
02173         pout << "Done" << std::endl;
02174 
02175         delete sg;
02176         return false;
02177 }
02178 
02179 Gump* GUIApp::getGump(uint16 gumpid)
02180 {
02181         return p_dynamic_cast<Gump*>(ObjectManager::get_instance()->
02182                                                                  getObject(gumpid));
02183 }
02184 
02185 void GUIApp::addGump(Gump* gump)
02186 {
02187         // TODO: At some point, this will have to _properly_ choose to
02188         // which 'layer' to add the gump: inverted, scaled or neither.
02189 
02190         assert(desktopGump);
02191 
02192         if (gump->IsOfType<ShapeViewerGump>() || gump->IsOfType<MiniMapGump>() ||
02193                 gump->IsOfType<ConsoleGump>() || gump->IsOfType<ScalerGump>() ||
02194                 gump->IsOfType<PentagramMenuGump>()// ||
02195                 //(ttfoverrides && (gump->IsOfType<BarkGump>() ||
02196                 //                                gump->IsOfType<AskGump>()))
02197                 )
02198         {
02199 //              pout << "adding to desktopgump: "; gump->dumpInfo();
02200                 desktopGump->AddChild(gump);
02201         }
02202         else if (gump->IsOfType<GameMapGump>())
02203         {
02204 //              pout << "adding to invertergump: "; gump->dumpInfo();
02205                 inverterGump->AddChild(gump);
02206         }
02207         else if (gump->IsOfType<InverterGump>())
02208         {
02209 //              pout << "adding to scalergump: "; gump->dumpInfo();
02210                 scalerGump->AddChild(gump);
02211         }
02212         else if (gump->IsOfType<DesktopGump>())
02213         {
02214         }
02215         else
02216         {
02217 //              pout << "adding to scalergump: "; gump->dumpInfo();
02218                 scalerGump->AddChild(gump);
02219         }
02220 }
02221 
02222 uint32 GUIApp::getGameTimeInSeconds()
02223 {
02224         // 1 second per every 30 frames
02225         return (Kernel::get_instance()->getFrameNum()+timeOffset)/30; // constant!
02226 }
02227 
02228 
02229 void GUIApp::save(ODataSource* ods)
02230 {
02231         uint8 s = (avatarInStasis ? 1 : 0);
02232         ods->write1(s);
02233 
02234         sint32 absoluteTime = Kernel::get_instance()->getFrameNum()+timeOffset;
02235         ods->write4(static_cast<uint32>(absoluteTime));
02236         ods->write2(avatarMoverProcess->getPid());
02237 
02238         Pentagram::Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
02239         for (int i = 0; i < 12; i++) ods->write2(pal->matrix[i]);
02240         ods->write2(pal->transform);
02241 
02242         ods->write2(static_cast<uint16>(inversion));
02243 
02244         ods->write4(save_count);
02245 
02246         uint8 c = (has_cheated ? 1 : 0);
02247         ods->write1(c);
02248 }
02249 
02250 bool GUIApp::load(IDataSource* ids, uint32 version)
02251 {
02252         avatarInStasis = (ids->read1() != 0);
02253 
02254         // no gump should be moused over after load
02255         mouseOverGump = 0;
02256 
02257         sint32 absoluteTime = static_cast<sint32>(ids->read4());
02258         timeOffset = absoluteTime - Kernel::get_instance()->getFrameNum();
02259 
02260         uint16 amppid = ids->read2();
02261         avatarMoverProcess = p_dynamic_cast<AvatarMoverProcess*>(Kernel::get_instance()->getProcess(amppid));
02262 
02263         sint16 matrix[12];
02264         for (int i = 0; i < 12; i++)
02265                 matrix[i] = ids->read2();
02266 
02267         PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game, matrix);
02268         Pentagram::Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
02269         pal->transform = static_cast<Pentagram::PalTransforms>(ids->read2());
02270 
02271         inversion = ids->read2();
02272 
02273         save_count = ids->read4();
02274 
02275         has_cheated = (ids->read1() != 0);
02276 
02277         return true;
02278 }
02279 
02280 //
02281 // Console Commands
02282 //
02283 
02284 void GUIApp::ConCmd_saveGame(const Console::ArgvType &argv)
02285 {
02286         if (argv.size()==1)
02287         {
02288                 pout << "Usage: GUIApp::saveGame <filename>" << std::endl;
02289                 return;
02290         }
02291 
02292         std::string filename = "@save/";
02293         filename += argv[1].c_str();
02294         GUIApp::get_instance()->saveGame(filename, argv[1]);
02295 }
02296 
02297 void GUIApp::ConCmd_loadGame(const Console::ArgvType &argv)
02298 {
02299         if (argv.size()==1)
02300         {
02301                 pout << "Usage: GUIApp::loadGame <filename>" << std::endl;
02302                 return;
02303         }
02304 
02305         std::string filename = "@save/";
02306         filename += argv[1].c_str();
02307         GUIApp::get_instance()->loadGame(filename);
02308 }
02309 
02310 void GUIApp::ConCmd_newGame(const Console::ArgvType &argv)
02311 {
02312         GUIApp::get_instance()->newGame();
02313 }
02314 
02315 
02316 void GUIApp::ConCmd_quit(const Console::ArgvType &argv)
02317 {
02318         GUIApp::get_instance()->isRunning = false;
02319 }
02320 
02321 void GUIApp::ConCmd_drawRenderStats(const Console::ArgvType &argv)
02322 {
02323         if (argv.size() == 1)
02324         {
02325                 pout << "GUIApp::drawRenderStats = " << GUIApp::get_instance()->drawRenderStats << std::endl;
02326         }
02327         else
02328         {
02329                 GUIApp::get_instance()->drawRenderStats = std::strtol(argv[1].c_str(), 0, 0) != 0;
02330         }
02331 }
02332 
02333 void GUIApp::ConCmd_engineStats(const Console::ArgvType &argv)
02334 {
02335         Kernel::get_instance()->kernelStats();
02336         ObjectManager::get_instance()->objectStats();
02337         UCMachine::get_instance()->usecodeStats();
02338         World::get_instance()->worldStats();
02339 }
02340 
02341 void GUIApp::ConCmd_changeGame(const Console::ArgvType &argv)
02342 {
02343         if (argv.size() == 1)
02344         {
02345                 pout << "Current game is: " << GUIApp::get_instance()->gameinfo->name << std::endl;
02346         }
02347         else
02348         {
02349                 GUIApp::get_instance()->changeGame(argv[1]);
02350         }
02351 }
02352 
02353 void GUIApp::ConCmd_listGames(const Console::ArgvType &argv)
02354 {
02355         GUIApp *app = GUIApp::get_instance(); 
02356         std::vector<Pentagram::istring> games;
02357         games = app->settingman->listGames();
02358         std::vector<Pentagram::istring>::iterator iter;
02359         for (iter = games.begin(); iter != games.end(); ++iter) {
02360                 Pentagram::istring game = *iter;
02361                 GameInfo* info = app->getGameInfo(game);
02362                 con.Printf(MM_INFO, "%s: ", game.c_str());
02363                 if (info) {
02364                         std::string details = info->getPrintDetails();
02365                         con.Print(MM_INFO, details.c_str());
02366                 } else {
02367                         con.Print(MM_INFO, "(unknown)");
02368                 }
02369                 con.Print(MM_INFO, "\n");
02370         }
02371 }
02372 
02373 void GUIApp::ConCmd_setVideoMode(const Console::ArgvType &argv)
02374 {
02375         int fullscreen = -1;
02376         
02377         //if (argv.size() == 4) {
02378         //      if (argv[3] == "fullscreen") fullscreen = 1;
02379         //      else fullscreen = 0;
02380         //} else 
02381         if (argv.size() != 3)
02382         {
02383                 //pout << "Usage: GUIApp::setVidMode width height [fullscreen/windowed]" << std::endl;
02384                 pout << "Usage: GUIApp::setVidMode width height" << std::endl;
02385                 return;
02386         }
02387 
02388         GUIApp::get_instance()->changeVideoMode(strtol(argv[1].c_str(), 0, 0), strtol(argv[2].c_str(), 0, 0), fullscreen);
02389 }
02390 
02391 void GUIApp::ConCmd_toggleFullscreen(const Console::ArgvType &argv)
02392 {
02393         GUIApp::get_instance()->changeVideoMode(-1, -1, -2);
02394 }
02395 
02396 void GUIApp::ConCmd_toggleAvatarInStasis(const Console::ArgvType &argv)
02397 {
02398         GUIApp * g = GUIApp::get_instance();
02399         g->toggleAvatarInStasis();
02400         pout << "avatarInStasis = " << g->isAvatarInStasis() << std::endl;
02401 }
02402 
02403 void GUIApp::ConCmd_togglePaintEditorItems(const Console::ArgvType &argv)
02404 {
02405         GUIApp * g = GUIApp::get_instance();
02406         g->togglePaintEditorItems();
02407         pout << "paintEditorItems = " << g->isPaintEditorItems() << std::endl;
02408 }
02409 
02410 void GUIApp::ConCmd_toggleShowTouchingItems(const Console::ArgvType &argv)
02411 {
02412         GUIApp * g = GUIApp::get_instance();
02413         g->toggleShowTouchingItems();
02414         pout << "ShowTouchingItems = " << g->isShowTouchingItems() << std::endl;
02415 }
02416 
02417 void GUIApp::ConCmd_closeItemGumps(const Console::ArgvType &argv)
02418 {
02419         GUIApp * g = GUIApp::get_instance();
02420         g->getDesktopGump()->CloseItemDependents();
02421 }
02422 
02423 //
02424 // Intrinsics
02425 //
02426 
02427 uint32 GUIApp::I_makeAvatarACheater(const uint8* /*args*/,
02428                                                                         unsigned int /*argsize*/)
02429 {
02430         GUIApp::get_instance()->makeCheater();
02431         return 0;
02432 }
02433 
02434 uint32 GUIApp::I_getCurrentTimerTick(const uint8* /*args*/,
02435                                                                                 unsigned int /*argsize*/)
02436 {
02437         // number of ticks of a 60Hz timer, with the default animrate of 30Hz
02438         return Kernel::get_instance()->getFrameNum()*2;
02439 }
02440 
02441 uint32 GUIApp::I_setAvatarInStasis(const uint8* args, unsigned int /*argsize*/)
02442 {
02443         ARG_SINT16(stasis);
02444         get_instance()->setAvatarInStasis(stasis!=0);
02445         return 0;
02446 }
02447 
02448 uint32 GUIApp::I_getAvatarInStasis(const uint8* /*args*/, unsigned int /*argsize*/)
02449 {
02450         if (get_instance()->avatarInStasis)
02451                 return 1;
02452         else
02453                 return 0;
02454 }
02455 
02456 uint32 GUIApp::I_getTimeInGameHours(const uint8* /*args*/,
02457                                                                                 unsigned int /*argsize*/)
02458 {
02459         // 900 seconds per game hour
02460         return get_instance()->getGameTimeInSeconds() / 900;
02461 }
02462 
02463 uint32 GUIApp::I_getTimeInMinutes(const uint8* /*args*/,
02464                                                                                 unsigned int /*argsize*/)
02465 {
02466         // 60 seconds per minute
02467         return get_instance()->getGameTimeInSeconds() / 60;
02468 }
02469 
02470 uint32 GUIApp::I_getTimeInSeconds(const uint8* /*args*/,
02471                                                                                 unsigned int /*argsize*/)
02472 {
02473         return get_instance()->getGameTimeInSeconds();
02474 }
02475 
02476 uint32 GUIApp::I_setTimeInGameHours(const uint8* args,
02477                                                                                 unsigned int /*argsize*/)
02478 {
02479         ARG_UINT16(newhour);
02480 
02481         // 1 game hour per every 27000 frames
02482         sint32  absolute = newhour*27000;
02483         get_instance()->timeOffset = absolute-Kernel::get_instance()->getFrameNum();
02484 
02485         return 0;
02486 }
02487 
02488 uint32 GUIApp::I_closeItemGumps(const uint8* args, unsigned int /*argsize*/)
02489 {
02490         GUIApp* g = GUIApp::get_instance();
02491         g->getDesktopGump()->CloseItemDependents();
02492 
02493         return 0;
02494 }

Generated on Fri Jul 27 22:27:17 2007 for pentagram by  doxygen 1.4.7