diff options
author | Ľubomír Remák | 2018-04-02 14:03:40 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-25 23:12:01 +0200 |
commit | 99d9055e201b0518baad741f4f46cb86c2f7e172 (patch) | |
tree | cf981af171d578d9064c09ab5e0ff60fb1c853c3 /engines/mutationofjb | |
parent | 2b94873694619272f79f6b358d4a18c8bce13cd8 (diff) | |
download | scummvm-rg350-99d9055e201b0518baad741f4f46cb86c2f7e172.tar.gz scummvm-rg350-99d9055e201b0518baad741f4f46cb86c2f7e172.tar.bz2 scummvm-rg350-99d9055e201b0518baad741f4f46cb86c2f7e172.zip |
MUTATIONOFJB: Load object frames and implement special handling for map scenes.
Diffstat (limited to 'engines/mutationofjb')
-rw-r--r-- | engines/mutationofjb/animationdecoder.cpp | 2 | ||||
-rw-r--r-- | engines/mutationofjb/debug.cpp | 33 | ||||
-rw-r--r-- | engines/mutationofjb/debug.h | 1 | ||||
-rw-r--r-- | engines/mutationofjb/game.cpp | 40 | ||||
-rw-r--r-- | engines/mutationofjb/game.h | 7 | ||||
-rw-r--r-- | engines/mutationofjb/gamedata.cpp | 56 | ||||
-rw-r--r-- | engines/mutationofjb/gamedata.h | 9 | ||||
-rw-r--r-- | engines/mutationofjb/mutationofjb.cpp | 125 | ||||
-rw-r--r-- | engines/mutationofjb/mutationofjb.h | 11 | ||||
-rw-r--r-- | engines/mutationofjb/room.cpp | 65 | ||||
-rw-r--r-- | engines/mutationofjb/room.h | 11 |
11 files changed, 296 insertions, 64 deletions
diff --git a/engines/mutationofjb/animationdecoder.cpp b/engines/mutationofjb/animationdecoder.cpp index 585ad91aa8..5b201535c8 100644 --- a/engines/mutationofjb/animationdecoder.cpp +++ b/engines/mutationofjb/animationdecoder.cpp @@ -159,7 +159,7 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) { const uint16 numLines = file.readUint16LE(); for (uint16 line = firstLine; line < firstLine + numLines; ++line) { - uint8 *imageData = reinterpret_cast<uint8 *>(_surface.getBasePtr(0, firstLine)); + uint8 *imageData = reinterpret_cast<uint8 *>(_surface.getBasePtr(0, line)); uint8 runs = file.readByte(); while (runs--) { diff --git a/engines/mutationofjb/debug.cpp b/engines/mutationofjb/debug.cpp index f533a94ffb..4ce2418d1b 100644 --- a/engines/mutationofjb/debug.cpp +++ b/engines/mutationofjb/debug.cpp @@ -65,6 +65,7 @@ Console::Console(MutationOfJBEngine *vm) : _vm(vm) { registerCmd("showstartup", WRAP_METHOD(Console, cmd_showstartup)); registerCmd("changescene", WRAP_METHOD(Console, cmd_changescene)); registerCmd("dumpsceneinfo", WRAP_METHOD(Console, cmd_dumpsceneinfo)); + registerCmd("dumpdoorinfo", WRAP_METHOD(Console, cmd_dumpdoorinfo)); registerCmd("dumpobjectinfo", WRAP_METHOD(Console, cmd_dumpobjectinfo)); registerCmd("dumpstaticinfo", WRAP_METHOD(Console, cmd_dumpstaticinfo)); } @@ -324,6 +325,38 @@ bool Console::cmd_dumpsceneinfo(int argc, const char **argv) { return true; } +bool Console::cmd_dumpdoorinfo(int argc, const char **argv) { + if (argc == 3) { + const uint8 sceneId = atoi(argv[1]); + const uint8 doorId = atoi(argv[2]); + + Scene *const scene = _vm->getGame().getGameData().getScene(sceneId); + if (scene) { + Door *const door = scene->getDoor(doorId); + if (door) { + debugPrintf("Name: '%s'\n", convertToASCII(door->_name).c_str()); + debugPrintf("DestSceneId: %u\n", (unsigned int) door->_destSceneId); + debugPrintf("DestX: %u\n", (unsigned int) door->_destX); + debugPrintf("DestY: %u\n", (unsigned int) door->_destY); + debugPrintf("X: %u\n", (unsigned int) door->_x); + debugPrintf("Y: %u\n", (unsigned int) door->_y); + debugPrintf("Width: %u\n", (unsigned int) door->_width); + debugPrintf("Height: %u\n", (unsigned int) door->_height); + debugPrintf("WalkToX: %u\n", (unsigned int) door->_walkToX); + debugPrintf("WalkToY: %u\n", (unsigned int) door->_walkToY); + debugPrintf("SP: %u\n", (unsigned int) door->_SP); + } else { + debugPrintf(_("Door %u not found.\n"), (unsigned int) doorId); + } + } else { + debugPrintf(_("Scene %u not found.\n"), (unsigned int) sceneId); + } + } else { + debugPrintf(_("dumpdoorinfo <sceneid> <doorid>\n")); + } + + return true; +} bool Console::cmd_dumpobjectinfo(int argc, const char **argv) { if (argc == 3) { const uint8 sceneId = atoi(argv[1]); diff --git a/engines/mutationofjb/debug.h b/engines/mutationofjb/debug.h index e57b787a6d..0cd7257203 100644 --- a/engines/mutationofjb/debug.h +++ b/engines/mutationofjb/debug.h @@ -45,6 +45,7 @@ private: bool cmd_showstartup(int argc, const char **argv); bool cmd_changescene(int argc, const char **argv); bool cmd_dumpsceneinfo(int argc, const char **argv); + bool cmd_dumpdoorinfo(int argc, const char **argv); bool cmd_dumpobjectinfo(int argc, const char **argv); bool cmd_dumpstaticinfo(int argc, const char **argv); diff --git a/engines/mutationofjb/game.cpp b/engines/mutationofjb/game.cpp index 156c0205d5..a46ca63965 100644 --- a/engines/mutationofjb/game.cpp +++ b/engines/mutationofjb/game.cpp @@ -46,7 +46,7 @@ Game::Game(MutationOfJBEngine *vm) globalScriptFile.close(); _localScript = nullptr; - _room = new Room(_vm->getScreen()); + _room = new Room(this, _vm->getScreen()); changeScene(13, false); // Initial scene. } @@ -55,6 +55,10 @@ GameData &Game::getGameData() { return *_gameData; } +Room &Game::getRoom() { + return *_room; +} + Script *Game::getGlobalScript() const { return _globalScript; } @@ -122,36 +126,6 @@ Script *Game::changeSceneDelayScript(uint8 sceneId, bool partB) { return _delayedLocalScript; } -Door *Game::findDoor(int16 x, int16 y) { - Scene *scene = _gameData->getCurrentScene(); - if (!scene) - return nullptr; - - for (int i = 0; i < MIN(ARRAYSIZE(scene->_doors), (int) scene->_noDoors); ++i) { - Door &door = scene->_doors[i]; - if ((x >= door._x) && (x < door._x + door._width) && (y >= door._y) && (y < door._y + door._height)) { - return &door; - } - } - - return nullptr; -} - -Static *Game::findStatic(int16 x, int16 y) { - Scene *scene = _gameData->getCurrentScene(); - if (!scene) - return nullptr; - - for (int i = 0; i < MIN(ARRAYSIZE(scene->_statics), (int) scene->_noStatics); ++i) { - Static &stat = scene->_statics[i]; - if ((x >= stat._x) && (x < stat._x + stat._width) && (y >= stat._y) && (y < stat._y + stat._height)) { - return &stat; - } - } - - return nullptr; -} - static Command *findActionInfoCommand(const ActionInfos &infos, const Common::String &entity1Name, const Common::String &entity2Name = Common::String()) { for (ActionInfos::const_iterator it = infos.begin(); it != infos.end(); ++it) { if (it->_entity1Name == entity1Name && it->_entity2Name == entity2Name) { @@ -180,6 +154,10 @@ bool Game::startActionSection(ActionInfo::Action action, const Common::String &e return false; } +bool Game::isCurrentSceneMap() const { + return _gameData->_currentScene == 12; +} + void Game::update() { Command::ExecuteResult res = _scriptExecCtx.runActiveCommand(); if (res == Command::Finished && _delayedLocalScript) { diff --git a/engines/mutationofjb/game.h b/engines/mutationofjb/game.h index 503cde98e4..c71b5f16e7 100644 --- a/engines/mutationofjb/game.h +++ b/engines/mutationofjb/game.h @@ -39,22 +39,23 @@ class Script; class Room; class Door; class Static; +class Bitmap; class Game { public: Game(MutationOfJBEngine *vm); GameData &getGameData(); - + Room &getRoom(); Script *getGlobalScript() const; Script *getLocalScript() const; void changeScene(uint8 sceneId, bool partB); Script *changeSceneDelayScript(uint8 sceneId, bool partB); - Door *findDoor(int16 x, int16 y); - Static *findStatic(int16 x, int16 y); bool startActionSection(ActionInfo::Action action, const Common::String &entity1Name, const Common::String &entity2Name = Common::String()); + bool isCurrentSceneMap() const; + void update(); private: diff --git a/engines/mutationofjb/gamedata.cpp b/engines/mutationofjb/gamedata.cpp index acca555bbc..fb9e642355 100644 --- a/engines/mutationofjb/gamedata.cpp +++ b/engines/mutationofjb/gamedata.cpp @@ -151,7 +151,7 @@ Door *Scene::getDoor(uint8 doorId) { } Object *Scene::getObject(uint8 objectId, bool ignoreNo) { - if (objectId == 0 || objectId > (!ignoreNo ? MIN(_noObjects, (uint8) ARRAYSIZE(_objects)) : ARRAYSIZE(_objects))) { + if (objectId == 0 || objectId > getNoObjects(ignoreNo)) { warning(_("Object %d does not exist"), objectId); return nullptr; } @@ -168,6 +168,60 @@ Static *Scene::getStatic(uint8 staticId, bool ignoreNo) { return &_statics[staticId - 1]; } +uint8 Scene::getNoDoors(bool ignoreNo) const { + return (!ignoreNo ? MIN(_noDoors, (uint8) ARRAYSIZE(_doors)) : ARRAYSIZE(_doors)); +} + +uint8 Scene::getNoObjects(bool ignoreNo) const { + return (!ignoreNo ? MIN(_noObjects, (uint8) ARRAYSIZE(_objects)) : ARRAYSIZE(_objects)); +} + +uint8 Scene::getNoStatics(bool ignoreNo) const { + return (!ignoreNo ? MIN(_noStatics, (uint8) ARRAYSIZE(_statics)) : ARRAYSIZE(_statics)); +} + +Door *Scene::findDoor(int16 x, int16 y, int *index) { + for (int i = 0; i < getNoDoors(); ++i) { + Door &door = _doors[i]; + if ((x >= door._x) && (x < door._x + door._width) && (y >= door._y) && (y < door._y + door._height)) { + if (index) { + *index = i + 1; + } + return &door; + } + } + + return nullptr; +} + +Static *Scene::findStatic(int16 x, int16 y, int *index) { + for (int i = 0; i < getNoStatics(); ++i) { + Static &stat = _statics[i]; + if ((x >= stat._x) && (x < stat._x + stat._width) && (y >= stat._y) && (y < stat._y + stat._height)) { + if (index) { + *index = i + 1; + } + return &stat; + } + } + + return nullptr; +} + +Bitmap *Scene::findBitmap(int16 x, int16 y, int *index) { + for (int i = 0; i < ARRAYSIZE(_bitmaps); ++i) { + Bitmap &bitmap = _bitmaps[i]; + if ((x >= bitmap._x1) && (x <= bitmap._x2) && (y >= bitmap._y1) && (y <= bitmap._y2)) { + if (index) { + *index = i + 1; + } + return &bitmap; + } + } + + return nullptr; +} + GameData::GameData() : _currentScene(0), diff --git a/engines/mutationofjb/gamedata.h b/engines/mutationofjb/gamedata.h index 473575328d..b0c64c5ac8 100644 --- a/engines/mutationofjb/gamedata.h +++ b/engines/mutationofjb/gamedata.h @@ -121,11 +121,18 @@ struct Bitmap { struct Scene { - Door *getDoor(uint8 objectId); Object *getObject(uint8 objectId, bool ignoreNo = false); Static *getStatic(uint8 staticId, bool ignoreNo = false); + uint8 getNoDoors(bool ignoreNo = false) const; + uint8 getNoObjects(bool ignoreNo = false) const; + uint8 getNoStatics(bool ignoreNo = false) const; + + Door *findDoor(int16 x, int16 y, int *index = nullptr); + Static *findStatic(int16 x, int16 y, int *index = nullptr); + Bitmap *findBitmap(int16 x, int16 y, int *index = nullptr); + uint8 _startup; uint8 _unknown001; uint8 _unknown002; diff --git a/engines/mutationofjb/mutationofjb.cpp b/engines/mutationofjb/mutationofjb.cpp index 622be67a8c..df8ad113a6 100644 --- a/engines/mutationofjb/mutationofjb.cpp +++ b/engines/mutationofjb/mutationofjb.cpp @@ -35,13 +35,16 @@ #include "mutationofjb/game.h" #include "mutationofjb/gamedata.h" #include "mutationofjb/debug.h" +#include "mutationofjb/room.h" namespace MutationOfJB { MutationOfJBEngine::MutationOfJBEngine(OSystem *syst) : Engine(syst), _console(nullptr), - _screen(nullptr) { + _screen(nullptr), + _currentAction(ActionInfo::Walk), + _mapObjectId(0) { debug("MutationOfJBEngine::MutationOfJBEngine"); } @@ -69,6 +72,94 @@ Game &MutationOfJBEngine::getGame() { return *_game; } +void MutationOfJBEngine::handleNormalScene(const Common::Event &event) { + Scene *const scene = _game->getGameData().getCurrentScene(); + + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + { + const int16 x = event.mouse.x; + const int16 y = event.mouse.y; + + if (Door *const door = scene->findDoor(x, y)) { + if (!_game->startActionSection(_currentAction, door->_name) && _currentAction == ActionInfo::Walk && door->_destSceneId != 0) { + _game->changeScene(door->_destSceneId, _game->getGameData()._partB); + } + } else if (Static *const stat = scene->findStatic(x, y)) { + if (stat->_active == 1) { + _game->startActionSection(_currentAction, stat->_name); + } + } + break; + } + default: + break; + } +} + +/* + Special handling for map scenes. + + Bitmaps define mouse clickable areas. + Statics are used to start actions. + Objects are used for showing labels. + +*/ +void MutationOfJBEngine::handleMapScene(const Common::Event &event) { + Scene *const scene = _game->getGameData().getCurrentScene(); + + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + { + const int16 x = event.mouse.x; + const int16 y = event.mouse.y; + + int index = 0; + if (Bitmap *const bitmap = scene->findBitmap(x, y, &index)) { + Static *const stat = scene->getStatic(index); + if (stat && stat->_active == 1) { + _game->startActionSection(ActionInfo::Walk, stat->_name); + } + } + break; + } + case Common::EVENT_MOUSEMOVE: + { + const int16 x = event.mouse.x; + const int16 y = event.mouse.y; + + int index = 0; + bool found = false; + if (Bitmap *const bitmap = scene->findBitmap(x, y, &index)) { + Static *const stat = scene->getStatic(index); + if (stat && stat->_active == 1) { + Object *const object = scene->getObject(index); + if (object) { + found = true; + if (index != _mapObjectId) { + if (_mapObjectId) { + _game->getRoom().drawObjectAnimation(_mapObjectId, 1); + _mapObjectId = 0; + } + + _mapObjectId = index; + _game->getRoom().drawObjectAnimation(_mapObjectId, 0); + } + } + } + } + + if (!found && _mapObjectId != 0) { + _game->getRoom().drawObjectAnimation(_mapObjectId, 1); + _mapObjectId = 0; + } + break; + } + default: + break; + } +} + Common::Error MutationOfJBEngine::run() { debug("MutationOfJBEngine::run"); @@ -77,11 +168,10 @@ Common::Error MutationOfJBEngine::run() { _console = new Console(this); _screen = new Graphics::Screen(); _game = new Game(this); - ActionInfo::Action currentAction = ActionInfo::Walk; setupCursor(); - while(!shouldQuit()) { + while (!shouldQuit()) { Common::Event event; while (_eventMan->pollEvent(event)) { switch (event.type) { @@ -93,45 +183,40 @@ Common::Error MutationOfJBEngine::run() { } break; } - case Common::EVENT_LBUTTONDOWN: - { - if (Door *const door = _game->findDoor(event.mouse.x, event.mouse.y)) { - if (!_game->startActionSection(currentAction, door->_name) && currentAction == ActionInfo::Walk && door->_destSceneId != 0) { - _game->changeScene(door->_destSceneId, _game->getGameData()._partB); - } - } else if (Static *const stat = _game->findStatic(event.mouse.x, event.mouse.y)) { - _game->startActionSection(currentAction, stat->_name); - } - break; - } case Common::EVENT_KEYUP: { switch (event.kbd.ascii) { case 'g': - currentAction = ActionInfo::Walk; + _currentAction = ActionInfo::Walk; break; case 'r': - currentAction = ActionInfo::Talk; + _currentAction = ActionInfo::Talk; break; case 's': - currentAction = ActionInfo::Look; + _currentAction = ActionInfo::Look; break; case 'b': - currentAction = ActionInfo::Use; + _currentAction = ActionInfo::Use; break; case 'n': - currentAction = ActionInfo::PickUp; + _currentAction = ActionInfo::PickUp; break; } } default: break; } + + if (!_game->isCurrentSceneMap()) { + handleNormalScene(event); + } else { + handleMapScene(event); + } } _console->onFrame(); _game->update(); - _system->delayMillis(40); + _system->delayMillis(10); _screen->update(); } diff --git a/engines/mutationofjb/mutationofjb.h b/engines/mutationofjb/mutationofjb.h index 893cca9772..ef0c97346d 100644 --- a/engines/mutationofjb/mutationofjb.h +++ b/engines/mutationofjb/mutationofjb.h @@ -24,9 +24,14 @@ #define MUTATIONOFJB_MUTATIONOFJB_H #include "engines/engine.h" +#include "mutationofjb/script.h" + +namespace Common { +class Event; +} namespace Graphics { - class Screen; +class Screen; } namespace MutationOfJB { @@ -46,10 +51,14 @@ public: private: bool loadGameData(bool partB); void setupCursor(); + void handleNormalScene(const Common::Event &event); + void handleMapScene(const Common::Event &event); Console *_console; Graphics::Screen *_screen; Game *_game; + ActionInfo::Action _currentAction; + uint8 _mapObjectId; }; diff --git a/engines/mutationofjb/room.cpp b/engines/mutationofjb/room.cpp index 547cda43f4..66da3acfb2 100644 --- a/engines/mutationofjb/room.cpp +++ b/engines/mutationofjb/room.cpp @@ -23,6 +23,8 @@ #include "mutationofjb/room.h" #include "mutationofjb/animationdecoder.h" #include "mutationofjb/encryptedfile.h" +#include "mutationofjb/game.h" +#include "mutationofjb/gamedata.h" #include "mutationofjb/util.h" #include "common/str.h" #include "common/translation.h" @@ -44,20 +46,75 @@ void RoomAnimationDecoderCallback::onPaletteUpdated(byte palette[PALETTE_SIZE]) } void RoomAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surface) { - if (frameNo != 0) { - return; + if (frameNo == 0) { + _room._screen->blitFrom(surface); } - _room._screen->blitFrom(surface); + const int frameNo1 = frameNo + 1; + + Scene *scene = _room._game->getGameData().getCurrentScene(); + if (scene) { + const uint8 noObjects = scene->getNoObjects(); + for (int i = 0; i < noObjects; ++i) { + Object &object = scene->_objects[i]; + const uint16 startFrame = (object._WY << 8) + object._FS; + if (frameNo1 >= startFrame && frameNo1 < startFrame + object._NA) { + const int x = object._x; + const int y = object._y; + const int w = object._XL / 4 * 4; + const int h = object._YL / 4 * 4; + Common::Rect rect(x, y, x + w, y + h); + + const Graphics::Surface sharedSurface = surface.getSubArea(rect); + Graphics::Surface outSurface; + outSurface.copyFrom(sharedSurface); + _room._surfaces[_room._objectsStart[i] + frameNo1 - startFrame] = outSurface; + } + } + } } -Room::Room(Graphics::Screen *screen) : _screen(screen) {} +Room::Room(Game *game, Graphics::Screen *screen) : _game(game), _screen(screen) {} bool Room::load(uint8 roomNumber, bool roomB) { + _objectsStart.clear(); + + Scene *const scene = _game->getGameData().getCurrentScene(); + if (scene) { + const uint8 noObjects = scene->getNoObjects(); + for (int i = 0; i < noObjects; ++i) { + uint8 firstIndex = 0; + if (i != 0) { + firstIndex = _objectsStart[i - 1] + scene->_objects[i - 1]._NA; + } + _objectsStart.push_back(firstIndex); + + uint8 numAnims = scene->_objects[i]._NA; + while (numAnims--) { + _surfaces.push_back(Graphics::Surface()); + } + } + } + const Common::String fileName = Common::String::format("room%d%s.dat", roomNumber, roomB ? "b" : ""); AnimationDecoder decoder(fileName); RoomAnimationDecoderCallback callback(*this); return decoder.decode(&callback); } +void Room::drawObjectAnimation(uint8 objectId, int animOffset) { + Scene *const scene = _game->getGameData().getCurrentScene(); + if (!scene) { + return; + } + Object *const object = scene->getObject(objectId); + if (!object) { + return; + } + + const int startFrame = _objectsStart[objectId - 1]; + const int animFrame = startFrame + animOffset; + _screen->blitFrom(_surfaces[animFrame], Common::Point(object->_x, object->_y)); +} + } diff --git a/engines/mutationofjb/room.h b/engines/mutationofjb/room.h index e8f444007e..a2be2fc3be 100644 --- a/engines/mutationofjb/room.h +++ b/engines/mutationofjb/room.h @@ -24,23 +24,30 @@ #define MUTATIONOFJB_ROOM_H #include "common/scummsys.h" +#include "common/array.h" +#include "graphics/surface.h" namespace Graphics { - class Screen; +class Screen; } namespace MutationOfJB { class EncryptedFile; +class Game; class Room { public: friend class RoomAnimationDecoderCallback; - Room(Graphics::Screen *screen); + Room(Game *game, Graphics::Screen *screen); bool load(uint8 roomNumber, bool roomB); + void drawObjectAnimation(uint8 objectId, int animOffset); private: + Game *_game; Graphics::Screen *_screen; + Common::Array<Graphics::Surface> _surfaces; + Common::Array<int> _objectsStart; }; } |