Permalink
Browse files

MUTATIONOFJB: Draw objects (first frame only) and improve conversatio…

…n support.
  • Loading branch information...
LubomirR authored and sev- committed Jul 14, 2018
1 parent d2e354b commit febff83a4edc89e1dbc6f4c56f5531f0eb8f3287
@@ -56,7 +56,7 @@ bool DefineStructCommandParser::parse(const Common::String &line, ScriptParseCon

for (int j = 0; j < 5; ++j) {
ConversationInfo::Item convItem;
convItem._question = atoi(linePtr);
convItem._choice = atoi(linePtr);
linePtr += 6;
convItem._response = atoi(linePtr);
linePtr += 6;
@@ -21,9 +21,12 @@
*/

#include "mutationofjb/commands/talkcommand.h"
#include "mutationofjb/tasks/conversationtask.h"
#include "mutationofjb/script.h"

#include "mutationofjb/game.h"
#include "mutationofjb/script.h"
#include "mutationofjb/tasks/conversationtask.h"
#include "mutationofjb/tasks/taskmanager.h"

#include "common/str.h"

namespace MutationOfJB {
@@ -53,7 +56,7 @@ bool TalkCommandParser::parse(const Common::String &line, ScriptParseContext &,

Command::ExecuteResult TalkCommand::execute(ScriptExecutionContext &scriptExeCtx) {
if (!_task) {
_task = new ConversationTask(scriptExeCtx.getGame().getGameData()._conversationInfo);
_task = new ConversationTask(scriptExeCtx.getGameData()._currentScene, scriptExeCtx.getGame().getGameData()._conversationInfo);
scriptExeCtx.getGame().getTaskManager().addTask(_task);
}

@@ -100,7 +100,9 @@ Script *Game::changeSceneLoadScript(uint8 sceneId, bool partB) {
_gameData->_lastScene = _gameData->_currentScene;
_gameData->_currentScene = sceneId;
_gameData->_partB = partB;

_room->load(_gameData->_currentScene, partB);
_room->redraw();

EncryptedFile scriptFile;
Common::String fileName = Common::String::format("scrn%d%s.atn", sceneId, partB ? "b" : "");
@@ -180,6 +182,7 @@ void Game::update() {
}

_gui.update();
_taskManager.update();
}

Gui &Game::getGui() {
@@ -227,4 +230,9 @@ Assets& Game::getAssets() {
return _assets;
}

Graphics::Screen &Game::getScreen()
{
return *_vm->getScreen();
}

}
@@ -71,6 +71,8 @@ class Game {
TaskManager& getTaskManager();
Assets &getAssets();

Graphics::Screen &getScreen();

private:
bool loadGameData(bool partB);
void runActiveCommand();
@@ -136,7 +136,11 @@ bool Scene::loadFromStream(Common::ReadStream &stream) {
_palRotStart = stream.readByte();
_palRotEnd = stream.readByte();
_palRotPeriod = stream.readByte();
stream.read(_unknown38A, 80);
_exhaustedChoiceNext = stream.readByte();

for (i = 0; i < 79; ++i) {
_exhaustedChoices[i]._encodedData = stream.readByte();
}

return true;
}
@@ -222,6 +226,22 @@ Bitmap *Scene::findBitmap(int16 x, int16 y, int *index) {
return nullptr;
}

void Scene::addExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceIndexList) {
_exhaustedChoices[_exhaustedChoiceNext - 1] = ExhaustedChoice(context, choiceIndex, choiceIndexList);
_exhaustedChoiceNext++;
}

bool Scene::isChoiceExhausted(uint8 context, uint8 choiceIndex, uint8 choiceListIndex) const {
for (uint i = 0; i < _exhaustedChoiceNext - 1; ++i) {
const ExhaustedChoice &choice = _exhaustedChoices[i];
if (choice.getContext() == context && choice.getChoiceIndex() == choiceIndex && choice.getChoiceListIndex() == choiceListIndex) {
return true;
}
}

return false;
}


GameData::GameData()
: _currentScene(0),
@@ -121,6 +121,22 @@ struct Bitmap {
bool loadFromStream(Common::ReadStream &stream);
};

struct ExhaustedChoice {
/*
1 bit - context
3 bits - choice index
4 bits - choice list index
*/
uint8 _encodedData;

uint8 getContext() const { return (_encodedData >> 7) & 0x1; }
uint8 getChoiceIndex() const { return (_encodedData >> 4) & 0x7; }
uint8 getChoiceListIndex() const { return _encodedData & 0xF; }

ExhaustedChoice() : _encodedData(0) {}
ExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceListIndex) :
_encodedData(((context & 0x1) << 7) | ((choiceIndex & 0x7) << 4) | (choiceListIndex & 0xF)) {}
};

struct Scene {
Door *getDoor(uint8 objectId);
@@ -135,6 +151,9 @@ struct Scene {
Static *findStatic(int16 x, int16 y, int *index = nullptr);
Bitmap *findBitmap(int16 x, int16 y, int *index = nullptr);

void addExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceIndexList);
bool isChoiceExhausted(uint8 context, uint8 choiceIndex, uint8 choiceIndexList) const;

uint8 _startup;
uint8 _unknown001;
uint8 _unknown002;
@@ -156,14 +175,17 @@ struct Scene {
uint8 _palRotStart;
uint8 _palRotEnd;
uint8 _palRotPeriod;
uint8 _unknown38A[80];

/* Points to the first free item in exhausted choices list. */
uint8 _exhaustedChoiceNext;
ExhaustedChoice _exhaustedChoices[79];

bool loadFromStream(Common::ReadStream &stream);
};

struct ConversationInfo {
struct Item {
uint8 _question;
uint8 _choice;
uint8 _response;
uint8 _nextLineIndex;
};
@@ -22,6 +22,7 @@ MODULE_OBJS := \
commands/seqcommand.o \
commands/talkcommand.o \
tasks/conversationtask.o \
tasks/saytask.o \
tasks/taskmanager.o \
widgets/buttonwidget.o \
widgets/conversationwidget.o \
@@ -42,6 +43,7 @@ MODULE_OBJS := \
mutationofjb.o \
room.o \
script.o \
timer.o \
util.o

# This module can be built as a plugin
@@ -21,17 +21,25 @@
*/

#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"

#include "graphics/screen.h"

namespace MutationOfJB {

enum {
GAME_AREA_WIDTH = 320,
GAME_AREA_HEIGHT = 139
};

class RoomAnimationDecoderCallback : public AnimationDecoderCallback {
public:
RoomAnimationDecoderCallback(Room &room) : _room(room) {}
@@ -47,9 +55,11 @@ void RoomAnimationDecoderCallback::onPaletteUpdated(byte palette[PALETTE_SIZE])

void RoomAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surface) {
if (frameNo == 0) {
Common::Rect rect(0, 0, 320, 139);
Common::Rect rect(0, 0, GAME_AREA_WIDTH, GAME_AREA_HEIGHT);
if (_room._game->isCurrentSceneMap()) {
rect = Common::Rect(0, 0, 320, 200);
} else {
_room._background.blitFrom(surface, rect, Common::Point(0, 0));
}
_room._screen->blitFrom(surface, rect, Common::Point(0, 0));
}
@@ -78,10 +88,11 @@ void RoomAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surfa
}
}

Room::Room(Game *game, Graphics::Screen *screen) : _game(game), _screen(screen) {}
Room::Room(Game *game, Graphics::Screen *screen) : _game(game), _screen(screen), _background(GAME_AREA_WIDTH, GAME_AREA_HEIGHT) {}

bool Room::load(uint8 roomNumber, bool roomB) {
_objectsStart.clear();
_surfaces.clear(); // TODO: Fix memory leak.

Scene *const scene = _game->getGameData().getCurrentScene();
if (scene) {
@@ -118,7 +129,23 @@ void Room::drawObjectAnimation(uint8 objectId, int animOffset) {

const int startFrame = _objectsStart[objectId - 1];
const int animFrame = startFrame + animOffset;
// TODO: Threshold.
_screen->blitFrom(_surfaces[animFrame], Common::Point(object->_x, object->_y));
}

void Room::redraw() {
if (!_game->isCurrentSceneMap()) {
Common::Rect rect(0, 0, GAME_AREA_WIDTH, GAME_AREA_HEIGHT);
_screen->blitFrom(_background.rawSurface(), rect, Common::Point(0, 0));

Scene *const currentScene = _game->getGameData().getCurrentScene();
for (int i = 0; i < currentScene->getNoObjects(); ++i) {
Object *const obj = currentScene->getObject(i + 1);
if (obj->_AC) {
drawObjectAnimation(i + 1, 0);
}
}
}
}

}
@@ -26,6 +26,7 @@
#include "common/scummsys.h"
#include "common/array.h"
#include "graphics/surface.h"
#include "graphics/managed_surface.h"

namespace Graphics {
class Screen;
@@ -44,9 +45,11 @@ class Room {
Room(Game *game, Graphics::Screen *screen);
bool load(uint8 roomNumber, bool roomB);
void drawObjectAnimation(uint8 objectId, int animOffset);
void redraw();
private:
Game *_game;
Graphics::Screen *_screen;
Graphics::ManagedSurface _background;
Common::Array<Graphics::Surface> _surfaces;
Common::Array<int> _objectsStart;
};
Oops, something went wrong.

0 comments on commit febff83

Please sign in to comment.