aboutsummaryrefslogtreecommitdiff
path: root/engines/mutationofjb/tasks/conversationtask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mutationofjb/tasks/conversationtask.cpp')
-rw-r--r--engines/mutationofjb/tasks/conversationtask.cpp173
1 files changed, 148 insertions, 25 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.
+}
+
}