00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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);
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
00095
00096 pout << "Starting new Ultima 8 game." << std::endl;
00097
00098 ObjectManager* objman = ObjectManager::get_instance();
00099
00100
00101 for (uint16 i = 384; i < 512; ++i)
00102 objman->reserveObjId(i);
00103
00104
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);
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);
00133 delete u8save;
00134
00135 MainActor* av = getMainActor();
00136 assert(av);
00137
00138 av->setName("Avatar");
00139
00140
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));
00156 if (!backpack) return;
00157
00158
00159 Item* money = ItemFactory::createItem(143, 7, 500, 0, 0, 0, 0, true);
00160 money->moveToContainer(backpack);
00161 money->setGumpLocation(40, 20);
00162
00163
00164 Item *skull = ItemFactory::createItem(814, 0, 0, 0, 0, 0, 0, true);
00165 skull->moveToContainer(backpack);
00166 skull->setGumpLocation(60, 20);
00167
00168
00169 Item *recall = ItemFactory::createItem(833, 0, 0, 0, 0, 0, 0, true);
00170 recall->moveToContainer(backpack);
00171 recall->setGumpLocation(20, 20);
00172
00173
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
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
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
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
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
00277 Item* armour = ItemFactory::createItem(64, 0, 0, 0, 0, 0, 0, true);
00278 armour->moveToContainer(backpack);
00279 armour->randomGumpLocation();
00280
00281
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));
00300 if (!backpack) return;
00301
00302 Item* item;
00303
00304
00305 for (unsigned int i = 0; i < 7; ++i) {
00306 item = getItem(av->getEquip(i));
00307 if (item) {
00308 item->moveToContainer(backpack, false);
00309 item->randomGumpLocation();
00310 }
00311 }
00312
00313
00314
00315
00316 item = ItemFactory::createItem(822, 0, 0, 0, 0, 0, 0, true);
00317 av->setEquip(item, false);
00318
00319
00320 item = ItemFactory::createItem(841, 0, 0, 0, 0, 0, 0, true);
00321 av->setEquip(item, false);
00322
00323
00324 item = ItemFactory::createItem(842, 0, 0, 0, 0, 0, 0, true);
00325 av->setEquip(item, false);
00326
00327
00328 item = ItemFactory::createItem(843, 0, 0, 0, 0, 0, 0, true);
00329 av->setEquip(item, false);
00330
00331
00332 item = ItemFactory::createItem(844, 0, 0, 0, 0, 0, 0, true);
00333 av->setEquip(item, false);
00334
00335
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);
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);
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 }