U8Game.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2004-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 "U8Game.h"
00022 
00023 #include "PaletteManager.h"
00024 #include "IDataSource.h"
00025 #include "FileSystem.h"
00026 #include "GameData.h"
00027 #include "XFormBlend.h"
00028 #include "U8SaveFile.h"
00029 #include "World.h"
00030 #include "MainActor.h"
00031 #include "ItemFactory.h"
00032 #include "ObjectManager.h"
00033 #include "GUIApp.h"
00034 #include "SettingManager.h"
00035 #include "MovieGump.h"
00036 #include "RawArchive.h"
00037 #include "CreditsGump.h"
00038 #include "Kernel.h"
00039 #include "MusicProcess.h"
00040 #include "StartU8Process.h"
00041 #include "getObject.h"
00042 
00043 U8Game::U8Game() : Game()
00044 {
00045         // Set some defaults for gameplay-related settings
00046         SettingManager* settingman = SettingManager::get_instance();
00047         settingman->setDefault("skipstart", false);
00048         settingman->setDefault("endgame", false);
00049         settingman->setDefault("quotes", false);
00050         settingman->setDefault("footsteps", true);
00051         settingman->setDefault("cheat", true);
00052         settingman->setDefault("targetedjump", true);
00053 
00054         GameInfo* info = GUIApp::get_instance()->getGameInfo();
00055         if (info->language == GameInfo::GAMELANG_JAPANESE) {
00056                 settingman->setDefault("textdelay", 20);
00057         } else {
00058                 settingman->setDefault("textdelay", 8);
00059         }
00060 
00061         con.AddConsoleCommand("Cheat::items", U8Game::ConCmd_cheatItems);
00062         con.AddConsoleCommand("Cheat::equip", U8Game::ConCmd_cheatEquip);
00063 }
00064 
00065 U8Game::~U8Game()
00066 {
00067         con.RemoveConsoleCommand(U8Game::ConCmd_cheatItems);
00068         con.RemoveConsoleCommand(U8Game::ConCmd_cheatEquip);
00069 }
00070 
00071 bool U8Game::loadFiles()
00072 {
00073         // Load palette
00074         pout << "Load Palette" << std::endl;
00075         IDataSource *pf = FileSystem::get_instance()->ReadFile("@game/static/u8pal.pal");
00076         if (!pf) {
00077                 perr << "Unable to load static/u8pal.pal." << std::endl;
00078                 return false;
00079         }
00080         pf->seek(4); // seek past header
00081 
00082         IBufferDataSource xfds(U8XFormPal,1024);
00083         PaletteManager::get_instance()->load(PaletteManager::Pal_Game, *pf, xfds);
00084         delete pf;
00085 
00086         pout << "Load GameData" << std::endl;
00087         GameData::get_instance()->loadU8Data();
00088 
00089         return true;
00090 }
00091 
00092 bool U8Game::startGame()
00093 {
00094         // NOTE: assumes the entire engine has been reset!
00095 
00096         pout << "Starting new Ultima 8 game." << std::endl;
00097 
00098         ObjectManager* objman = ObjectManager::get_instance();
00099 
00100         // reserve a number of objids just in case we'll need them sometime
00101         for (uint16 i = 384; i < 512; ++i)
00102                 objman->reserveObjId(i);
00103 
00104         // reserve ObjId 666 for the Guardian Bark hack
00105         objman->reserveObjId(666);
00106 
00107         IDataSource *saveds = FileSystem::get_instance()->ReadFile("@game/savegame/u8save.000");
00108         if (!saveds) {
00109                 perr << "Unable to load savegame/u8save.000." << std::endl;
00110                 return false;
00111         }
00112         U8SaveFile *u8save = new U8SaveFile(saveds);
00113 
00114         IDataSource *nfd = u8save->getDataSource("NONFIXED.DAT");
00115         if (!nfd) {
00116                 perr << "Unable to load savegame/u8save.000/NONFIXED.DAT." <<std::endl;
00117                 return false;
00118         }
00119         World::get_instance()->loadNonFixed(nfd); // deletes nfd
00120 
00121         IDataSource *icd = u8save->getDataSource("ITEMCACH.DAT");
00122         if (!icd) {
00123                 perr << "Unable to load savegame/u8save.000/ITEMCACH.DAT." <<std::endl;
00124                 return false;
00125         }
00126         IDataSource *npcd = u8save->getDataSource("NPCDATA.DAT");
00127         if (!npcd) {
00128                 perr << "Unable to load savegame/u8save.000/NPCDATA.DAT." << std::endl;
00129                 return false;
00130         }
00131 
00132         World::get_instance()->loadItemCachNPCData(icd, npcd); // deletes icd, npcd
00133         delete u8save;
00134 
00135         MainActor* av = getMainActor();
00136         assert(av);
00137 
00138         av->setName("Avatar"); // default name
00139 
00140         // avatar needs a backpack ... CONSTANTs and all that
00141         Item* backpack = ItemFactory::createItem(529, 0, 0, 0, 0, 0, 0, true);
00142         backpack->moveToContainer(av);
00143 
00144         World::get_instance()->switchMap(av->getMapNum());
00145 
00146         GUIApp::get_instance()->setAvatarInStasis(true);
00147 
00148         return true;
00149 }
00150 
00151 void U8Game::ConCmd_cheatItems(const Console::ArgvType &argv)
00152 {
00153         MainActor* av = getMainActor();
00154         if (!av) return;
00155         Container* backpack = getContainer(av->getEquip(7)); // CONSTANT!
00156         if (!backpack) return;
00157 
00158         // obsidian
00159         Item* money = ItemFactory::createItem(143, 7, 500, 0, 0, 0, 0, true);
00160         money->moveToContainer(backpack);
00161         money->setGumpLocation(40, 20);
00162 
00163         // skull of quakes
00164         Item *skull = ItemFactory::createItem(814, 0, 0, 0, 0, 0, 0, true);
00165         skull->moveToContainer(backpack);  
00166         skull->setGumpLocation(60, 20);
00167 
00168         // recall item
00169         Item *recall = ItemFactory::createItem(833, 0, 0, 0, 0, 0, 0, true);
00170         recall->moveToContainer(backpack);
00171         recall->setGumpLocation(20, 20);
00172 
00173         // sword
00174         Item* sword = ItemFactory::createItem(420, 0, 0, 0, 0, 0, 0, true);
00175         sword->moveToContainer(backpack);
00176         sword->setGumpLocation(20, 30);
00177 
00178         Item* flamesting = ItemFactory::createItem(817, 0, 0, 0, 0, 0, 0, true);
00179         flamesting->moveToContainer(backpack);
00180         flamesting->setGumpLocation(20, 30);
00181 
00182         Item* hammer = ItemFactory::createItem(815, 0, 0, 0, 0, 0, 0, true);
00183         hammer->moveToContainer(backpack);
00184         hammer->setGumpLocation(20, 30);
00185 
00186         Item* slayer = ItemFactory::createItem(816, 0, 0, 0, 0, 0, 0, true);
00187         slayer->moveToContainer(backpack);
00188         slayer->setGumpLocation(20, 30);
00189 
00190         // necromancy reagents
00191         Item* bagitem = ItemFactory::createItem(637, 0, 0, 0, 0, 0, 0, true);
00192         bagitem->moveToContainer(backpack);
00193         bagitem->setGumpLocation(70, 40);
00194 
00195         bagitem = ItemFactory::createItem(637, 0, 0, 0, 0, 0, 0, true);
00196         Container* bag = p_dynamic_cast<Container*>(bagitem);
00197 
00198         Item* reagents = ItemFactory::createItem(395, 0, 50, 0, 0, 0, 0, true);
00199         reagents->moveToContainer(bag);
00200         reagents->setGumpLocation(10, 10);
00201         reagents = ItemFactory::createItem(395, 6, 50, 0, 0, 0, 0, true);
00202         reagents->moveToContainer(bag);
00203         reagents->setGumpLocation(30, 10);
00204         reagents = ItemFactory::createItem(395, 8, 50, 0, 0, 0, 0, true);
00205         reagents->moveToContainer(bag);
00206         reagents->setGumpLocation(50, 10);
00207         reagents = ItemFactory::createItem(395, 9, 50, 0, 0, 0, 0, true);
00208         reagents->moveToContainer(bag);
00209         reagents->setGumpLocation(20, 30);
00210         reagents = ItemFactory::createItem(395, 10, 50, 0, 0, 0, 0, true);
00211         reagents->moveToContainer(bag);
00212         reagents->setGumpLocation(40, 30);
00213         reagents = ItemFactory::createItem(395, 14, 50, 0, 0, 0, 0, true);
00214         reagents->moveToContainer(bag);
00215         reagents->setGumpLocation(60, 30);
00216 
00217         bagitem->moveToContainer(backpack);
00218         bagitem->setGumpLocation(70, 20);
00219 
00220         // theurgy foci
00221         bagitem = ItemFactory::createItem(637, 0, 0, 0, 0, 0, 0, true);
00222         bag = p_dynamic_cast<Container*>(bagitem);
00223 
00224         Item* focus = ItemFactory::createItem(396, 8, 0, 0, 0, 0, 0, true);
00225         focus->moveToContainer(bag);
00226         focus->setGumpLocation(10, 10);
00227         focus = ItemFactory::createItem(396, 9, 0, 0, 0, 0, 0, true);
00228         focus->moveToContainer(bag);
00229         focus->setGumpLocation(25, 10);
00230         focus = ItemFactory::createItem(396, 10, 0, 0, 0, 0, 0, true);
00231         focus->moveToContainer(bag);
00232         focus->setGumpLocation(40, 10);
00233         focus = ItemFactory::createItem(396, 11, 0, 0, 0, 0, 0, true);
00234         focus->moveToContainer(bag);
00235         focus->setGumpLocation(55, 10);
00236         focus = ItemFactory::createItem(396, 12, 0, 0, 0, 0, 0, true);
00237         focus->moveToContainer(bag);
00238         focus->setGumpLocation(70, 10);
00239         focus = ItemFactory::createItem(396, 13, 0, 0, 0, 0, 0, true);
00240         focus->moveToContainer(bag);
00241         focus->setGumpLocation(10, 30);
00242         focus = ItemFactory::createItem(396, 14, 0, 0, 0, 0, 0, true);
00243         focus->moveToContainer(bag);
00244         focus->setGumpLocation(30, 30);
00245         focus = ItemFactory::createItem(396, 15, 0, 0, 0, 0, 0, true);
00246         focus->moveToContainer(bag);
00247         focus->setGumpLocation(50, 30); 
00248         focus = ItemFactory::createItem(396, 17, 0, 0, 0, 0, 0, true);
00249         focus->moveToContainer(bag);
00250         focus->setGumpLocation(70, 30); 
00251 
00252         bagitem->moveToContainer(backpack);
00253         bagitem->setGumpLocation(0, 30);
00254 
00255 
00256         // oil flasks
00257         Item* flask = ItemFactory::createItem(579, 0, 0, 0, 0, 0, 0, true);
00258         flask->moveToContainer(backpack);
00259         flask->setGumpLocation(30, 40);
00260         flask = ItemFactory::createItem(579, 0, 0, 0, 0, 0, 0, true);
00261         flask->moveToContainer(backpack);
00262         flask->setGumpLocation(30, 40);
00263         flask = ItemFactory::createItem(579, 0, 0, 0, 0, 0, 0, true);
00264         flask->moveToContainer(backpack);
00265         flask->setGumpLocation(30, 40);
00266 
00267         // zealan shield
00268         Item* shield = ItemFactory::createItem(828, 0, 0, 0, 0, 0, 0, true);
00269         shield->moveToContainer(backpack);
00270         shield->randomGumpLocation();
00271 
00272         shield = ItemFactory::createItem(539, 0, 0, 0, 0, 0, 0, true);
00273         shield->moveToContainer(backpack);
00274         shield->randomGumpLocation();
00275 
00276         // armour
00277         Item* armour = ItemFactory::createItem(64, 0, 0, 0, 0, 0, 0, true);
00278         armour->moveToContainer(backpack);
00279         armour->randomGumpLocation();
00280 
00281         // death disks
00282         Item* disk = ItemFactory::createItem(750, 0, 0, 0, 0, 0, 0, true);
00283         disk->moveToContainer(backpack);
00284         disk->randomGumpLocation();
00285 
00286         disk = ItemFactory::createItem(750, 0, 0, 0, 0, 0, 0, true);
00287         disk->moveToContainer(backpack);
00288         disk->randomGumpLocation();
00289 
00290         disk = ItemFactory::createItem(750, 0, 0, 0, 0, 0, 0, true);
00291         disk->moveToContainer(backpack);
00292         disk->randomGumpLocation();
00293 }
00294 
00295 void U8Game::ConCmd_cheatEquip(const Console::ArgvType &argv)
00296 {
00297         MainActor* av = getMainActor();
00298         if (!av) return;
00299         Container* backpack = getContainer(av->getEquip(7)); // CONSTANT!
00300         if (!backpack) return;
00301 
00302         Item* item;
00303 
00304         // move all current equipment to backpack
00305         for (unsigned int i = 0; i < 7; ++i) {
00306                 item = getItem(av->getEquip(i));
00307                 if (item) {
00308                         item->moveToContainer(backpack, false); // no weight/volume check
00309                         item->randomGumpLocation();
00310                 }
00311         }
00312 
00313         // give new equipment:
00314 
00315         // deceiver
00316         item = ItemFactory::createItem(822, 0, 0, 0, 0, 0, 0, true);
00317         av->setEquip(item, false);
00318 
00319         // armour
00320         item = ItemFactory::createItem(841, 0, 0, 0, 0, 0, 0, true);
00321         av->setEquip(item, false);
00322 
00323         // shield
00324         item = ItemFactory::createItem(842, 0, 0, 0, 0, 0, 0, true);
00325         av->setEquip(item, false);
00326 
00327         // helmet
00328         item = ItemFactory::createItem(843, 0, 0, 0, 0, 0, 0, true);
00329         av->setEquip(item, false);
00330 
00331         // arm guards
00332         item = ItemFactory::createItem(844, 0, 0, 0, 0, 0, 0, true);
00333         av->setEquip(item, false);
00334 
00335         // leggings
00336         item = ItemFactory::createItem(845, 0, 0, 0, 0, 0, 0, true);
00337         av->setEquip(item, false);
00338 }
00339 
00340 bool U8Game::startInitialUsecode()
00341 {
00342         Process* proc = new StartU8Process();
00343         Kernel::get_instance()->addProcess(proc);
00344 
00345         return true;
00346 }
00347 
00348 
00349 ProcId U8Game::playIntroMovie()
00350 {
00351         GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00352         char langletter = gameinfo->getLanguageFileLetter();
00353         if (!langletter) {
00354                 perr << "U8Game::playIntro: Unknown language." << std::endl;
00355                 return 0;
00356         }
00357 
00358         std::string filename = "@game/static/";
00359         filename += langletter;
00360         filename += "intro.skf";
00361 
00362         FileSystem* filesys = FileSystem::get_instance();
00363         IDataSource* skf = filesys->ReadFile(filename);
00364         if (!skf) {
00365                 pout << "U8Game::playIntro: movie not found." << std::endl;
00366                 return 0;
00367         }
00368         
00369         RawArchive* flex = new RawArchive(skf);
00370         return MovieGump::U8MovieViewer(flex, true);
00371 }
00372 
00373 ProcId U8Game::playEndgameMovie()
00374 {
00375         std::string filename = "@game/static/endgame.skf";
00376         FileSystem* filesys = FileSystem::get_instance();
00377         IDataSource* skf = filesys->ReadFile(filename);
00378         if (!skf) {
00379                 pout << "U8Game::playEndgame: movie not found." << std::endl;
00380                 return 0;
00381         }
00382         
00383         RawArchive* flex = new RawArchive(skf);
00384         return MovieGump::U8MovieViewer(flex);
00385 }
00386 
00387 void U8Game::playCredits()
00388 {
00389         GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00390         char langletter = gameinfo->getLanguageFileLetter();
00391         if (!langletter) {
00392                 perr << "U8Game::playCredits: Unknown language." << std::endl;
00393                 return;
00394         }
00395         std::string filename = "@game/static/";
00396         filename += langletter;
00397         filename += "credits.dat";
00398 
00399         IDataSource* ids = FileSystem::get_instance()->ReadFile(filename);
00400         if (!ids) {
00401                 perr << "U8Game::playCredits: error opening credits file: "
00402                          << filename << std::endl;
00403                 return;
00404         }
00405         std::string text = getCreditText(ids);
00406         delete ids;
00407 
00408         MusicProcess* musicproc = MusicProcess::get_instance();
00409         if (musicproc) musicproc->playMusic(51); // CONSTANT!
00410 
00411         CreditsGump* gump = new CreditsGump(text);
00412         gump->InitGump(0);
00413         gump->SetFlagWhenFinished("quotes");
00414         gump->setRelativePosition(Gump::CENTER);
00415 }
00416 
00417 void U8Game::playQuotes()
00418 {
00419         std::string filename = "@game/static/quotes.dat";
00420 
00421         IDataSource* ids = FileSystem::get_instance()->ReadFile(filename);
00422         if (!ids) {
00423                 perr << "U8Game::playCredits: error opening credits file: "
00424                          << filename << std::endl;
00425                 return;
00426         }
00427         std::string text = getCreditText(ids);
00428         delete ids;
00429 
00430         MusicProcess* musicproc = MusicProcess::get_instance();
00431         if (musicproc) musicproc->playMusic(113); // CONSTANT!
00432 
00433         Gump* gump = new CreditsGump(text, 80);
00434         gump->InitGump(0);
00435         gump->setRelativePosition(Gump::CENTER);
00436 }
00437 
00438 
00439 void U8Game::writeSaveInfo(ODataSource* ods)
00440 {
00441         MainActor* av = getMainActor();
00442         sint32 x,y,z;
00443 
00444         std::string avname = av->getName();
00445         uint8 namelength = static_cast<uint8>(avname.size());
00446         ods->write1(namelength);
00447         for (unsigned int i = 0; i < namelength; ++i)
00448                 ods->write1(static_cast<uint8>(avname[i]));
00449 
00450         av->getLocation(x,y,z);
00451         ods->write2(av->getMapNum());
00452         ods->write4(static_cast<uint32>(x));
00453         ods->write4(static_cast<uint32>(y));
00454         ods->write4(static_cast<uint32>(z));
00455 
00456         ods->write2(av->getStr());
00457         ods->write2(av->getInt());
00458         ods->write2(av->getDex());
00459         ods->write2(av->getHP());
00460         ods->write2(av->getMaxHP());
00461         ods->write2(av->getMana());
00462         ods->write2(av->getMaxMana());
00463         ods->write2(av->getArmourClass());
00464         ods->write2(av->getTotalWeight());
00465 
00466         for (unsigned int i = 1; i <= 6; i++)
00467         {
00468                 uint16 objid = av->getEquip(i);
00469                 Item* item = getItem(objid);
00470                 if (item) {
00471                         ods->write4(item->getShape());
00472                         ods->write4(item->getFrame());
00473                 } else {
00474                         ods->write4(0);
00475                         ods->write4(0);
00476                 }
00477         }
00478 }
00479 
00480 
00481 std::string U8Game::getCreditText(IDataSource* ids)
00482 {
00483         std::string text;
00484         unsigned int size = ids->getSize();
00485         text.resize(size);
00486         for (unsigned int i = 0; i < size; ++i) {
00487                 uint8 c = ids->read1();
00488                 int x;
00489                 switch(i) {
00490             case 0: case 1:
00491                         x = 0; break;
00492                 case 2:
00493                         x = 0xE1; break;
00494                 default:
00495                         x = 0x20 * (i+1) + (i >> 1);
00496                         x += (i % 0x40) * ((i & 0xC0) >> 6) * 0x40;
00497                         break;
00498                 }
00499                 char d = (c ^ x) & 0xFF;
00500                 if (d == 0) d = '\n';
00501                 text[i] = d;
00502         }
00503 
00504         return text;
00505 }

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