aboutsummaryrefslogtreecommitdiff
path: root/engines/mutationofjb/tasks
diff options
context:
space:
mode:
authorĽubomír Remák2018-07-15 00:18:54 +0200
committerEugene Sandulenko2018-08-25 23:12:01 +0200
commitfebff83a4edc89e1dbc6f4c56f5531f0eb8f3287 (patch)
tree756129c1736a39aad5473d7873810a3a742911ae /engines/mutationofjb/tasks
parentd2e354b51f637dc2e9b251256b5a017cb41cfe59 (diff)
downloadscummvm-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.cpp173
-rw-r--r--engines/mutationofjb/tasks/conversationtask.h25
-rw-r--r--engines/mutationofjb/tasks/saytask.cpp55
-rw-r--r--engines/mutationofjb/tasks/saytask.h44
-rw-r--r--engines/mutationofjb/tasks/task.h5
-rw-r--r--engines/mutationofjb/tasks/taskmanager.cpp4
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();
+ }
}
}