Permalink
Browse files

MUTATIONOFJB: Implement SayCommand::execute.

  • Loading branch information...
LubomirR committed Jul 21, 2018
1 parent b73d158 commit 46bb90e9982730aa3aabebcc966f986da2367fdc
@@ -21,7 +21,13 @@
*/

#include "mutationofjb/commands/saycommand.h"

#include "mutationofjb/game.h"
#include "mutationofjb/gamedata.h"
#include "mutationofjb/script.h"
#include "mutationofjb/tasks/saytask.h"
#include "mutationofjb/tasks/taskmanager.h"

#include "common/str.h"
#include "common/debug.h"
#include "common/debug-channels.h"
@@ -140,9 +146,18 @@ bool SayCommandParser::parse(const Common::String &line, ScriptParseContext &par
}


Command::ExecuteResult SayCommand::execute(ScriptExecutionContext &) {
// TODO: Actual implementation.
debug("%s [%s]", _lineToSay.c_str(), _voiceFile.c_str());
Command::ExecuteResult SayCommand::execute(ScriptExecutionContext &scriptExecCtx) {
Game &game = scriptExecCtx.getGame();

if (_waitForPrevious) {
if (game.getActiveSayTask()) {
return InProgress;
}
}

TaskPtr task(new SayTask(_lineToSay, game.getGameData()._color));
game.getTaskManager().startTask(task);

return Finished;
}

@@ -57,11 +57,10 @@ bool TalkCommandParser::parse(const Common::String &line, ScriptParseContext &,
Command::ExecuteResult TalkCommand::execute(ScriptExecutionContext &scriptExeCtx) {
if (!_task) {
_task = TaskPtr(new ConversationTask(scriptExeCtx.getGameData()._currentScene, scriptExeCtx.getGame().getGameData()._conversationInfo, _mode));
scriptExeCtx.getGame().getTaskManager().addTask(_task);
scriptExeCtx.getGame().getTaskManager().startTask(_task);
}

if (_task->getState() == Task::FINISHED) {
scriptExeCtx.getGame().getTaskManager().removeTask(_task);
_task.reset();

return Command::Finished;
@@ -77,7 +77,7 @@ bool Font::load(const Common::String &fileName) {
void Font::drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf) const {
GlyphMap::iterator it = _glyphs.find(glyph);
if (it == _glyphs.end()) {
warning("Glyph %d not found", glyph);
// Missing glyph is a common situation in the game and it's okay to ignore it.
return;
}

@@ -42,8 +42,8 @@ Game::Game(MutationOfJBEngine *vm)
_randomSource("mutationofjb"),
_delayedLocalScript(nullptr),
_gui(*this, _vm->getScreen()),
_scriptExecCtx(*this),
_currentAction(ActionInfo::Walk),
_scriptExecCtx(*this),
_taskManager(*this),
_assets(*this) {

@@ -61,7 +61,7 @@ Game::Game(MutationOfJBEngine *vm)

_gui.init();

_taskManager.addTask(TaskPtr(new ObjectAnimationTask));
_taskManager.startTask(TaskPtr(new ObjectAnimationTask));
}

Common::RandomSource &Game::getRandomSource() {
@@ -240,9 +240,16 @@ Assets &Game::getAssets() {
return _assets;
}

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

TaskPtr Game::getActiveSayTask() const {
return _activeSayTask;
}

void Game::setActiveSayTask(const TaskPtr &sayTask) {
_activeSayTask = sayTask;
}

}
@@ -23,13 +23,15 @@
#ifndef MUTATIONOFJB_GAME_H
#define MUTATIONOFJB_GAME_H

#include "common/random.h"
#include "common/scummsys.h"
#include "mutationofjb/assets.h"
#include "mutationofjb/gui.h"
#include "mutationofjb/script.h"
#include "mutationofjb/tasks/taskmanager.h"

#include "common/ptr.h"
#include "common/random.h"
#include "common/scummsys.h"

namespace Common {
class String;
}
@@ -44,6 +46,7 @@ class Room;
class Door;
class Static;
class Bitmap;
class SayTask;

class Game {
public:
@@ -75,6 +78,9 @@ class Game {

Graphics::Screen &getScreen();

TaskPtr getActiveSayTask() const;
void setActiveSayTask(const TaskPtr &sayTask);

private:
bool loadGameData(bool partB);
void runActiveCommand();
@@ -96,6 +102,7 @@ class Game {

TaskManager _taskManager;
Assets _assets;
TaskPtr _activeSayTask;
};

}
@@ -247,7 +247,8 @@ GameData::GameData()
: _currentScene(0),
_lastScene(0),
_partB(false),
_inventory()
_inventory(),
_color(WHITE)
{}

Scene *GameData::getScene(uint8 sceneId) {
@@ -323,14 +323,16 @@ struct GameData {

bool loadFromStream(Common::ReadStream &stream);

uint8 _currentScene;
uint8 _currentScene; // Persistent.
uint8 _lastScene;
bool _partB;
Inventory _inventory;
Common::String _currentAPK;
bool _partB; // Persistent.
Inventory _inventory; // Persistent.
Common::String _currentAPK; // Persistent.
ConversationInfo _conversationInfo;
/** Current SayCommand color. */
uint8 _color;
private:
Scene _scenes[45];
Scene _scenes[45]; // Persistent.
};

enum Colors {
@@ -154,6 +154,7 @@ Command::ExecuteResult ScriptExecutionContext::startCommand(Command *cmd) {
warning(_("Trying to start command while another one is running."));
return Command::Finished;
}
getGameData()._color = WHITE; // The original game resets the color to WHITE beforing running script sections.
clear();
_activeCommand = cmd;
return runActiveCommand();
@@ -54,7 +54,6 @@ void ConversationTask::start() {
void ConversationTask::update() {
if (_sayTask) {
if (_sayTask->getState() == Task::FINISHED) {
getTaskManager()->removeTask(_sayTask);
_sayTask.reset();

switch (_substate) {
@@ -67,7 +66,7 @@ void ConversationTask::update() {

_substate = SAYING_RESPONSE;
createSayTasks(line);
getTaskManager()->addTask(_sayTask);
getTaskManager()->startTask(_sayTask);
break;
}
case SAYING_RESPONSE: {
@@ -105,7 +104,7 @@ void ConversationTask::onChoiceClicked(ConversationWidget *convWidget, int, uint

_substate = SAYING_CHOICE;
createSayTasks(line);
getTaskManager()->addTask(_sayTask);
getTaskManager()->startTask(_sayTask);
_currentItem = &item;

if (!line->_speeches[0].isRepeating()) {
@@ -177,7 +176,7 @@ void ConversationTask::showChoicesOrPick() {

_substate = SAYING_CHOICE;
createSayTasks(line);
getTaskManager()->addTask(_sayTask);
getTaskManager()->startTask(_sayTask);
_currentItem = &item;

if (!line->_speeches[0].isRepeating()) {
@@ -192,7 +191,7 @@ void ConversationTask::showChoicesOrPick() {

_substate = SAYING_RESPONSE;
createSayTasks(line);
getTaskManager()->addTask(_sayTask);
getTaskManager()->startTask(_sayTask);
_currentItem = &item;

_haveChoices = true;
@@ -204,7 +203,7 @@ void ConversationTask::showChoicesOrPick() {
finish();
} else {
_sayTask = TaskPtr(new SayTask("Nothing to talk about.", _convInfo._color)); // TODO: This is hardcoded in executable. Load it.
getTaskManager()->addTask(_sayTask);
getTaskManager()->startTask(_sayTask);
_substate = SAYING_NO_CHOICES;
_currentItem = nullptr;
}
@@ -34,21 +34,31 @@

namespace MutationOfJB {

SayTask::SayTask(const Common::String &toSay, uint8 color) : _toSay(toSay), _color(color), _timer(1000) {}
SayTask::SayTask(const Common::String &toSay, uint8 color) : _toSay(toSay), _color(color), _timer(50 * toSay.size()) {}

void SayTask::start() {
Game &game = getTaskManager()->getGame();
if (game.getActiveSayTask()) {
getTaskManager()->stopTask(game.getActiveSayTask());
}
game.setActiveSayTask(getTaskManager()->getTask(this));

setState(RUNNING);
drawSubtitle(_toSay, 160, 0, _color); // TODO: Respect PTALK and LTALK commands.
_timer.start();
setState(RUNNING);
}

void SayTask::update() {
_timer.update();

if (_timer.isFinished()) {
getTaskManager()->getGame().getRoom().redraw(); // TODO: Only redraw the area occupied by the text.
setState(FINISHED);
return;
finish();
}
}

void SayTask::stop() {
if (getState() == RUNNING) {
finish();
}
}

@@ -89,4 +99,14 @@ void SayTask::drawSubtitle(const Common::String &text, int16 talkX, int16 talkY,
_boundingBox.setHeight(lines.size() * font.getLineHeight());
}

void SayTask::finish() {
getTaskManager()->getGame().getRoom().redraw(); // TODO: Only redraw the area occupied by the text.
setState(FINISHED);

Game &game = getTaskManager()->getGame();
if (game.getActiveSayTask().get() == this) {
game.setActiveSayTask(Common::SharedPtr<SayTask>());
}
}

}
@@ -38,9 +38,11 @@ class SayTask : public Task {

virtual void start() override;
virtual void update() override;
virtual void stop() override;

private:
void drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, uint8 color);
void finish();

Common::String _toSay;
uint8 _color;
@@ -48,7 +48,7 @@ void SequentialTask::runTasks() {
const TaskPtr &task = _tasks.front();
switch (task->getState()) {
case IDLE:
getTaskManager()->addTask(task);
getTaskManager()->startTask(task);
break;
case RUNNING:
return;
@@ -44,6 +44,7 @@ class Task {

virtual void start() = 0;
virtual void update() = 0;
virtual void stop() { assert(false); } // Assert by default - stopping might not be safe for all tasks.

void setTaskManager(TaskManager *taskMan) { _taskManager = taskMan; }
TaskManager *getTaskManager() { return _taskManager; }
@@ -21,21 +21,39 @@
*/

#include "mutationofjb/tasks/taskmanager.h"

#include "mutationofjb/tasks/task.h"

#include "common/translation.h"

namespace MutationOfJB {

void TaskManager::addTask(const TaskPtr &task) {
void TaskManager::startTask(const TaskPtr &task) {
_tasks.push_back(task);
task->setTaskManager(this);
task->start();
}

void TaskManager::removeTask(const TaskPtr &task) {
void TaskManager::stopTask(const TaskPtr &task) {
TaskPtrs::iterator it = Common::find(_tasks.begin(), _tasks.end(), task);
if (it != _tasks.end()) {
_tasks.erase(it);
if (it == _tasks.end()) {
warning(_("Task is not registered in TaskManager."));
return;
}

task->stop();
assert(task->getState() != Task::RUNNING);
_tasks.erase(it);
}

TaskPtr TaskManager::getTask(Task *const task) {
for (TaskPtrs::iterator it = _tasks.begin(); it != _tasks.end(); ++it) {
if (it->get() == task) {
return *it;
}
}

return TaskPtr();
}

void TaskManager::update() {
@@ -35,8 +35,30 @@ class TaskManager {
public:
TaskManager(Game &game) : _game(game) {}

void addTask(const TaskPtr &task);
void removeTask(const TaskPtr &task);
/**
* Adds the task to the internal list and starts it.
*
* When the task is finished, it is automatically removed from the list.
* stopTask does not need to be called for that.
*/
void startTask(const TaskPtr &task);

/**
* Stops the task and removes it from the internal list.
*
* Call this only if you need to explicitly stop the task (usually before it's finished).
*/
void stopTask(const TaskPtr &task);

/**
* Gets task shared pointer from raw pointer.
*
* Since task lifetime is under control of SharedPtr, raw pointers shouldn't be used.
* However, if only a raw pointer is available (e.g. this),
* the method can be used to obtain a SharedPtr.
*/
TaskPtr getTask(Task* task);

void update();

Game &getGame() { return _game; }

0 comments on commit 46bb90e

Please sign in to comment.