Initial commit
This commit is contained in:
245
engines/ultima/ultima8/games/cru_game.cpp
Normal file
245
engines/ultima/ultima8/games/cru_game.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/games/cru_game.h"
|
||||
#include "ultima/ultima8/games/start_crusader_process.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gumps/movie_gump.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
#include "ultima/ultima8/gumps/main_menu_process.h"
|
||||
#include "ultima/ultima8/gumps/cru_credits_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_demo_gump.h"
|
||||
#include "ultima/ultima8/kernel/object_manager.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/gfx/xform_blend.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/actors/npc_dat.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
#include "gui/message.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
CruGame::CruGame() : Game(), _skipIntroMovie(false) {
|
||||
}
|
||||
|
||||
CruGame::~CruGame() {
|
||||
|
||||
}
|
||||
|
||||
static bool loadPalette(const char *path, PaletteManager::PalIndex index) {
|
||||
Common::File pf;
|
||||
if (!pf.open(path)) {
|
||||
warning("Unable to load %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::MemoryReadStream xfds(CruXFormPal, 1024);
|
||||
PaletteManager::get_instance()->load(index, pf, xfds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CruGame::loadFiles() {
|
||||
// Load palette
|
||||
debug(1, "Load Palettes");
|
||||
|
||||
if (!loadPalette("static/gamepal.pal", PaletteManager::Pal_Game))
|
||||
return false;
|
||||
// This one is not always present and only needed for the credits,
|
||||
// let it fail if needed.
|
||||
loadPalette("static/cred.pal", PaletteManager::Pal_Cred);
|
||||
if (!loadPalette("static/diff.pal", PaletteManager::Pal_Diff))
|
||||
return false;
|
||||
if (!loadPalette("static/misc.pal", PaletteManager::Pal_Misc))
|
||||
return false;
|
||||
if (!loadPalette("static/misc2.pal", PaletteManager::Pal_Misc2))
|
||||
return false;
|
||||
// We don't use his one at the moment, ok to fail.
|
||||
loadPalette("static/star.pal", PaletteManager::Pal_Star);
|
||||
|
||||
debug(1, "Load GameData");
|
||||
GameData::get_instance()->loadRemorseData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CruGame::startGame() {
|
||||
// NOTE: assumes the entire engine has been reset!
|
||||
debug(1, "Starting new Crusader: No Remorse game.");
|
||||
|
||||
ObjectManager *objman = ObjectManager::get_instance();
|
||||
|
||||
// reserve a number of objids just in case we'll need them sometime
|
||||
for (uint16 i = 384; i < 512; ++i)
|
||||
objman->reserveObjId(i);
|
||||
|
||||
Actor *actor = ItemFactory::createActor(1, 0, 0, Item::FLG_IN_NPC_LIST,
|
||||
1, 1, Item::EXT_PERMANENT_NPC, false);
|
||||
if (!actor)
|
||||
error("Couldn't create MainActor");
|
||||
|
||||
const NPCDat *npcData = GameData::get_instance()->getNPCDataForShape(1);
|
||||
|
||||
actor->setStr(75);
|
||||
actor->setHP(npcData->getMaxHp());
|
||||
actor->setInt(5000); // max mana (energy) is 2x intelligence, or 10000.
|
||||
actor->setMana(2500);
|
||||
|
||||
ObjectManager::get_instance()->assignActorObjId(actor, 1);
|
||||
|
||||
actor->setLocation(0, 0, 0); // Map 1 (mission 1)
|
||||
|
||||
// Some useful points to warp into for testing No Remorse
|
||||
//actor->setLocation(60716, 59400, 16); // Map 1 (mission 1)
|
||||
//actor->setLocation(42493, 26621, 16); // Map 2 (mission 1 / level 4)
|
||||
//actor->setLocation(34302, 32254, 16); // Map 3 (mission 2)
|
||||
//actor->setLocation(34813, 33789, 16); // Map 4
|
||||
//actor->setLocation(37373, 30205, 16); // Map 5
|
||||
//actor->setLocation(37373, 30205, 16); // Map 6
|
||||
//actor->setLocation(35070, 26142, 96); // Map 7
|
||||
//actor->setLocation(29693, 32253, 0); // Map 8 - unfinished area?
|
||||
//actor->setLocation(2046, 2046, 0); // Map 9
|
||||
//actor->setLocation(14845, 6141, 0); // Map 22 - debugging map
|
||||
//actor->setLocation(34302, 32254, 16); // Map 40 (Rebel base)
|
||||
|
||||
World::get_instance()->switchMap(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CruGame::startInitialUsecode(int saveSlot) {
|
||||
if (saveSlot >= 0 && ConfMan.getBool("skip_intro"))
|
||||
_skipIntroMovie = true;
|
||||
Process* proc = new StartCrusaderProcess(saveSlot);
|
||||
Kernel::get_instance()->addProcess(proc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static ProcId playMovie(const char *movieID, bool fade, bool noScale) {
|
||||
MovieGump *gump = MovieGump::CruMovieViewer(movieID, 640, 480, nullptr, nullptr, 0);
|
||||
if (!gump) {
|
||||
debug(1, "RemorseGame::playIntro: movie %s not found.", movieID);
|
||||
return 0;
|
||||
}
|
||||
gump->CreateNotifier();
|
||||
return gump->GetNotifyProcess()->getPid();
|
||||
}
|
||||
|
||||
ProcId CruGame::playIntroMovie(bool fade) {
|
||||
if (_skipIntroMovie)
|
||||
return 0;
|
||||
const char *name = (GAME_IS_REMORSE ? "T01" : "origin");
|
||||
ProcId pid = playMovie(name, fade, true);
|
||||
if (!pid) {
|
||||
GUI::MessageDialogWithURL dialog(_("Crusader intro movie file missing - check that the FLICS and SOUND directories have been copied from the CD. More instructions are on the wiki: https://wiki.scummvm.org/index.php?title=Crusader:_No_Remorse."), "https://wiki.scummvm.org/index.php?title=Crusader:_No_Remorse");
|
||||
dialog.runModal();
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
ProcId CruGame::playIntroMovie2(bool fade) {
|
||||
if (_skipIntroMovie)
|
||||
return 0;
|
||||
const char *name = (GAME_IS_REMORSE ? "T02" : "ANIM01");
|
||||
return playMovie(name, fade, false);
|
||||
}
|
||||
|
||||
ProcId CruGame::playEndgameMovie(bool fade) {
|
||||
return playMovie("O01", fade, false);
|
||||
}
|
||||
|
||||
void CruGame::playDemoScreen() {
|
||||
Process *menuproc = new MainMenuProcess();
|
||||
Kernel::get_instance()->addProcess(menuproc);
|
||||
|
||||
const char *bmp_filename = "static/buyme.dat";
|
||||
auto *bmprs = new Common::File();
|
||||
if (!bmprs->open(bmp_filename)) {
|
||||
warning("RemorseGame::playDemoScreen: error opening demo background: %s", bmp_filename);
|
||||
delete bmprs;
|
||||
return;
|
||||
}
|
||||
Gump *gump = new CruDemoGump(bmprs);
|
||||
gump->InitGump(0);
|
||||
gump->CreateNotifier();
|
||||
Process *notifyproc = gump->GetNotifyProcess();
|
||||
|
||||
if (notifyproc) {
|
||||
menuproc->waitFor(notifyproc);
|
||||
}
|
||||
}
|
||||
|
||||
ProcId CruGame::playCreditsNoMenu() {
|
||||
const char *txt_filename = "static/credits.dat";
|
||||
const char *bmp_filename = "static/cred.dat";
|
||||
auto *txtrs = new Common::File();
|
||||
auto *bmprs = new Common::File();
|
||||
|
||||
if (!txtrs->open(txt_filename)) {
|
||||
warning("RemorseGame::playCredits: error opening credits text: %s", txt_filename);
|
||||
delete txtrs;
|
||||
delete bmprs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bmprs->open(bmp_filename)) {
|
||||
warning("RemorseGame::playCredits: error opening credits background: %s", bmp_filename);
|
||||
delete txtrs;
|
||||
delete bmprs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gump *creditsgump = new CruCreditsGump(txtrs, bmprs);
|
||||
creditsgump->InitGump(nullptr);
|
||||
creditsgump->CreateNotifier();
|
||||
Process *notifyproc = creditsgump->GetNotifyProcess();
|
||||
return notifyproc->getPid();
|
||||
}
|
||||
|
||||
|
||||
void CruGame::playCredits() {
|
||||
Process *menuproc = new MainMenuProcess();
|
||||
Kernel::get_instance()->addProcess(menuproc);
|
||||
|
||||
ProcId creditsnotify = playCreditsNoMenu();
|
||||
|
||||
if (creditsnotify) {
|
||||
menuproc->waitFor(creditsnotify);
|
||||
}
|
||||
}
|
||||
|
||||
void CruGame::writeSaveInfo(Common::WriteStream *ws) {
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
69
engines/ultima/ultima8/games/cru_game.h
Normal file
69
engines/ultima/ultima8/games/cru_game.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_CRUGAME_H
|
||||
#define ULTIMA8_GAMES_CRUGAME_H
|
||||
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class CruGame : public Game {
|
||||
public:
|
||||
CruGame();
|
||||
~CruGame() override;
|
||||
|
||||
//! load/init game's data files
|
||||
bool loadFiles() override;
|
||||
|
||||
//! initialize new game
|
||||
bool startGame() override;
|
||||
|
||||
//! start initial usecode
|
||||
bool startInitialUsecode(int saveSlot = -1) override;
|
||||
|
||||
//! write game-specific savegame info (avatar stats, equipment, ...)
|
||||
void writeSaveInfo(Common::WriteStream *ws) override;
|
||||
|
||||
ProcId playIntroMovie(bool fade) override;
|
||||
ProcId playIntroMovie2(bool fade);
|
||||
ProcId playEndgameMovie(bool fade) override;
|
||||
void playCredits() override;
|
||||
void playQuotes() override { }; // no quotes for Crusader
|
||||
void playDemoScreen() override;
|
||||
|
||||
/** Play credits but without showing a menu at the end - just finish. */
|
||||
ProcId playCreditsNoMenu();
|
||||
|
||||
void setSkipIntroMovie() {
|
||||
_skipIntroMovie = true;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Whether this game should skip the intro movie on startup */
|
||||
bool _skipIntroMovie;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
92
engines/ultima/ultima8/games/game.cpp
Normal file
92
engines/ultima/ultima8/games/game.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/games/u8_game.h"
|
||||
#include "ultima/ultima8/games/cru_game.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/gumps/main_menu_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
Game *Game::_game = nullptr;
|
||||
|
||||
Game::Game() {
|
||||
_game = this;
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
assert(_game == this);
|
||||
_game = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Game *Game::createGame(const GameInfo *info) {
|
||||
switch (info->_type) {
|
||||
case GameInfo::GAME_U8:
|
||||
return new U8Game();
|
||||
case GameInfo::GAME_REMORSE:
|
||||
case GameInfo::GAME_REGRET:
|
||||
return new CruGame();
|
||||
default:
|
||||
error("createGame: invalid game tyoe");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 Game::I_playEndgame(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ConfMan.setBool("endgame", true);
|
||||
ConfMan.setBool("quotes", true);
|
||||
ConfMan.flushToDisk();
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
palman->untransformPalette(PaletteManager::Pal_Game);
|
||||
|
||||
Process *menuproc = new MainMenuProcess();
|
||||
Kernel::get_instance()->addProcess(menuproc);
|
||||
|
||||
ProcId moviepid = Game::get_instance()->playEndgameMovie(false);
|
||||
Process *movieproc = Kernel::get_instance()->getProcess(moviepid);
|
||||
if (movieproc) {
|
||||
menuproc->waitFor(movieproc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 Game::I_playCredits(const uint8 */*args*/, unsigned int /*argsize*/) {
|
||||
Game::get_instance()->playCredits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 Game::I_playDemoScreen(const uint8 */*args*/, unsigned int /*argsize*/) {
|
||||
Game::get_instance()->playDemoScreen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
71
engines/ultima/ultima8/games/game.h
Normal file
71
engines/ultima/ultima8/games/game.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_GAME_H
|
||||
#define ULTIMA8_GAMES_GAME_H
|
||||
|
||||
#include "ultima/ultima8/games/game_info.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Game {
|
||||
public:
|
||||
Game();
|
||||
virtual ~Game();
|
||||
|
||||
static Game *get_instance() {
|
||||
return _game;
|
||||
}
|
||||
|
||||
//! load/init game's data files
|
||||
virtual bool loadFiles() = 0;
|
||||
|
||||
//! initialize new game
|
||||
virtual bool startGame() = 0;
|
||||
|
||||
//! start initial usecode
|
||||
virtual bool startInitialUsecode(int saveSlot = -1) = 0;
|
||||
|
||||
//! write game-specific savegame info (avatar stats, equipment, ...)
|
||||
virtual void writeSaveInfo(Common::WriteStream *ws) = 0;
|
||||
|
||||
virtual ProcId playIntroMovie(bool fade) = 0;
|
||||
virtual ProcId playEndgameMovie(bool fade) = 0;
|
||||
virtual void playCredits() = 0;
|
||||
virtual void playQuotes() = 0;
|
||||
virtual void playDemoScreen() = 0;
|
||||
|
||||
static Game *createGame(const GameInfo *info);
|
||||
|
||||
INTRINSIC(I_playEndgame);
|
||||
INTRINSIC(I_playCredits);
|
||||
INTRINSIC(I_playDemoScreen);
|
||||
|
||||
protected:
|
||||
static Game *_game;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
680
engines/ultima/ultima8/games/game_data.cpp
Normal file
680
engines/ultima/ultima8/games/game_data.cpp
Normal file
@@ -0,0 +1,680 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/misc/util.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/usecode/usecode_flex.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "ultima/ultima8/world/map_glob.h"
|
||||
#include "ultima/ultima8/world/fire_type_table.h"
|
||||
#include "ultima/ultima8/world/actors/npc_dat.h"
|
||||
#include "ultima/ultima8/world/actors/combat_dat.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/wpn_ovlay_dat.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/games/game_info.h"
|
||||
#include "ultima/ultima8/gumps/weasel_dat.h"
|
||||
#include "ultima/ultima8/conf/config_file_manager.h"
|
||||
#include "ultima/ultima8/convert/crusader/convert_shape_crusader.h"
|
||||
#include "ultima/ultima8/audio/music_flex.h"
|
||||
#include "ultima/ultima8/audio/speech_flex.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
GameData *GameData::_gameData = nullptr;
|
||||
|
||||
GameData::GameData(GameInfo *gameInfo)
|
||||
: _fixed(nullptr), _mainShapes(nullptr), _mainUsecode(nullptr), _globs(),
|
||||
_fonts(nullptr), _gumps(nullptr), _mouse(nullptr), _music(nullptr),
|
||||
_weaponOverlay(nullptr), _soundFlex(nullptr), _gameInfo(gameInfo) {
|
||||
debug(1, "Creating GameData...");
|
||||
|
||||
_gameData = this;
|
||||
_speech.resize(1024);
|
||||
}
|
||||
|
||||
GameData::~GameData() {
|
||||
debug(1, "Destroying GameData...");
|
||||
|
||||
delete _fixed;
|
||||
_fixed = nullptr;
|
||||
|
||||
delete _mainShapes;
|
||||
_mainShapes = nullptr;
|
||||
|
||||
delete _mainUsecode;
|
||||
_mainUsecode = nullptr;
|
||||
|
||||
for (unsigned int i = 0; i < _globs.size(); ++i)
|
||||
delete _globs[i];
|
||||
_globs.clear();
|
||||
|
||||
delete _fonts;
|
||||
_fonts = nullptr;
|
||||
|
||||
delete _gumps;
|
||||
_gumps = nullptr;
|
||||
|
||||
delete _mouse;
|
||||
_mouse = nullptr;
|
||||
|
||||
delete _music;
|
||||
_music = nullptr;
|
||||
|
||||
delete _weaponOverlay;
|
||||
_weaponOverlay = nullptr;
|
||||
|
||||
delete _soundFlex;
|
||||
_soundFlex = nullptr;
|
||||
|
||||
for (unsigned int i = 0; i < _npcTable.size(); ++i)
|
||||
delete _npcTable[i];
|
||||
_npcTable.clear();
|
||||
|
||||
_gameData = nullptr;
|
||||
|
||||
for (unsigned int i = 0; i < _speech.size(); ++i) {
|
||||
SpeechFlex **s = _speech[i];
|
||||
if (s) delete *s;
|
||||
delete s;
|
||||
}
|
||||
_speech.clear();
|
||||
}
|
||||
|
||||
MapGlob *GameData::getGlob(uint32 glob) const {
|
||||
if (glob < _globs.size())
|
||||
return _globs[glob];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ShapeArchive *GameData::getShapeFlex(uint16 flexId) const {
|
||||
switch (flexId) {
|
||||
case MAINSHAPES:
|
||||
return _mainShapes;
|
||||
case GUMPS:
|
||||
return _gumps;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Shape *GameData::getShape(FrameID f) const {
|
||||
ShapeArchive *sf = getShapeFlex(f._flexId);
|
||||
if (!sf)
|
||||
return nullptr;
|
||||
Shape *shape = sf->getShape(f._shapeNum);
|
||||
return shape;
|
||||
}
|
||||
|
||||
const ShapeFrame *GameData::getFrame(FrameID f) const {
|
||||
const Shape *shape = getShape(f);
|
||||
if (!shape)
|
||||
return nullptr;
|
||||
const ShapeFrame *frame = shape->getFrame(f._frameNum);
|
||||
return frame;
|
||||
}
|
||||
|
||||
void GameData::loadTranslation() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
Common::Path translationfile;
|
||||
|
||||
if (_gameInfo->_type == GameInfo::GAME_U8) {
|
||||
switch (_gameInfo->_language) {
|
||||
case GameInfo::GAMELANG_ENGLISH:
|
||||
// using "translation" to enable bug fixes
|
||||
translationfile = "u8english.ini";
|
||||
break;
|
||||
case GameInfo::GAMELANG_FRENCH:
|
||||
translationfile = "u8french.ini";
|
||||
break;
|
||||
case GameInfo::GAMELANG_GERMAN:
|
||||
translationfile = "u8german.ini";
|
||||
break;
|
||||
case GameInfo::GAMELANG_SPANISH:
|
||||
translationfile = "u8spanish.ini";
|
||||
break;
|
||||
case GameInfo::GAMELANG_JAPANESE:
|
||||
translationfile = "u8japanese.ini";
|
||||
break;
|
||||
default:
|
||||
warning("Unknown language.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!translationfile.empty()) {
|
||||
debug(1, "Loading translation: %s", translationfile.toString().c_str());
|
||||
|
||||
config->readConfigFile(translationfile, "language");
|
||||
}
|
||||
}
|
||||
|
||||
Std::string GameData::translate(const Std::string &text) {
|
||||
// TODO: maybe cache these lookups? config calls may be expensive
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
Std::string trans;
|
||||
if (config->get("language", "text", text, trans)) {
|
||||
return trans;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
FrameID GameData::translate(FrameID f) {
|
||||
// TODO: maybe cache these lookups? config calls may be expensive
|
||||
// TODO: add any non-gump shapes when applicable
|
||||
// TODO: allow translations to be in another shapeflex
|
||||
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
Std::string category = "language";
|
||||
Std::string section;
|
||||
|
||||
switch (f._flexId) {
|
||||
case GUMPS:
|
||||
section = "gumps";
|
||||
break;
|
||||
default:
|
||||
return f;
|
||||
}
|
||||
|
||||
char buf[100];
|
||||
Common::sprintf_s(buf, "%d,%d", f._shapeNum, f._frameNum);
|
||||
|
||||
Std::string key = buf;
|
||||
Std::string trans;
|
||||
if (!config->get(category, section, key, trans)) {
|
||||
return f;
|
||||
}
|
||||
|
||||
FrameID t;
|
||||
t._flexId = f._flexId;
|
||||
int n = sscanf(trans.c_str(), "%u,%u", &t._shapeNum, &t._frameNum);
|
||||
if (n != 2) {
|
||||
warning("Invalid shape translation: %s", trans.c_str());
|
||||
return f;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void GameData::loadU8Data() {
|
||||
auto *fd = new Common::File();
|
||||
if (!fd->open("static/fixed.dat"))
|
||||
error("Unable to load static/fixed.dat");
|
||||
|
||||
_fixed = new RawArchive(fd);
|
||||
|
||||
char langletter = _gameInfo->getLanguageUsecodeLetter();
|
||||
if (!langletter)
|
||||
error("Unknown language. Unable to open usecode");
|
||||
|
||||
Std::string filename = "usecode/";
|
||||
filename += langletter;
|
||||
filename += "usecode.flx";
|
||||
|
||||
|
||||
auto *uds = new Common::File();
|
||||
if (!uds->open(Common::Path(filename)))
|
||||
error("Unable to load %s", filename.c_str());
|
||||
|
||||
_mainUsecode = new UsecodeFlex(uds);
|
||||
|
||||
// Load main shapes
|
||||
debug(1, "Load Shapes");
|
||||
auto *sf = new Common::File();
|
||||
if (!(sf->open("static/u8shapes.flx") || sf->open("static/u8shapes.cmp")))
|
||||
error("Unable to load static/u8shapes.flx or static/u8shapes.cmp");
|
||||
|
||||
_mainShapes = new MainShapeArchive(sf, MAINSHAPES,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
|
||||
// Load weapon, armour info
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
config->readConfigFile("u8weapons.ini", "weapons");
|
||||
config->readConfigFile("u8armour.ini", "armour");
|
||||
config->readConfigFile("u8monsters.ini", "monsters");
|
||||
config->readConfigFile("u8game.ini", "game");
|
||||
|
||||
// Load typeflags
|
||||
auto *tfs = new Common::File();
|
||||
if (!tfs->open("static/typeflag.dat"))
|
||||
error("Unable to load static/typeflag.dat");
|
||||
|
||||
_mainShapes->loadTypeFlags(tfs);
|
||||
delete tfs;
|
||||
|
||||
// Load animdat
|
||||
auto *af = new Common::File();
|
||||
if (!af->open("static/anim.dat"))
|
||||
error("Unable to load static/anim.dat");
|
||||
|
||||
_mainShapes->loadAnimDat(af);
|
||||
delete af;
|
||||
|
||||
// Load weapon overlay data
|
||||
auto *wod = new Common::File();
|
||||
if (!wod->open("static/wpnovlay.dat"))
|
||||
error("Unable to load static/wpnovlay.dat");
|
||||
|
||||
RawArchive *overlayflex = new RawArchive(wod);
|
||||
_weaponOverlay = new WpnOvlayDat();
|
||||
_weaponOverlay->load(overlayflex);
|
||||
delete overlayflex;
|
||||
|
||||
// Load _globs
|
||||
auto *gds = new Common::File();
|
||||
if (!gds->open("static/glob.flx"))
|
||||
error("Unable to load static/glob.flx");
|
||||
|
||||
RawArchive *globflex = new RawArchive(gds);
|
||||
_globs.clear();
|
||||
_globs.resize(globflex->getCount());
|
||||
for (unsigned int i = 0; i < globflex->getCount(); ++i) {
|
||||
MapGlob *glob = 0;
|
||||
Common::SeekableReadStream *globrs = globflex->get_datasource(i);
|
||||
|
||||
if (globrs && globrs->size()) {
|
||||
glob = new MapGlob();
|
||||
glob->read(globrs);
|
||||
}
|
||||
delete globrs;
|
||||
|
||||
_globs[i] = glob;
|
||||
}
|
||||
delete globflex;
|
||||
|
||||
// Load fonts
|
||||
auto *fds = new Common::File();
|
||||
if (!fds->open("static/u8fonts.flx"))
|
||||
error("Unable to load static/u8fonts.flx");
|
||||
|
||||
_fonts = new FontShapeArchive(fds, OTHER,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
_fonts->setHVLeads();
|
||||
|
||||
// Load \mouse
|
||||
auto *msds = new Common::File();
|
||||
if (!msds->open("static/u8mouse.shp"))
|
||||
error("Unable to load static/u8mouse.shp");
|
||||
|
||||
_mouse = new Shape(msds, 0);
|
||||
_mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
delete msds;
|
||||
|
||||
auto *gumpds = new Common::File();
|
||||
if (!gumpds->open("static/u8gumps.flx"))
|
||||
error("Unable to load static/u8gumps.flx");
|
||||
|
||||
_gumps = new GumpShapeArchive(gumpds, GUMPS,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
|
||||
auto *gumpageds = new Common::File();
|
||||
if (!gumpageds->open("static/gumpage.dat"))
|
||||
error("Unable to load static/gumpage.dat");
|
||||
|
||||
_gumps->loadGumpage(gumpageds);
|
||||
delete gumpageds;
|
||||
|
||||
|
||||
auto *mf = new Common::File();
|
||||
if (!mf->open("sound/music.flx"))
|
||||
error("Unable to load sound/music.flx");
|
||||
|
||||
_music = new MusicFlex(mf);
|
||||
|
||||
auto *sndflx = new Common::File();
|
||||
if (!sndflx->open("sound/sound.flx"))
|
||||
error("Unable to load sound/sound.flx");
|
||||
|
||||
_soundFlex = new SoundFlex(sndflx);
|
||||
|
||||
loadTranslation();
|
||||
}
|
||||
|
||||
void GameData::setupFontOverrides() {
|
||||
setupTTFOverrides("game", false);
|
||||
|
||||
if (_gameInfo->_language == GameInfo::GAMELANG_JAPANESE)
|
||||
setupJPOverrides();
|
||||
}
|
||||
|
||||
void GameData::setupJPOverrides() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
FontManager *fontmanager = FontManager::get_instance();
|
||||
KeyMap jpkeyvals;
|
||||
|
||||
jpkeyvals = config->listKeyValues("language", "jpfonts");
|
||||
for (const auto &i : jpkeyvals) {
|
||||
int fontnum = atoi(i._key.c_str());
|
||||
const Std::string &fontdesc = i._value;
|
||||
|
||||
Std::vector<Std::string> vals;
|
||||
SplitString(fontdesc, ',', vals);
|
||||
if (vals.size() != 2) {
|
||||
warning("Invalid jpfont override: %s", fontdesc.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int jpfontnum = atoi(vals[0].c_str());
|
||||
uint32 col32 = strtol(vals[1].c_str(), 0, 0);
|
||||
|
||||
if (!fontmanager->addJPOverride(fontnum, jpfontnum, col32)) {
|
||||
warning("failed to setup jpfont override for font %d", fontnum);
|
||||
}
|
||||
}
|
||||
|
||||
setupTTFOverrides("language", true);
|
||||
}
|
||||
|
||||
void GameData::setupTTFOverrides(const char *category, bool SJIS) {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
FontManager *fontmanager = FontManager::get_instance();
|
||||
KeyMap ttfkeyvals;
|
||||
|
||||
bool overridefonts = ConfMan.getBool("font_override");
|
||||
if (!overridefonts) return;
|
||||
|
||||
ttfkeyvals = config->listKeyValues(category, "fontoverride");
|
||||
for (const auto &i : ttfkeyvals) {
|
||||
int fontnum = atoi(i._key.c_str());
|
||||
const Std::string &fontdesc = i._value;
|
||||
|
||||
Std::vector<Std::string> vals;
|
||||
SplitString(fontdesc, ',', vals);
|
||||
if (vals.size() != 4) {
|
||||
warning("Invalid ttf override: %s", fontdesc.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
const Common::Path filename(vals[0]);
|
||||
int pointsize = atoi(vals[1].c_str());
|
||||
uint32 col32 = strtol(vals[2].c_str(), 0, 0);
|
||||
int border = atoi(vals[3].c_str());
|
||||
|
||||
if (!fontmanager->addTTFOverride(fontnum, filename, pointsize,
|
||||
col32, border, SJIS)) {
|
||||
warning("failed to setup ttf override for font %d", fontnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpeechFlex *GameData::getSpeechFlex(uint32 shapeNum) {
|
||||
if (shapeNum >= _speech.size())
|
||||
return nullptr;
|
||||
|
||||
SpeechFlex **s = _speech[shapeNum];
|
||||
if (s)
|
||||
return *s;
|
||||
|
||||
char langletter = _gameInfo->getLanguageFileLetter();
|
||||
if (!langletter) {
|
||||
warning("GameData::getSpeechFlex: Unknown language.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::Path path(Common::String::format("sound/%c%i.flx", langletter, shapeNum));
|
||||
|
||||
auto *sflx = new Common::File();
|
||||
if (!sflx->open(path)) {
|
||||
delete sflx;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
s = new SpeechFlex *;
|
||||
*s = new SpeechFlex(sflx);
|
||||
_speech[shapeNum] = s;
|
||||
|
||||
return *s;
|
||||
}
|
||||
|
||||
const NPCDat *GameData::getNPCData(uint16 entry) const {
|
||||
if (entry < _npcTable.size()) {
|
||||
return _npcTable[entry];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const NPCDat *GameData::getNPCDataForShape(uint16 shapeno) const {
|
||||
for (const auto *npcdat : _npcTable) {
|
||||
if (npcdat->getShapeNo() == shapeno)
|
||||
return npcdat;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CombatDat *GameData::getCombatDat(uint16 entry) const {
|
||||
if (entry < _combatData.size()) {
|
||||
return _combatData[entry];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const WeaselDat *GameData::getWeaselDat(uint16 entry) const {
|
||||
if (entry < _weaselData.size()) {
|
||||
return _weaselData[entry];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const FireType *GameData::getFireType(uint16 type) const {
|
||||
return FireTypeTable::get(type);
|
||||
}
|
||||
|
||||
void GameData::loadRemorseData() {
|
||||
auto *fd = new Common::File();
|
||||
if (!fd->open("static/fixed.dat"))
|
||||
error("Unable to load static/fixed.dat");
|
||||
|
||||
_fixed = new RawArchive(fd);
|
||||
|
||||
char langletter = _gameInfo->getLanguageUsecodeLetter();
|
||||
if (!langletter)
|
||||
error("Unknown language. Unable to open usecode");
|
||||
|
||||
Std::string filename = "usecode/";
|
||||
filename += langletter;
|
||||
filename += "usecode.flx";
|
||||
|
||||
auto *uds = new Common::File();
|
||||
if (!uds->open(filename.c_str()))
|
||||
error("Unable to load %s", filename.c_str());
|
||||
|
||||
_mainUsecode = new UsecodeFlex(uds);
|
||||
|
||||
// Load main shapes
|
||||
debug(1, "Load Shapes");
|
||||
auto *sf = new Common::File();
|
||||
if (!sf->open("static/shapes.flx"))
|
||||
error("Unable to load static/shapes.flx");
|
||||
|
||||
_mainShapes = new MainShapeArchive(sf, MAINSHAPES,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game),
|
||||
&CrusaderShapeFormat);
|
||||
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
// Load weapon, armour info
|
||||
if (_gameInfo->_type == GameInfo::GAME_REMORSE)
|
||||
config->readConfigFile("remorseweapons.ini", "weapons");
|
||||
else
|
||||
config->readConfigFile("regretweapons.ini", "weapons");
|
||||
|
||||
config->readConfigFile("remorsegame.ini", "game");
|
||||
|
||||
// Load typeflags
|
||||
auto *tfs = new Common::File();
|
||||
if (!tfs->open("static/typeflag.dat"))
|
||||
error("Unable to load static/typeflag.dat");
|
||||
|
||||
_mainShapes->loadTypeFlags(tfs);
|
||||
delete tfs;
|
||||
|
||||
// Load animdat
|
||||
auto *af = new Common::File();
|
||||
if (!af->open("static/anim.dat"))
|
||||
error("Unable to load static/anim.dat");
|
||||
|
||||
_mainShapes->loadAnimDat(af);
|
||||
delete af;
|
||||
|
||||
// Load weapon overlay data
|
||||
auto *wod = new Common::File();
|
||||
if (!wod->open("static/wpnovlay.dat"))
|
||||
error("Unable to load static/wpnovlay.dat");
|
||||
|
||||
RawArchive *overlayflex = new RawArchive(wod);
|
||||
_weaponOverlay = new WpnOvlayDat();
|
||||
_weaponOverlay->load(overlayflex);
|
||||
delete overlayflex;
|
||||
|
||||
// Load globs
|
||||
auto *gds = new Common::File();
|
||||
if (!gds->open("static/glob.flx"))
|
||||
error("Unable to load static/glob.flx");
|
||||
|
||||
RawArchive *globflex = new RawArchive(gds);
|
||||
_globs.clear();
|
||||
_globs.resize(globflex->getCount());
|
||||
for (unsigned int i = 0; i < globflex->getCount(); ++i) {
|
||||
MapGlob *glob = 0;
|
||||
Common::SeekableReadStream *globrs = globflex->get_datasource(i);
|
||||
|
||||
if (globrs && globrs->size()) {
|
||||
glob = new MapGlob();
|
||||
glob->read(globrs);
|
||||
}
|
||||
delete globrs;
|
||||
|
||||
_globs[i] = glob;
|
||||
}
|
||||
delete globflex;
|
||||
|
||||
// Load fonts
|
||||
auto *fds = new Common::File();
|
||||
if (!fds->open("static/fonts.flx"))
|
||||
error("Unable to load static/fonts.flx");
|
||||
|
||||
_fonts = new FontShapeArchive(fds, OTHER,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
_fonts->setHVLeads();
|
||||
|
||||
// Load mouse
|
||||
auto *msds = new Common::File();
|
||||
if (!msds->open("static/mouse.shp"))
|
||||
error("Unable to load static/mouse.shp");
|
||||
|
||||
_mouse = new Shape(msds, 0);
|
||||
_mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
delete msds;
|
||||
|
||||
auto *gumpds = new Common::File();
|
||||
if (!gumpds->open("static/gumps.flx"))
|
||||
error("Unable to load static/gumps.flx");
|
||||
|
||||
_gumps = new GumpShapeArchive(gumpds, GUMPS,
|
||||
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
||||
|
||||
auto *dtableds = new Common::File();
|
||||
if (!dtableds->open("static/dtable.flx"))
|
||||
error("Unable to load static/dtable.flx");
|
||||
|
||||
RawArchive *dtableflex = new RawArchive(dtableds);
|
||||
_npcTable = NPCDat::load(dtableflex);
|
||||
delete dtableflex;
|
||||
|
||||
auto *damageds = new Common::File();
|
||||
if (!damageds->open("static/damage.flx"))
|
||||
error("Unable to load static/damage.flx");
|
||||
|
||||
RawArchive *damageflex = new RawArchive(damageds);
|
||||
if (damageflex->getCount() != 1)
|
||||
error("static/damage.flx appears corrupted");
|
||||
|
||||
_mainShapes->loadDamageDat(damageflex->get_datasource(0));
|
||||
|
||||
delete damageflex;
|
||||
|
||||
auto *combatds = new Common::File();
|
||||
if (!combatds->open("static/combat.dat"))
|
||||
error("Unable to load static/combat.dat");
|
||||
|
||||
RawArchive *combatflex = new RawArchive(combatds);
|
||||
_combatData.clear();
|
||||
_combatData.resize(combatflex->getCount());
|
||||
for (uint32 i = 0; i < combatflex->getCount(); i++) {
|
||||
Common::SeekableReadStream *combatflexrs = combatflex->get_datasource(i);
|
||||
|
||||
if (combatflexrs && combatflexrs->size() > 20) {
|
||||
_combatData[i] = new CombatDat(*combatflexrs);
|
||||
}
|
||||
delete combatflexrs;
|
||||
}
|
||||
|
||||
delete combatflex;
|
||||
|
||||
auto *stuffds = new Common::File();
|
||||
if (!stuffds->open("static/stuff.dat"))
|
||||
error("Unable to load static/stuff.dat");
|
||||
|
||||
// Weasel shop data.
|
||||
// 14 blocks of 323 bytes, references like W01 and I07
|
||||
// (weapon and inventory)
|
||||
while (!stuffds->eos()) {
|
||||
WeaselDat *data = new WeaselDat(stuffds);
|
||||
_weaselData.push_back(data);
|
||||
}
|
||||
|
||||
delete stuffds;
|
||||
|
||||
auto *xformpalds = new Common::File();
|
||||
if (!xformpalds->open("static/xformpal.dat"))
|
||||
error("Unable to load static/xformpal.dat");
|
||||
RawArchive *xformpalflex = new RawArchive(xformpalds);
|
||||
|
||||
// TODO: What's in this flex?
|
||||
// Object 1: 32 bytes
|
||||
// Object 2: 2304 bytes - presumably data for 3 palettes == 768 * 3
|
||||
// almost no low numbers (so not raw palette data, would be missing black..)
|
||||
|
||||
delete xformpalflex;
|
||||
|
||||
// Note: No MusicFlex for Remorse, as the music is all in different AMF files.
|
||||
// The remorse_music_process will load them.
|
||||
|
||||
auto *sndflx = new Common::File();
|
||||
if (!sndflx->open("sound/sound.flx"))
|
||||
error("Unable to load sound/sound.flx");
|
||||
|
||||
_soundFlex = new SoundFlex(sndflx);
|
||||
|
||||
loadTranslation();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
146
engines/ultima/ultima8/games/game_data.h
Normal file
146
engines/ultima/ultima8/games/game_data.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_GAMEDATA_H
|
||||
#define ULTIMA8_GAMES_GAMEDATA_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/gfx/frame_id.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RawArchive;
|
||||
class MainShapeArchive;
|
||||
class FontShapeArchive;
|
||||
class GumpShapeArchive;
|
||||
class ShapeArchive;
|
||||
class Usecode;
|
||||
class MapGlob;
|
||||
class Shape;
|
||||
class MusicFlex;
|
||||
class WpnOvlayDat;
|
||||
class NPCDat;
|
||||
class CombatDat;
|
||||
class FireType;
|
||||
class ShapeFrame;
|
||||
class WeaselDat;
|
||||
class SoundFlex;
|
||||
class SpeechFlex;
|
||||
struct GameInfo;
|
||||
|
||||
class GameData {
|
||||
public:
|
||||
GameData(GameInfo *gameinfo);
|
||||
~GameData();
|
||||
|
||||
static GameData *get_instance() {
|
||||
return _gameData;
|
||||
}
|
||||
|
||||
void loadU8Data();
|
||||
void loadRemorseData();
|
||||
void setupFontOverrides();
|
||||
|
||||
Usecode *getMainUsecode() const {
|
||||
return _mainUsecode;
|
||||
}
|
||||
MainShapeArchive *getMainShapes() const {
|
||||
return _mainShapes;
|
||||
}
|
||||
RawArchive *getFixed() const {
|
||||
return _fixed;
|
||||
}
|
||||
MapGlob *getGlob(uint32 glob) const;
|
||||
FontShapeArchive *getFonts() const {
|
||||
return _fonts;
|
||||
}
|
||||
GumpShapeArchive *getGumps() const {
|
||||
return _gumps;
|
||||
}
|
||||
Shape *getMouse() const {
|
||||
return _mouse;
|
||||
}
|
||||
MusicFlex *getMusic() const {
|
||||
return _music;
|
||||
}
|
||||
WpnOvlayDat *getWeaponOverlay() const {
|
||||
return _weaponOverlay;
|
||||
}
|
||||
SoundFlex *getSoundFlex() const {
|
||||
return _soundFlex;
|
||||
}
|
||||
SpeechFlex *getSpeechFlex(uint32 shapenum);
|
||||
|
||||
ShapeArchive *getShapeFlex(uint16 flexId) const;
|
||||
Shape *getShape(FrameID frameid) const;
|
||||
const ShapeFrame *getFrame(FrameID frameid) const;
|
||||
|
||||
const NPCDat *getNPCData(uint16 entry) const;
|
||||
const NPCDat *getNPCDataForShape(uint16 shapeno) const;
|
||||
|
||||
const CombatDat *getCombatDat(uint16 entry) const;
|
||||
|
||||
const FireType *getFireType(uint16 type) const;
|
||||
|
||||
const WeaselDat *getWeaselDat(uint16 level) const;
|
||||
|
||||
Std::string translate(const Std::string &text);
|
||||
FrameID translate(FrameID frame);
|
||||
|
||||
enum ShapeFlexId {
|
||||
OTHER = 0,
|
||||
MAINSHAPES = 1,
|
||||
GUMPS = 2
|
||||
};
|
||||
private:
|
||||
void loadTranslation();
|
||||
void setupTTFOverrides(const char *category, bool SJIS);
|
||||
void setupJPOverrides();
|
||||
|
||||
RawArchive *_fixed;
|
||||
MainShapeArchive *_mainShapes;
|
||||
Usecode *_mainUsecode;
|
||||
Std::vector<MapGlob *> _globs;
|
||||
FontShapeArchive *_fonts;
|
||||
GumpShapeArchive *_gumps;
|
||||
Shape *_mouse;
|
||||
MusicFlex *_music;
|
||||
WpnOvlayDat *_weaponOverlay;
|
||||
Std::vector<NPCDat *> _npcTable;
|
||||
Std::vector<CombatDat *> _combatData;
|
||||
Std::vector<WeaselDat *> _weaselData;
|
||||
|
||||
SoundFlex *_soundFlex;
|
||||
Std::vector<SpeechFlex **> _speech;
|
||||
GameInfo *_gameInfo;
|
||||
|
||||
static GameData *_gameData;
|
||||
};
|
||||
|
||||
#define _TL_(x) (GameData::get_instance()->translate(x))
|
||||
#define _TL_SHP_(x) (GameData::get_instance()->translate(x))
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
225
engines/ultima/ultima8/games/game_info.cpp
Normal file
225
engines/ultima/ultima8/games/game_info.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_info.h"
|
||||
#include "ultima/ultima8/misc/util.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
struct GameTypeDesc {
|
||||
const char *shortname;
|
||||
const char *longname;
|
||||
};
|
||||
struct GameLangDesc {
|
||||
char letter;
|
||||
char usecodeletter;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
// Keep order the same as the GameType enum!
|
||||
static const GameTypeDesc gametypes[] = {
|
||||
{ "", "" },
|
||||
{ "ultima8", "Ultima VIII: Pagan" },
|
||||
{ "remorse", "Crusader: No Remorse" },
|
||||
{ "regret", "Crusader: No Regret" },
|
||||
{ "pentmenu", "Pentagram Menu" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
// Keep order the same as the GameLanguage enum!
|
||||
static const GameLangDesc gamelangs[] = {
|
||||
{ 0, 0, "unknown" },
|
||||
{ 'e', 'e', "English" },
|
||||
{ 'f', 'f', "French" },
|
||||
{ 'g', 'g', "German" },
|
||||
{ 'e', 'e', "Spanish" },
|
||||
{ 'e', 'j', "Japanese" },
|
||||
{ '\0', '\0', 0 }
|
||||
};
|
||||
|
||||
|
||||
GameInfo::GameInfo() : _type(GAME_UNKNOWN), version(0), _language(GAMELANG_UNKNOWN),
|
||||
_ucOffVariant(GAME_UC_DEFAULT) {
|
||||
for (int i = 0; i < 16; ++i)
|
||||
_md5[i] = 0;
|
||||
}
|
||||
|
||||
char GameInfo::getLanguageFileLetter() const {
|
||||
switch (_type) {
|
||||
case GAME_U8: {
|
||||
unsigned int l = static_cast<unsigned int>(_language);
|
||||
assert(l < (sizeof(gamelangs) / sizeof(gamelangs[0])) - 1);
|
||||
|
||||
return gamelangs[l].letter;
|
||||
}
|
||||
case GAME_REMORSE:
|
||||
case GAME_REGRET:
|
||||
return 'e';
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char GameInfo::getLanguageUsecodeLetter() const {
|
||||
switch (_type) {
|
||||
case GAME_U8: {
|
||||
unsigned int l = static_cast<unsigned int>(_language);
|
||||
assert(l < (sizeof(gamelangs) / sizeof(gamelangs[0])) - 1);
|
||||
|
||||
return gamelangs[l].usecodeletter;
|
||||
}
|
||||
case GAME_REMORSE:
|
||||
case GAME_REGRET:
|
||||
return 'e';
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Std::string GameInfo::getLanguage() const {
|
||||
unsigned int l = static_cast<unsigned int>(_language);
|
||||
assert(l < (sizeof(gamelangs) / sizeof(gamelangs[0])) - 1);
|
||||
|
||||
return gamelangs[l].name;
|
||||
}
|
||||
|
||||
Std::string GameInfo::getGameTitle() const {
|
||||
unsigned int t = static_cast<unsigned int>(_type);
|
||||
assert(t < (sizeof(gametypes) / sizeof(gametypes[0])) - 1);
|
||||
|
||||
return gametypes[t].longname;
|
||||
}
|
||||
|
||||
Std::string GameInfo::getPrintableVersion() const {
|
||||
char buf[32];
|
||||
Common::sprintf_s(buf, "%d.%02d", version / 100, version % 100);
|
||||
return buf;
|
||||
}
|
||||
|
||||
Std::string GameInfo::getPrintDetails() const {
|
||||
Std::string ret;
|
||||
|
||||
Std::string title = getGameTitle();
|
||||
if (title == "") title = "Unknown";
|
||||
|
||||
ret = title + ", ";
|
||||
|
||||
Std::string lang = getLanguage();
|
||||
if (lang == "") lang = "Unknown";
|
||||
ret += lang;
|
||||
|
||||
ret += ", version ";
|
||||
ret += getPrintableVersion();
|
||||
|
||||
ret += ", md5 ";
|
||||
ret += getPrintableMD5();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Std::string GameInfo::getPrintableMD5() const {
|
||||
Std::string ret;
|
||||
|
||||
char buf[33];
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
Common::sprintf_s(buf + 2 * i, 3, "%02x", _md5[i]);
|
||||
}
|
||||
|
||||
ret = buf;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GameInfo::match(GameInfo &other, bool ignoreMD5) const {
|
||||
if (_type != other._type) return false;
|
||||
if (_language != other._language) return false;
|
||||
if (ignoreMD5) return true;
|
||||
|
||||
// NOTE: Version and MD5 hash are not currently set
|
||||
if (version != other.version) return false;
|
||||
return (memcmp(_md5, other._md5, 16) == 0);
|
||||
}
|
||||
|
||||
void GameInfo::save(Common::WriteStream *ws) {
|
||||
unsigned int l = static_cast<unsigned int>(_language);
|
||||
assert(l < (sizeof(gamelangs) / sizeof(gamelangs[0])) - 1);
|
||||
unsigned int t = static_cast<unsigned int>(_type);
|
||||
assert(t < (sizeof(gametypes) / sizeof(gametypes[0])) - 1);
|
||||
|
||||
Std::string game = gametypes[t].shortname;
|
||||
Std::string lang = gamelangs[l].name;
|
||||
|
||||
char buf[16];
|
||||
Common::sprintf_s(buf, "%d", version);
|
||||
Std::string ver = buf;
|
||||
Std::string md5Str = getPrintableMD5();
|
||||
|
||||
Std::string d = game + "," + lang + "," + ver + "," + md5Str + "\n";
|
||||
ws->write(d.c_str(), d.size());
|
||||
}
|
||||
|
||||
bool GameInfo::load(Common::SeekableReadStream *rs, uint32 ver) {
|
||||
Std::string s;
|
||||
Std::vector<Std::string> parts;
|
||||
|
||||
s = rs->readLine();
|
||||
SplitString(s, ',', parts);
|
||||
if (parts.size() != 4) return false;
|
||||
|
||||
int i = 0;
|
||||
while (gametypes[i].shortname) {
|
||||
if (parts[0] == gametypes[i].shortname) {
|
||||
_type = static_cast<GameType>(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!gametypes[i].shortname) return false;
|
||||
|
||||
i = 0;
|
||||
while (gamelangs[i].name) {
|
||||
if (parts[1] == gamelangs[i].name) {
|
||||
_language = static_cast<GameLanguage>(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!gamelangs[i].name) return false;
|
||||
|
||||
this->version = strtol(parts[2].c_str(), 0, 0);
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
char buf[3];
|
||||
buf[0] = parts[3][2 * i];
|
||||
buf[1] = parts[3][2 * i + 1];
|
||||
buf[2] = 0;
|
||||
long x = strtol(buf, 0, 16);
|
||||
_md5[i] = static_cast<uint8>(x);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
90
engines/ultima/ultima8/games/game_info.h
Normal file
90
engines/ultima/ultima8/games/game_info.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_GAMEINFO_H
|
||||
#define ULTIMA8_GAMES_GAMEINFO_H
|
||||
|
||||
#include "ultima/shared/std/string.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class IDataSource;
|
||||
|
||||
//! GameInfo contains detailed information about the game
|
||||
struct GameInfo {
|
||||
GameInfo();
|
||||
|
||||
Std::string _name;
|
||||
|
||||
enum GameType {
|
||||
GAME_UNKNOWN = 0,
|
||||
GAME_U8,
|
||||
GAME_REMORSE,
|
||||
GAME_REGRET
|
||||
} _type;
|
||||
|
||||
// Usecode coff variant
|
||||
enum GameUsecodeOffsetVariant {
|
||||
GAME_UC_DEFAULT, // Most versions of most games
|
||||
GAME_UC_ORIG, // Original (pre-patch) CD versions of Crusader games
|
||||
GAME_UC_DEMO, // Crusader: No Remorse or No Regret Demos
|
||||
GAME_UC_REM_ES, // Crusader: No Remorse Spanish
|
||||
GAME_UC_REM_FR, // Crusader: No Remorse French
|
||||
GAME_UC_REM_JA, // Crusader: No Remorse Japanese
|
||||
GAME_UC_REG_DE // Crusader: No Regret German
|
||||
} _ucOffVariant;
|
||||
|
||||
//! version number, encoded as 100*major + minor
|
||||
//! so, 2.12 becomes 212
|
||||
//! 0 = unknown
|
||||
int version;
|
||||
|
||||
enum GameLanguage {
|
||||
GAMELANG_UNKNOWN = 0,
|
||||
GAMELANG_ENGLISH,
|
||||
GAMELANG_FRENCH,
|
||||
GAMELANG_GERMAN,
|
||||
GAMELANG_SPANISH,
|
||||
GAMELANG_JAPANESE
|
||||
} _language;
|
||||
|
||||
uint8 _md5[16];
|
||||
|
||||
char getLanguageFileLetter() const;
|
||||
char getLanguageUsecodeLetter() const;
|
||||
Std::string getLanguage() const;
|
||||
Std::string getGameTitle() const;
|
||||
Std::string getPrintableVersion() const;
|
||||
|
||||
Std::string getPrintDetails() const;
|
||||
Std::string getPrintableMD5() const;
|
||||
|
||||
bool match(GameInfo &other, bool ignoreMD5 = false) const;
|
||||
|
||||
void save(Common::WriteStream *ws);
|
||||
bool load(Common::SeekableReadStream *rs, uint32 /* version */);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
162
engines/ultima/ultima8/games/start_crusader_process.cpp
Normal file
162
engines/ultima/ultima8/games/start_crusader_process.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "ultima/ultima8/games/start_crusader_process.h"
|
||||
#include "ultima/ultima8/games/cru_game.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/gumps/difficulty_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_status_gump.h"
|
||||
#include "ultima/ultima8/gumps/cru_pickup_area_gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
#include "ultima/ultima8/world/actors/teleport_to_egg_process.h"
|
||||
#include "ultima/ultima8/gfx/palette_fader_process.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(StartCrusaderProcess)
|
||||
|
||||
StartCrusaderProcess::StartCrusaderProcess(int saveSlot) : Process(),
|
||||
_initStage(PlayFirstMovie), _saveSlot(saveSlot) {
|
||||
_flags |= PROC_PREVENT_SAVE;
|
||||
}
|
||||
|
||||
|
||||
void StartCrusaderProcess::run() {
|
||||
if (_initStage == PlayFirstMovie) {
|
||||
_initStage = PlaySecondMovie;
|
||||
ProcId moviepid = Game::get_instance()->playIntroMovie(false);
|
||||
Process *movieproc = Kernel::get_instance()->getProcess(moviepid);
|
||||
if (movieproc) {
|
||||
waitFor(movieproc);
|
||||
}
|
||||
return;
|
||||
} else if (_initStage == PlaySecondMovie) {
|
||||
_initStage = ShowDifficultyMenu;
|
||||
CruGame *game = dynamic_cast<CruGame *>(Game::get_instance());
|
||||
assert(game);
|
||||
ProcId moviepid = game->playIntroMovie2(false);
|
||||
Process *movieproc = Kernel::get_instance()->getProcess(moviepid);
|
||||
if (movieproc) {
|
||||
waitFor(movieproc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to load the save game, if succeeded this process will terminate
|
||||
if (_saveSlot >= 0) {
|
||||
Common::Error loadError = Ultima8Engine::get_instance()->loadGameState(_saveSlot);
|
||||
if (loadError.getCode() != Common::kNoError) {
|
||||
Ultima8Engine::get_instance()->setError(loadError);
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_initStage == ShowDifficultyMenu) {
|
||||
DifficultyGump *gump = new DifficultyGump();
|
||||
_initStage = StartGame;
|
||||
gump->InitGump(nullptr, true);
|
||||
return;
|
||||
}
|
||||
|
||||
Gump *statusGump = new CruStatusGump(true);
|
||||
statusGump->InitGump(nullptr, false);
|
||||
|
||||
Gump *cruPickupAreaGump = new CruPickupAreaGump(true);
|
||||
cruPickupAreaGump->InitGump(nullptr, false);
|
||||
|
||||
MainActor *avatar = getMainActor();
|
||||
int mapnum = avatar->getMapNum();
|
||||
|
||||
// These items are the same in Regret and Remorse
|
||||
Item *datalink = ItemFactory::createItem(0x4d4, 0, 0, 0, 0, mapnum, 0, true);
|
||||
avatar->addItemCru(datalink, false);
|
||||
Item *smiley = ItemFactory::createItem(0x598, 0, 0, 0, 0, mapnum, 0, true);
|
||||
smiley->moveToContainer(avatar);
|
||||
|
||||
avatar->setShieldType(1);
|
||||
|
||||
#if 0
|
||||
// Give the avatar *all the weapons and ammo*.. (handy for testing)
|
||||
|
||||
Ultima8Engine::get_instance()->setCheatMode(true);
|
||||
|
||||
static const uint32 wpnshapes[] = {
|
||||
// Weapons
|
||||
0x032E, 0x032F, 0x0330, 0x038C, 0x0332, 0x0333, 0x0334,
|
||||
0x038E, 0x0388, 0x038A, 0x038D, 0x038B, 0x0386,
|
||||
// Ammo
|
||||
0x033D, 0x033E, 0x033F, 0x0340, 0x0341,
|
||||
// No Regret Weapons
|
||||
0x5F6, 0x5F5, 0x198,
|
||||
// No Regret Ammo
|
||||
0x615, 0x614
|
||||
};
|
||||
for (int i = 0; i < ARRAYSIZE(wpnshapes); i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
Item *wpn = ItemFactory::createItem(wpnshapes[i], 0, 0, 0, 0, mapnum, 0, true);
|
||||
avatar->addItemCru(wpn, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
avatar->teleport(1, 0x1e);
|
||||
// The first level 0x1e teleporter in No Remorse goes straight to another
|
||||
// teleport, so undo the flag that normally stops that.
|
||||
avatar->setJustTeleported(false);
|
||||
|
||||
if (GAME_IS_REGRET) {
|
||||
avatar->setInCombat(0);
|
||||
avatar->setDir(dir_south);
|
||||
avatar->setActorFlag(Actor::ACT_WEAPONREADY);
|
||||
}
|
||||
|
||||
Process *fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0xFF, 0xFF, 0xFF, 0x00), true, 0x7FFF, 60, false);
|
||||
Kernel::get_instance()->addProcess(fader);
|
||||
|
||||
Ultima8Engine::get_instance()->setAvatarInStasis(false);
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
void StartCrusaderProcess::saveData(Common::WriteStream *ws) {
|
||||
warning("Attempted save of process with prevent save flag");
|
||||
|
||||
Process::saveData(ws);
|
||||
}
|
||||
|
||||
bool StartCrusaderProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
60
engines/ultima/ultima8/games/start_crusader_process.h
Normal file
60
engines/ultima/ultima8/games/start_crusader_process.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_STARTCRUSADERPROCESS_H
|
||||
#define ULTIMA8_GAMES_STARTCRUSADERPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Item;
|
||||
|
||||
class StartCrusaderProcess : public Process {
|
||||
public:
|
||||
enum CruInitStage {
|
||||
PlayFirstMovie,
|
||||
PlaySecondMovie,
|
||||
ShowDifficultyMenu,
|
||||
StartGame
|
||||
};
|
||||
|
||||
protected:
|
||||
CruInitStage _initStage;
|
||||
int _saveSlot;
|
||||
|
||||
public:
|
||||
StartCrusaderProcess(int saveSlot);
|
||||
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
void run() override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
130
engines/ultima/ultima8/games/start_u8_process.cpp
Normal file
130
engines/ultima/ultima8/games/start_u8_process.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "ultima/ultima8/games/start_u8_process.h"
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
#include "ultima/ultima8/world/loop_script.h"
|
||||
#include "ultima/ultima8/usecode/uc_list.h"
|
||||
#include "ultima/ultima8/world/current_map.h"
|
||||
#include "ultima/ultima8/world/egg.h"
|
||||
#include "ultima/ultima8/world/camera_process.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/gumps/menu_gump.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/gfx/palette_fader_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(StartU8Process)
|
||||
|
||||
StartU8Process::StartU8Process(int saveSlot) : Process(),
|
||||
_init(false), _saveSlot(saveSlot), _skipStart(saveSlot >= 0) {
|
||||
_flags |= PROC_PREVENT_SAVE;
|
||||
}
|
||||
|
||||
|
||||
void StartU8Process::run() {
|
||||
if (!_skipStart && !_init) {
|
||||
_init = true;
|
||||
ProcId moviepid = Game::get_instance()->playIntroMovie(false);
|
||||
Process *movieproc = Kernel::get_instance()->getProcess(moviepid);
|
||||
if (movieproc) {
|
||||
waitFor(movieproc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load the save game, if succeeded this process will terminate
|
||||
if (_saveSlot >= 0) {
|
||||
Common::Error loadError = Ultima8Engine::get_instance()->loadGameState(_saveSlot);
|
||||
if (loadError.getCode() != Common::kNoError) {
|
||||
Ultima8Engine::get_instance()->setError(loadError);
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteFaderProcess::I_fadeFromBlack(0, 0);
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentMap *currentmap = World::get_instance()->getCurrentMap();
|
||||
UCList uclist(2);
|
||||
|
||||
if (!_skipStart) {
|
||||
LOOPSCRIPT(script, LS_AND(LS_SHAPE_EQUAL1(73), LS_Q_EQUAL(36)));
|
||||
currentmap->areaSearch(&uclist, script, sizeof(script),
|
||||
0, 256, false, 16188, 7500);
|
||||
if (uclist.getSize() < 1) {
|
||||
warning("Unable to find FIRST egg");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 objid = uclist.getuint16(0);
|
||||
Egg *egg = dynamic_cast<Egg *>(getObject(objid));
|
||||
Point3 pt = egg->getLocation();
|
||||
// Center on egg
|
||||
CameraProcess::SetCameraProcess(new CameraProcess(pt));
|
||||
egg->hatch();
|
||||
}
|
||||
|
||||
// Music Egg
|
||||
// Item 2145 (class Item, shape 562, 0, (11551,2079,48) q:52, m:0, n:0, f:2000, ef:2)
|
||||
uclist.free();
|
||||
LOOPSCRIPT(musicscript, LS_SHAPE_EQUAL1(562));
|
||||
currentmap->areaSearch(&uclist, musicscript, sizeof(musicscript),
|
||||
0, 256, false, 11551, 2079);
|
||||
|
||||
if (uclist.getSize() < 1) {
|
||||
warning("Unable to find MUSIC egg");
|
||||
} else {
|
||||
ObjId objid = uclist.getuint16(0);
|
||||
Item *musicEgg = getItem(objid);
|
||||
musicEgg->callUsecodeEvent_cachein();
|
||||
}
|
||||
|
||||
if (!_skipStart)
|
||||
MenuGump::inputName();
|
||||
else
|
||||
Ultima8Engine::get_instance()->setAvatarInStasis(false);
|
||||
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
void StartU8Process::saveData(Common::WriteStream *ws) {
|
||||
warning("Attempted save of process with prevent save flag");
|
||||
|
||||
Process::saveData(ws);
|
||||
}
|
||||
|
||||
bool StartU8Process::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
53
engines/ultima/ultima8/games/start_u8_process.h
Normal file
53
engines/ultima/ultima8/games/start_u8_process.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_STARTU8PROCESS_H
|
||||
#define ULTIMA8_GAMES_STARTU8PROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Item;
|
||||
|
||||
class StartU8Process : public Process {
|
||||
protected:
|
||||
bool _init;
|
||||
bool _skipStart;
|
||||
int _saveSlot;
|
||||
|
||||
public:
|
||||
StartU8Process(int saveSlot = -1);
|
||||
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
void run() override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
233
engines/ultima/ultima8/games/treasure_loader.cpp
Normal file
233
engines/ultima/ultima8/games/treasure_loader.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/games/treasure_loader.h"
|
||||
|
||||
#include "ultima/ultima8/conf/config_file_manager.h"
|
||||
#include "ultima/ultima8/misc/util.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
TreasureLoader::TreasureLoader() {
|
||||
}
|
||||
|
||||
TreasureLoader::~TreasureLoader() {
|
||||
}
|
||||
|
||||
void TreasureLoader::loadDefaults() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
KeyMap lootkeyvals;
|
||||
|
||||
// load default treasure types
|
||||
lootkeyvals = config->listKeyValues("game", "treasure");
|
||||
for (const auto &i : lootkeyvals) {
|
||||
TreasureInfo ti;
|
||||
bool ok = internalParse(i._value, ti, true);
|
||||
if (ok) {
|
||||
_defaultTreasure[i._key] = ti;
|
||||
} else {
|
||||
warning("Failed to parse treasure type '%s': %s", i._key.c_str(), i._value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TreasureLoader::parse(const Std::string &desc,
|
||||
Std::vector<TreasureInfo> &treasure) const {
|
||||
treasure.clear();
|
||||
|
||||
Std::vector<Std::string> tr;
|
||||
SplitString(desc, ';', tr);
|
||||
|
||||
TreasureInfo ti;
|
||||
for (unsigned int i = 0; i < tr.size(); ++i) {
|
||||
if (internalParse(tr[i], ti, false)) {
|
||||
treasure.push_back(ti);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreasureLoader::internalParse(const Std::string &desc, TreasureInfo &ti,
|
||||
bool loadingDefault) const {
|
||||
ti.clear();
|
||||
bool loadedDefault = false;
|
||||
|
||||
Std::vector<Common::Pair<Std::string, Std::string> > kv;
|
||||
SplitStringKV(desc, ' ', kv);
|
||||
|
||||
for (unsigned int i = 0; i < kv.size(); ++i) {
|
||||
const Std::string &key = kv[i].first;
|
||||
Std::string val = kv[i].second;
|
||||
|
||||
if (key == "shape") {
|
||||
if (!parseUInt32Vector(val, ti._shapes)) {
|
||||
warning("Failed to parse treasure shape list '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
// validate the shapes are > 0 and < max shape
|
||||
for (unsigned int j = 0; j < ti._shapes.size(); j++) {
|
||||
if (ti._shapes[j] <= 0 || ti._shapes[j] > 65535) {
|
||||
warning("Invalid treasure shape in list '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (key == "frame") {
|
||||
if (!parseUInt32Vector(val, ti._frames)) {
|
||||
warning("Failed to parse treasure frame list '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
// validate the frames are < max frame (0 frame is valid)
|
||||
for (unsigned int j = 0; j < ti._frames.size(); j++) {
|
||||
if (ti._frames[j] > 65535) {
|
||||
warning("Invalid treasure frame in list '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (key == "count") {
|
||||
if (!parseUIntRange(val, ti._minCount, ti._maxCount)) {
|
||||
int x;
|
||||
if (!parseInt(val, x) || x <= 0) {
|
||||
warning("Invalid treasure count '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
ti._minCount = ti._maxCount = x;
|
||||
}
|
||||
} else if (key == "chance") {
|
||||
if (!parseDouble(val, ti._chance) || ti._chance <= 0) {
|
||||
warning("Invalid treasure chance '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
} else if (key == "map") {
|
||||
if (val.size() > 1 && val[0] == '!')
|
||||
val[0] = '-'; // HACK: invert map for 'not this map'
|
||||
if (!parseInt(val, ti._map))
|
||||
return false;
|
||||
} else if (key == "special" && loadingDefault) {
|
||||
ti._special = val;
|
||||
} else if (key == "type" && !loadingDefault) {
|
||||
if (loadedDefault)
|
||||
return false;
|
||||
TreasureMap::const_iterator iter;
|
||||
iter = _defaultTreasure.find(val);
|
||||
if (iter != _defaultTreasure.end())
|
||||
ti = iter->_value;
|
||||
else
|
||||
return false;
|
||||
loadedDefault = true;
|
||||
} else if (key == "mult" && !loadingDefault) {
|
||||
if (!loadedDefault) {
|
||||
warning("Need defaults before applying multiplier in treasure data '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
unsigned int minmult, maxmult;
|
||||
if (!parseUIntRange(val, minmult, maxmult)) {
|
||||
int x;
|
||||
if (!parseInt(val, x) || x <= 0) {
|
||||
warning("Invalid treasure multiplier '%s'", val.c_str());
|
||||
return false;
|
||||
}
|
||||
minmult = maxmult = x;
|
||||
}
|
||||
ti._minCount *= minmult;
|
||||
ti._maxCount *= maxmult;
|
||||
} else {
|
||||
warning("Unknown key parsing treasure '%s'", key.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreasureLoader::parseUInt32Vector(const Std::string &val_,
|
||||
Std::vector<uint32> &vec) const {
|
||||
Std::string val = val_;
|
||||
vec.clear();
|
||||
|
||||
if (val.empty())
|
||||
return false;
|
||||
|
||||
while (!val.empty()) {
|
||||
Std::string::size_type pos = val.find(',');
|
||||
const Std::string item = val.substr(0, pos);
|
||||
|
||||
Std::string::size_type itempos = val.find('-');
|
||||
if (itempos != Std::string::npos) {
|
||||
unsigned int min, max;
|
||||
if (!parseUIntRange(item, min, max))
|
||||
return false;
|
||||
for (unsigned int i = min; i <= max; ++i)
|
||||
vec.push_back(i);
|
||||
} else {
|
||||
int x;
|
||||
if (!parseInt(item, x) || x < 0)
|
||||
return false;
|
||||
vec.push_back(x);
|
||||
}
|
||||
|
||||
if (pos != Std::string::npos) pos++;
|
||||
val.erase(0, pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreasureLoader::parseUIntRange(const Std::string &val,
|
||||
unsigned int &min, unsigned int &max) const {
|
||||
Std::string::size_type pos = val.find('-');
|
||||
if (pos == 0 || pos == Std::string::npos || pos + 1 >= val.size())
|
||||
return false;
|
||||
int t1 = 0;
|
||||
int t2 = 0;
|
||||
bool ok = true;
|
||||
ok = ok && parseInt(val.substr(0, pos), t1);
|
||||
ok = ok && parseInt(val.substr(pos + 1), t2);
|
||||
ok = ok && (t1 <= t2 && t1 >= 0 && t2 >= 0);
|
||||
if (ok) {
|
||||
min = t1;
|
||||
max = t2;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TreasureLoader::parseDouble(const Std::string &val, double &d) const {
|
||||
if (val.empty())
|
||||
return false;
|
||||
// TODO: error checking
|
||||
d = atof(val.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreasureLoader::parseInt(const Std::string &val, int &i) const {
|
||||
if (val.empty())
|
||||
return false;
|
||||
// TODO: error checking
|
||||
i = strtol(val.c_str(), 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
58
engines/ultima/ultima8/games/treasure_loader.h
Normal file
58
engines/ultima/ultima8/games/treasure_loader.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_TREASURELOADER_H
|
||||
#define ULTIMA8_GAMES_TREASURELOADER_H
|
||||
|
||||
#include "ultima/ultima8/world/actors/treasure_info.h"
|
||||
#include "ultima/shared/std/containers.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
typedef Common::HashMap<Std::string, TreasureInfo, Common::IgnoreCase_Hash> TreasureMap;
|
||||
|
||||
class TreasureLoader {
|
||||
public:
|
||||
TreasureLoader();
|
||||
~TreasureLoader();
|
||||
|
||||
//! load defaults from 'game' ini section
|
||||
void loadDefaults();
|
||||
|
||||
//! parse treasure string into vector of TreasureInfo objects
|
||||
bool parse(const Std::string &, Std::vector<TreasureInfo> &treasure) const;
|
||||
|
||||
private:
|
||||
TreasureMap _defaultTreasure;
|
||||
|
||||
bool internalParse(const Std::string &desc, TreasureInfo &ti, bool loadingDefault) const;
|
||||
|
||||
bool parseUInt32Vector(const Std::string &val, Std::vector<uint32> &vec) const;
|
||||
bool parseUIntRange(const Std::string &val, unsigned int &min, unsigned int &max) const;
|
||||
bool parseDouble(const Std::string &val, double &d) const;
|
||||
bool parseInt(const Std::string &val, int &i) const;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
316
engines/ultima/ultima8/games/u8_game.cpp
Normal file
316
engines/ultima/ultima8/games/u8_game.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "gui/error.h"
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/games/u8_game.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/fade_to_modal_process.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/xform_blend.h"
|
||||
#include "ultima/ultima8/filesys/u8_save_file.h"
|
||||
#include "ultima/ultima8/world/world.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/world/item_factory.h"
|
||||
#include "ultima/ultima8/kernel/object_manager.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/gumps/movie_gump.h"
|
||||
#include "ultima/ultima8/gumps/credits_gump.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/games/start_u8_process.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
U8Game::U8Game() : Game() {
|
||||
// Set some defaults for gameplay-related settings
|
||||
ConfMan.registerDefault("endgame", false);
|
||||
ConfMan.registerDefault("quotes", false);
|
||||
ConfMan.registerDefault("footsteps", true);
|
||||
ConfMan.registerDefault("targetedjump", true);
|
||||
ConfMan.registerDefault("subtitles", true);
|
||||
ConfMan.registerDefault("speech_mute", false);
|
||||
|
||||
const GameInfo *info = Ultima8Engine::get_instance()->getGameInfo();
|
||||
if (info->_language == GameInfo::GAMELANG_JAPANESE) {
|
||||
ConfMan.registerDefault("talkspeed", 24);
|
||||
} else {
|
||||
ConfMan.registerDefault("talkspeed", 60);
|
||||
}
|
||||
}
|
||||
|
||||
U8Game::~U8Game() {
|
||||
}
|
||||
|
||||
bool U8Game::loadFiles() {
|
||||
// Load palette
|
||||
debug(1, "Load Palette");
|
||||
Common::File pf;
|
||||
if (!pf.open("static/u8pal.pal")) {
|
||||
warning("Unable to load static/u8pal.pal.");
|
||||
return false;
|
||||
}
|
||||
pf.seek(4); // seek past header
|
||||
|
||||
Common::MemoryReadStream xfds(U8XFormPal, 1024);
|
||||
PaletteManager::get_instance()->load(PaletteManager::Pal_Game, pf, xfds);
|
||||
|
||||
debug(1, "Load GameData");
|
||||
GameData::get_instance()->loadU8Data();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool U8Game::startGame() {
|
||||
// NOTE: assumes the entire engine has been reset!
|
||||
debug(1, "Starting new Ultima 8 game.");
|
||||
|
||||
ObjectManager *objman = ObjectManager::get_instance();
|
||||
|
||||
// reserve a number of objids just in case we'll need them sometime
|
||||
for (uint16 i = 384; i < 512; ++i)
|
||||
objman->reserveObjId(i);
|
||||
|
||||
// Reserved for the Guardian Bark hack
|
||||
objman->reserveObjId(kGuardianId);
|
||||
|
||||
auto *savers = new Common::File();
|
||||
if (!savers->open("savegame/u8save.000")) {
|
||||
Common::U32String errmsg = _(
|
||||
"Missing Required File\n\n"
|
||||
"Starting a game requires SAVEGAME/U8SAVE.000\n"
|
||||
"from an original installation.\n\n"
|
||||
"Please check you have copied all the files correctly.");
|
||||
::GUI::displayErrorDialog(errmsg);
|
||||
delete savers;
|
||||
error("Unable to load savegame/u8save.000");
|
||||
return false;
|
||||
}
|
||||
U8SaveFile *u8save = new U8SaveFile(savers);
|
||||
|
||||
Common::SeekableReadStream *nfd = u8save->createReadStreamForMember("NONFIXED.DAT");
|
||||
if (!nfd) {
|
||||
warning("Unable to load savegame/u8save.000/NONFIXED.DAT.");
|
||||
return false;
|
||||
}
|
||||
World::get_instance()->loadNonFixed(nfd); // deletes nfd
|
||||
|
||||
Common::SeekableReadStream *icd = u8save->createReadStreamForMember("ITEMCACH.DAT");
|
||||
if (!icd) {
|
||||
warning("Unable to load savegame/u8save.000/ITEMCACH.DAT.");
|
||||
return false;
|
||||
}
|
||||
Common::SeekableReadStream *npcd = u8save->createReadStreamForMember("NPCDATA.DAT");
|
||||
if (!npcd) {
|
||||
warning("Unable to load savegame/u8save.000/NPCDATA.DAT.");
|
||||
delete icd;
|
||||
return false;
|
||||
}
|
||||
|
||||
World::get_instance()->loadItemCachNPCData(icd, npcd); // deletes icd, npcd
|
||||
delete u8save;
|
||||
|
||||
MainActor *av = getMainActor();
|
||||
assert(av);
|
||||
|
||||
av->setName("Avatar"); // default name
|
||||
|
||||
// avatar needs a backpack ... CONSTANTs and all that
|
||||
Item *backpack = ItemFactory::createItem(529, 0, 0, 0, 0, 0, 0, true);
|
||||
backpack->moveToContainer(av);
|
||||
|
||||
World::get_instance()->switchMap(av->getMapNum());
|
||||
|
||||
Ultima8Engine::get_instance()->setAvatarInStasis(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool U8Game::startInitialUsecode(int saveSlot) {
|
||||
Process *proc = new StartU8Process(saveSlot);
|
||||
Kernel::get_instance()->addProcess(proc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ProcId U8Game::playIntroMovie(bool fade) {
|
||||
const GameInfo *gameinfo = Ultima8Engine::get_instance()->getGameInfo();
|
||||
char langletter = gameinfo->getLanguageFileLetter();
|
||||
if (!langletter) {
|
||||
warning("U8Game::playIntro: Unknown language.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::String filename = "static/";
|
||||
filename += langletter;
|
||||
filename += "intro.skf";
|
||||
|
||||
auto *skf = new Common::File();
|
||||
if (!skf->open(filename.c_str())) {
|
||||
debug(1, "U8Game::playIntro: movie not found.");
|
||||
delete skf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MovieGump::U8MovieViewer(skf, fade, true, true);
|
||||
}
|
||||
|
||||
ProcId U8Game::playEndgameMovie(bool fade) {
|
||||
static const Common::Path filename = "static/endgame.skf";
|
||||
auto *skf = new Common::File();
|
||||
if (!skf->open(filename)) {
|
||||
debug(1, "U8Game::playEndgame: movie not found.");
|
||||
delete skf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MovieGump::U8MovieViewer(skf, fade, false, true);
|
||||
}
|
||||
|
||||
void U8Game::playCredits() {
|
||||
const GameInfo *gameinfo = Ultima8Engine::get_instance()->getGameInfo();
|
||||
char langletter = gameinfo->getLanguageFileLetter();
|
||||
if (!langletter) {
|
||||
warning("U8Game::playCredits: Unknown language.");
|
||||
return;
|
||||
}
|
||||
|
||||
Common::String filename = "static/";
|
||||
filename += langletter;
|
||||
filename += "credits.dat";
|
||||
|
||||
auto *rs = new Common::File();
|
||||
if (!rs->open(filename.c_str())) {
|
||||
warning("U8Game::playCredits: error opening credits file: %s", filename.c_str());
|
||||
delete rs;
|
||||
return;
|
||||
}
|
||||
Std::string text = getCreditText(rs);
|
||||
delete rs;
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) musicproc->playMusic(51); // CONSTANT!
|
||||
|
||||
CreditsGump *gump = new CreditsGump(text);
|
||||
gump->SetFlagWhenFinished("quotes");
|
||||
FadeToModalProcess *p = new FadeToModalProcess(gump);
|
||||
Kernel::get_instance()->addProcess(p);
|
||||
}
|
||||
|
||||
void U8Game::playQuotes() {
|
||||
static const Common::Path filename = "static/quotes.dat";
|
||||
|
||||
auto *rs = new Common::File();
|
||||
if (!rs->open(filename)) {
|
||||
warning("U8Game::playQuotes: error opening quotes file: %s", filename.toString().c_str());
|
||||
delete rs;
|
||||
return;
|
||||
}
|
||||
const Std::string text = getCreditText(rs);
|
||||
delete rs;
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) musicproc->playMusic(113); // CONSTANT!
|
||||
|
||||
CreditsGump *gump = new CreditsGump(text, 80);
|
||||
FadeToModalProcess *p = new FadeToModalProcess(gump);
|
||||
Kernel::get_instance()->addProcess(p);
|
||||
}
|
||||
|
||||
|
||||
void U8Game::writeSaveInfo(Common::WriteStream *ws) {
|
||||
MainActor *av = getMainActor();
|
||||
|
||||
const Std::string &avname = av->getName();
|
||||
const uint8 namelength = static_cast<uint8>(avname.size());
|
||||
ws->writeByte(namelength);
|
||||
for (unsigned int i = 0; i < namelength; ++i)
|
||||
ws->writeByte(static_cast<uint8>(avname[i]));
|
||||
|
||||
Point3 pt = av->getLocation();
|
||||
ws->writeUint16LE(av->getMapNum());
|
||||
ws->writeUint32LE(static_cast<uint32>(pt.x));
|
||||
ws->writeUint32LE(static_cast<uint32>(pt.y));
|
||||
ws->writeUint32LE(static_cast<uint32>(pt.z));
|
||||
|
||||
ws->writeUint16LE(av->getStr());
|
||||
ws->writeUint16LE(av->getInt());
|
||||
ws->writeUint16LE(av->getDex());
|
||||
ws->writeUint16LE(av->getHP());
|
||||
ws->writeUint16LE(av->getMaxHP());
|
||||
ws->writeUint16LE(av->getMana());
|
||||
ws->writeUint16LE(av->getMaxMana());
|
||||
ws->writeUint16LE(av->getArmourClass());
|
||||
ws->writeUint16LE(av->getTotalWeight());
|
||||
|
||||
for (unsigned int i = 1; i <= 6; i++) {
|
||||
uint16 objid = av->getEquip(i);
|
||||
Item *item = getItem(objid);
|
||||
if (item) {
|
||||
ws->writeUint32LE(item->getShape());
|
||||
ws->writeUint32LE(item->getFrame());
|
||||
} else {
|
||||
ws->writeUint32LE(0);
|
||||
ws->writeUint32LE(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Std::string U8Game::getCreditText(Common::SeekableReadStream *rs) {
|
||||
unsigned int size = rs->size();
|
||||
Std::string text(size, ' ');
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
uint8 c = rs->readByte();
|
||||
int x;
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
x = 0;
|
||||
break;
|
||||
case 2:
|
||||
x = 0xE1;
|
||||
break;
|
||||
default:
|
||||
x = 0x20 * (i + 1) + (i >> 1);
|
||||
x += (i % 0x40) * ((i & 0xC0) >> 6) * 0x40;
|
||||
break;
|
||||
}
|
||||
char d = (c ^ x) & 0xFF;
|
||||
if (d == 0) d = '\n';
|
||||
text[i] = d;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
60
engines/ultima/ultima8/games/u8_game.h
Normal file
60
engines/ultima/ultima8/games/u8_game.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GAMES_U8GAME_H
|
||||
#define ULTIMA8_GAMES_U8GAME_H
|
||||
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class U8Game: public Game {
|
||||
public:
|
||||
U8Game();
|
||||
~U8Game() override;
|
||||
|
||||
//! load/init game's data files
|
||||
bool loadFiles() override;
|
||||
|
||||
//! initialize new game
|
||||
bool startGame() override;
|
||||
|
||||
//! start initial usecode
|
||||
bool startInitialUsecode(int saveSlot) override;
|
||||
|
||||
//! write game-specific savegame info (avatar stats, equipment, ...)
|
||||
void writeSaveInfo(Common::WriteStream *ws) override;
|
||||
|
||||
ProcId playIntroMovie(bool fade) override;
|
||||
ProcId playEndgameMovie(bool fade) override;
|
||||
void playCredits() override;
|
||||
void playQuotes() override;
|
||||
void playDemoScreen() override { }; // no demo for U8
|
||||
|
||||
protected:
|
||||
Std::string getCreditText(Common::SeekableReadStream *rs);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user