diff options
author | Ľubomír Remák | 2018-07-15 00:18:54 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-25 23:12:01 +0200 |
commit | febff83a4edc89e1dbc6f4c56f5531f0eb8f3287 (patch) | |
tree | 756129c1736a39aad5473d7873810a3a742911ae /engines/mutationofjb/tasks | |
parent | d2e354b51f637dc2e9b251256b5a017cb41cfe59 (diff) | |
download | scummvm-rg350-febff83a4edc89e1dbc6f4c56f5531f0eb8f3287.tar.gz scummvm-rg350-febff83a4edc89e1dbc6f4c56f5531f0eb8f3287.tar.bz2 scummvm-rg350-febff83a4edc89e1dbc6f4c56f5531f0eb8f3287.zip |
MUTATIONOFJB: Draw objects (first frame only) and improve conversation support.
Diffstat (limited to 'engines/mutationofjb/tasks')
-rw-r--r-- | engines/mutationofjb/tasks/conversationtask.cpp | 173 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/conversationtask.h | 25 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/saytask.cpp | 55 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/saytask.h | 44 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/task.h | 5 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/taskmanager.cpp | 4 |
6 files changed, 276 insertions, 30 deletions
diff --git a/engines/mutationofjb/tasks/conversationtask.cpp b/engines/mutationofjb/tasks/conversationtask.cpp index 75d850465b..512b38b710 100644 --- a/engines/mutationofjb/tasks/conversationtask.cpp +++ b/engines/mutationofjb/tasks/conversationtask.cpp @@ -21,63 +21,186 @@ */ #include "mutationofjb/tasks/conversationtask.h" -#include "mutationofjb/tasks/taskmanager.h" + #include "mutationofjb/assets.h" +#include "mutationofjb/conversationlinelist.h" #include "mutationofjb/game.h" #include "mutationofjb/gamedata.h" #include "mutationofjb/gui.h" +#include "mutationofjb/tasks/saytask.h" +#include "mutationofjb/tasks/taskmanager.h" #include "mutationofjb/util.h" #include "mutationofjb/widgets/conversationwidget.h" namespace MutationOfJB { void ConversationTask::start() { + setState(RUNNING); + Game &game = getTaskManager()->getGame(); ConversationWidget &widget = game.getGui().getConversationWidget(); widget.setCallback(this); widget.setVisible(true); - updateWidget(); + _currentLineIndex = 0; + + showChoicesOrPick(); } void ConversationTask::update() { -} + if (_sayTask) { + if (_sayTask->getState() == Task::FINISHED) { + getTaskManager()->removeTask(_sayTask); + delete _sayTask; + _sayTask = nullptr; -void ConversationTask::onResponseClicked(ConversationWidget *, int response) { + switch (_substate) { + case SAYING_NO_CHOICES: + finish(); + break; + case SAYING_CHOICE: { + const ConversationLineList& responseList = getTaskManager()->getGame().getAssets().getResponseList(); + const ConversationLineList::Line *const line = responseList.getLine(_currentItem->_response); - uint8 nextLineIndex = _convInfo._lines[_currentLine]._items[response]._nextLineIndex; - if (nextLineIndex == 0) { - setState(FINISHED); - Game &game = getTaskManager()->getGame(); - ConversationWidget &widget = game.getGui().getConversationWidget(); - widget.setVisible(false); - game.getGui().markDirty(); // TODO: Handle automatically when changing visibility. - return; + _sayTask = new SayTask(line->_speeches[0]._text, _convInfo._color); + getTaskManager()->addTask(_sayTask); + _substate = SAYING_RESPONSE; + break; + } + case SAYING_RESPONSE: { + if (_currentItem->_nextLineIndex == 0) { + finish(); + } else { + _currentLineIndex = _currentItem->_nextLineIndex - 1; + showChoicesOrPick(); + } + break; + } + default: + break; + } + } } +} - _currentLine = nextLineIndex - 1; - updateWidget(); +void ConversationTask::onChoiceClicked(ConversationWidget *convWidget, int, uint32 data) { + const ConversationInfo::Item &item = getCurrentLine()->_items[data]; + convWidget->clearChoices(); + + const ConversationLineList& toSayList = getTaskManager()->getGame().getAssets().getToSayList(); + _sayTask = new SayTask(toSayList.getLine(item._choice)->_speeches[0]._text, _convInfo._color); + getTaskManager()->addTask(_sayTask); + _substate = SAYING_CHOICE; + _currentItem = &item; + getTaskManager()->getGame().getGameData().getCurrentScene()->addExhaustedChoice(_convInfo._context, data + 1, _currentLineIndex + 1); } -void ConversationTask::updateWidget() { +void ConversationTask::showChoicesOrPick() { Game &game = getTaskManager()->getGame(); - ConversationWidget &widget = game.getGui().getConversationWidget(); + GameData &gameData = game.getGameData(); + Scene *const scene = gameData.getScene(_sceneId); + + Common::Array<uint32> itemsWithValidChoices; + Common::Array<uint32> itemsWithValidResponses; + Common::Array<uint32> itemsWithValidNext; + + /* + Collect valid "to say" choices (not exhausted and not empty). + Collect valid responses (not exhausted and not empty). + If there are at least two visible choices, we show them. + If there is just one visible choice, pick it automatically. + If there are no visible choices, automatically pick first valid response. + */ + + const ConversationInfo::Line *const currentLine = getCurrentLine(); + for (ConversationInfo::Items::size_type i = 0; i < currentLine->_items.size(); ++i) { + const ConversationInfo::Item &item = currentLine->_items[i]; + + if (scene->isChoiceExhausted(_convInfo._context, (uint8) i + 1, (uint8) _currentLineIndex + 1)) { + continue; + } + const uint8 choice = item._choice; + const uint8 response = item._response; + const uint8 next = item._nextLineIndex; + + if (choice != 0) { + itemsWithValidChoices.push_back(i); + } - const ConversationLineList& toSayList = game.getAssets().getToSayList(); + if (response != 0) { + itemsWithValidResponses.push_back(i); + } - const ConversationInfo::Line &convLine = _convInfo._lines[_currentLine]; + if (next != 0) { + itemsWithValidNext.push_back(i); + } + } + + if (itemsWithValidChoices.size() > 1) { + ConversationWidget &widget = game.getGui().getConversationWidget(); + const ConversationLineList& toSayList = game.getAssets().getToSayList(); - for (ConversationInfo::Items::size_type i = 0; i < convLine._items.size(); ++i) { - Common::String widgetText; - const uint8 question = convLine._items[i]._question; - if (question != 0) { - const ConversationLineList::Line *line = toSayList.getLine(convLine._items[i]._question); - widgetText = toUpperCP895(line->_speeches[0]._text); + for (Common::Array<uint32>::size_type i = 0; i < itemsWithValidChoices.size() && i < ConversationWidget::CONVERSATION_MAX_CHOICES; ++i) { + const ConversationInfo::Item &item = currentLine->_items[itemsWithValidChoices[i]]; + const ConversationLineList::Line *const line = toSayList.getLine(item._choice); + const Common::String widgetText = toUpperCP895(line->_speeches[0]._text); + widget.setChoice((int) i, widgetText, itemsWithValidChoices[i]); } + _substate = IDLE; + _currentItem = nullptr; + + _haveChoices = true; + } else if (itemsWithValidChoices.size() == 1) { + const ConversationLineList& toSayList = game.getAssets().getToSayList(); + const ConversationInfo::Item &item = currentLine->_items[itemsWithValidChoices.front()]; + const ConversationLineList::Line *const line = toSayList.getLine(item._choice); + + _sayTask = new SayTask(line->_speeches[0]._text, _convInfo._color); + getTaskManager()->addTask(_sayTask); + _substate = SAYING_CHOICE; + _currentItem = &item; + + game.getGameData().getCurrentScene()->addExhaustedChoice(_convInfo._context, itemsWithValidChoices.front() + 1, _currentLineIndex + 1); + + _haveChoices = true; + } else if (!itemsWithValidResponses.empty()) { + const ConversationLineList& responseList = game.getAssets().getResponseList(); + const ConversationInfo::Item &item = currentLine->_items[itemsWithValidResponses.front()]; + const ConversationLineList::Line *const line = responseList.getLine(item._response); - widget.setLine(i, widgetText); + _sayTask = new SayTask(line->_speeches[0]._text, _convInfo._color); + getTaskManager()->addTask(_sayTask); + _substate = SAYING_RESPONSE; + _currentItem = &item; + + _haveChoices = true; + } else if (!itemsWithValidNext.empty()) { + _currentLineIndex = currentLine->_items[itemsWithValidNext.front()]._nextLineIndex - 1; + showChoicesOrPick(); + } else { + if (_haveChoices) { + finish(); + } else { + _sayTask = new SayTask("Nothing to talk about.", _convInfo._color); // TODO: This is hardcoded in executable. Load it. + getTaskManager()->addTask(_sayTask); + _substate = SAYING_NO_CHOICES; + _currentItem = nullptr; + } } } +const ConversationInfo::Line *ConversationTask::getCurrentLine() const { + return &_convInfo._lines[_currentLineIndex]; +} + +void ConversationTask::finish() { + setState(FINISHED); + + Game &game = getTaskManager()->getGame(); + ConversationWidget &widget = game.getGui().getConversationWidget(); + widget.setVisible(false); + game.getGui().markDirty(); // TODO: Handle automatically when changing visibility. +} + } diff --git a/engines/mutationofjb/tasks/conversationtask.h b/engines/mutationofjb/tasks/conversationtask.h index 5cc0e5f49f..3bcbb6f998 100644 --- a/engines/mutationofjb/tasks/conversationtask.h +++ b/engines/mutationofjb/tasks/conversationtask.h @@ -26,20 +26,37 @@ namespace MutationOfJB { +class SayTask; + class ConversationTask : public Task, public ConversationWidgetCallback { public: - ConversationTask(const ConversationInfo& convInfo) : _convInfo(convInfo), _currentLine(0) {} + ConversationTask(uint8 sceneId, const ConversationInfo& convInfo) : _sceneId(sceneId), _convInfo(convInfo), _currentLineIndex(0), _currentItem(nullptr), _sayTask(nullptr), _substate(IDLE), _haveChoices(false) {} virtual ~ConversationTask() {} virtual void start() override; virtual void update() override; - virtual void onResponseClicked(ConversationWidget *, int response) override; + virtual void onChoiceClicked(ConversationWidget *, int response, uint32 data) override; private: - void updateWidget(); + void showChoicesOrPick(); + const ConversationInfo::Line *getCurrentLine() const; + void finish(); + uint8 _sceneId; const ConversationInfo &_convInfo; - uint _currentLine; + uint _currentLineIndex; + const ConversationInfo::Item *_currentItem; + SayTask* _sayTask; + + enum Substate { + IDLE, + SAYING_CHOICE, + SAYING_RESPONSE, + SAYING_NO_CHOICES + }; + + Substate _substate; + bool _haveChoices; }; } diff --git a/engines/mutationofjb/tasks/saytask.cpp b/engines/mutationofjb/tasks/saytask.cpp new file mode 100644 index 0000000000..2ef4cdf5df --- /dev/null +++ b/engines/mutationofjb/tasks/saytask.cpp @@ -0,0 +1,55 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mutationofjb/tasks/saytask.h" + +#include "mutationofjb/tasks/taskmanager.h" +#include "mutationofjb/assets.h" +#include "mutationofjb/game.h" +#include "mutationofjb/gamedata.h" +#include "mutationofjb/room.h" + +#include "graphics/managed_surface.h" +#include "graphics/screen.h" + +namespace MutationOfJB { + +SayTask::SayTask(const Common::String &toSay, uint8 color) : _toSay(toSay), _color(color), _timer(1000) {} + +void SayTask::start() { + + getTaskManager()->getGame().getAssets().getSpeechFont().drawString(_toSay, _color, 0, 0, getTaskManager()->getGame().getScreen()); + _timer.start(); + setState(RUNNING); +} + +void SayTask::update() { + _timer.update(); + + if (_timer.isFnished()) { + getTaskManager()->getGame().getRoom().redraw(); // TODO: Only redraw the area occupied by the text. + setState(FINISHED); + return; + } +} + +} diff --git a/engines/mutationofjb/tasks/saytask.h b/engines/mutationofjb/tasks/saytask.h new file mode 100644 index 0000000000..a7ac96d875 --- /dev/null +++ b/engines/mutationofjb/tasks/saytask.h @@ -0,0 +1,44 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mutationofjb/tasks/task.h" + +#include "mutationofjb/timer.h" + +#include "common/str.h" + +namespace MutationOfJB { + +class SayTask : public Task { +public: + SayTask(const Common::String &toSay, uint8 color); + + virtual void start() override; + virtual void update() override; + +private: + Common::String _toSay; + uint8 _color; + Timer _timer; +}; + +} diff --git a/engines/mutationofjb/tasks/task.h b/engines/mutationofjb/tasks/task.h index 7b43868269..1b98097b9c 100644 --- a/engines/mutationofjb/tasks/task.h +++ b/engines/mutationofjb/tasks/task.h @@ -20,6 +20,9 @@ * */ +#ifndef MUTATIONOFJB_TASK_H +#define MUTATIONOFJB_TASK_H + #include "common/scummsys.h" namespace MutationOfJB { @@ -54,3 +57,5 @@ private: }; } + +#endif diff --git a/engines/mutationofjb/tasks/taskmanager.cpp b/engines/mutationofjb/tasks/taskmanager.cpp index 981654981f..7fbf64dc9b 100644 --- a/engines/mutationofjb/tasks/taskmanager.cpp +++ b/engines/mutationofjb/tasks/taskmanager.cpp @@ -40,7 +40,9 @@ void TaskManager::removeTask(Task *task) { void TaskManager::update() { for (Tasks::const_iterator it = _tasks.begin(); it != _tasks.end(); ++it) { - (*it)->update(); + if ((*it)->getState() == Task::RUNNING) { + (*it)->update(); + } } } |