Permalink
Browse files

MUTATIONOFJB: Run extra sections from conversation.

  • Loading branch information...
LubomirR authored and sev- committed Jul 15, 2018
1 parent d22da95 commit d358a65bbc57ab9099620bf2309893f99dbf164c
@@ -35,6 +35,7 @@
("#U " | "-U ") <object1> [<object2>]
("#ELSE" | "-ELSE") [<tag>]
"#MACRO " <name>
"#EXTRA" <name>
If a line starts with '#', '=', '-', it is treated as the end of a section.
However, at the same time it can also start a new section depending on what follows.
@@ -46,6 +47,8 @@
#ELSE is used by conditional commands (see comments for IfCommand and others).
#MACRO starts a new macro. Global script can call macros from local script and vice versa.
#EXTRA defines an "extra" section. This is called from dialog responses ("TALK TO HIM" command).
*/

namespace MutationOfJB {
@@ -119,6 +122,9 @@ bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext
const uint8 startupId = atoi(line.c_str() + 9);
IdAndCommand ic = {startupId, command};
_foundStartups.push_back(ic);
} else if (line.size() >= 7 && line.hasPrefix("#EXTRA")) {
NameAndCommand nc = {line.c_str() + 6, command};
_foundExtras.push_back(nc);
}

if (firstChar == '#') {
@@ -183,6 +189,23 @@ void EndBlockCommandParser::transition(ScriptParseContext &parseCtx, Command *ol
}
}
}
if (!_foundExtras.empty()) {
if (newCommand) {
for (NameAndCommandArray::iterator it = _foundExtras.begin(); it != _foundExtras.end();) {
if (it->_command != oldCommand) {
it++;
continue;
}

if (!parseCtx._extras.contains(it->_name)) {
parseCtx._extras[it->_name] = newCommand;
} else {
warning(_("Extra '%s' already exists"), it->_name.c_str());
}
it = _foundExtras.erase(it);
}
}
}

if (newCommandParser != this) {
if (!_pendingActionInfos.empty()) {
@@ -208,9 +231,13 @@ void EndBlockCommandParser::finish(ScriptParseContext &) {
if (!_foundStartups.empty()) {
debug("Problem: Found startups from end block parser is not empty!");
}
if (!_foundExtras.empty()) {
debug("Problem: Found extras from end block parser is not empty!");
}
_pendingActionInfos.clear();
_foundMacros.clear();
_foundStartups.clear();
_foundExtras.clear();
}

Command::ExecuteResult EndBlockCommand::execute(ScriptExecutionContext &scriptExecCtx) {
@@ -56,6 +56,7 @@ class EndBlockCommandParser : public CommandParser {
typedef Common::Array<IdAndCommand> IdAndCommandArray;
NameAndCommandArray _foundMacros;
IdAndCommandArray _foundStartups;
NameAndCommandArray _foundExtras;
};

class EndBlockCommand : public Command {
@@ -56,8 +56,8 @@ bool ConversationLineList::parseFile(const Common::String &fileName) {

Common::String::iterator endIt = Common::find(lineStr.begin(), lineStr.end(), '|');
if (endIt != lineStr.end()) {
Common::String extra = lineStr + endIt;
if (*endIt == 'X') {
endIt++;
if (endIt != lineStr.end() && *endIt == 'X') {
line._extra = Common::String(endIt + 1, lineStr.end()); // Skip 'X' char.
}
}
@@ -202,6 +202,7 @@ Common::Error MutationOfJBEngine::run() {
_game->setCurrentAction(ActionInfo::PickUp);
break;
}
break;
}
default:
break;
@@ -189,6 +189,23 @@ Command *ScriptExecutionContext::getMacro(const Common::String &name) const {
return cmd;
}

Command *ScriptExecutionContext::getExtra(const Common::String &name) const {
Command *cmd = nullptr;

Script *const localScript = _localScriptOverride ? _localScriptOverride : _game.getLocalScript();
Script *const globalScript = _game.getGlobalScript();

if (localScript) {
cmd = localScript->getExtra(name);
}

if (!cmd && globalScript) {
cmd = globalScript->getExtra(name);
}

return cmd;
}

bool Script::loadFromStream(Common::SeekableReadStream &stream) {
destroy();

@@ -236,6 +253,7 @@ bool Script::loadFromStream(Common::SeekableReadStream &stream) {

_macros = parseCtx._macros;
_startups = parseCtx._startups;
_extras = parseCtx._extras;

return true;
}
@@ -285,4 +303,13 @@ Command *Script::getStartup(uint8 startupId) const {
return it->_value;
}

Command *Script::getExtra(const Common::String &name) const {
Extras::const_iterator it = _extras.find(name);
if (it == _extras.end()) {
return nullptr;
}

return it->_value;
}

}
@@ -67,6 +67,7 @@ typedef Common::Array<ActionInfo> ActionInfos;
typedef Common::Array<GotoCommand *> GotoCommands;
typedef Common::HashMap<Common::String, Command *> Macros;
typedef Common::HashMap<uint8, Command *> Startups;
typedef Common::HashMap<Common::String, Command *> Extras;

class ScriptParseContext {
public:
@@ -98,6 +99,7 @@ class ScriptParseContext {
ActionInfos _actionInfos;
Macros _macros;
Startups _startups;
Extras _extras;

private:
};
@@ -116,6 +118,7 @@ class ScriptExecutionContext {
Game &getGame();
GameData &getGameData();
Command *getMacro(const Common::String &name) const;
Command *getExtra(const Common::String &name) const;

private:
Game &_game;
@@ -135,13 +138,15 @@ class Script {
const Startups &getStartups() const;
Command *getMacro(const Common::String &name) const;
Command *getStartup(uint8 startupId) const;
Command *getExtra(const Common::String &name) const;

private:
void destroy();
Commands _allCommands;
ActionInfos _actionInfos[5];
Macros _macros;
Startups _startups;
Extras _extras;
};

}
@@ -27,11 +27,14 @@
#include "mutationofjb/game.h"
#include "mutationofjb/gamedata.h"
#include "mutationofjb/gui.h"
#include "mutationofjb/script.h"
#include "mutationofjb/tasks/saytask.h"
#include "mutationofjb/tasks/taskmanager.h"
#include "mutationofjb/util.h"
#include "mutationofjb/widgets/conversationwidget.h"

#include "common/translation.h"

namespace MutationOfJB {

void ConversationTask::start() {
@@ -69,11 +72,11 @@ void ConversationTask::update() {
break;
}
case SAYING_RESPONSE: {
if (_currentItem->_nextLineIndex == 0) {
finish();
} else {
_currentLineIndex = _currentItem->_nextLineIndex - 1;
showChoicesOrPick();
startExtra();

if (_substate != RUNNING_EXTRA)
{
gotoNextLine();
}
break;
}
@@ -82,6 +85,16 @@ void ConversationTask::update() {
}
}
}

if (_innerExecCtx) {
Command::ExecuteResult res = _innerExecCtx->runActiveCommand();
if (res == Command::Finished) {
delete _innerExecCtx;
_innerExecCtx = nullptr;

gotoNextLine();
}
}
}

void ConversationTask::onChoiceClicked(ConversationWidget *convWidget, int, uint32 data) {
@@ -203,4 +216,35 @@ void ConversationTask::finish() {
game.getGui().markDirty(); // TODO: Handle automatically when changing visibility.
}

void ConversationTask::startExtra() {
const ConversationLineList& responseList = getTaskManager()->getGame().getAssets().getResponseList();
const ConversationLineList::Line *const line = responseList.getLine(_currentItem->_response);
if (!line->_extra.empty()) {
_innerExecCtx = new ScriptExecutionContext(getTaskManager()->getGame());
Command *const extraCmd = _innerExecCtx->getExtra(line->_extra);
if (extraCmd) {
Command::ExecuteResult res = _innerExecCtx->startCommand(extraCmd);
if (res == Command::InProgress) {
_substate = RUNNING_EXTRA;
} else {
delete _innerExecCtx;
_innerExecCtx = nullptr;
}
} else {
warning(_("Extra '%s' not found"), line->_extra.c_str());
delete _innerExecCtx;
_innerExecCtx = nullptr;
}
}
}

void ConversationTask::gotoNextLine() {
if (_currentItem->_nextLineIndex == 0) {
finish();
} else {
_currentLineIndex = _currentItem->_nextLineIndex - 1;
showChoicesOrPick();
}
}

}
@@ -27,10 +27,11 @@
namespace MutationOfJB {

class SayTask;
class ScriptExecutionContext;

class ConversationTask : public Task, public ConversationWidgetCallback {
public:
ConversationTask(uint8 sceneId, const ConversationInfo& convInfo) : _sceneId(sceneId), _convInfo(convInfo), _currentLineIndex(0), _currentItem(nullptr), _sayTask(nullptr), _substate(IDLE), _haveChoices(false) {}
ConversationTask(uint8 sceneId, const ConversationInfo& convInfo) : _sceneId(sceneId), _convInfo(convInfo), _currentLineIndex(0), _currentItem(nullptr), _sayTask(nullptr), _substate(IDLE), _haveChoices(false), _innerExecCtx(nullptr) {}
virtual ~ConversationTask() {}

virtual void start() override;
@@ -41,6 +42,8 @@ class ConversationTask : public Task, public ConversationWidgetCallback {
void showChoicesOrPick();
const ConversationInfo::Line *getCurrentLine() const;
void finish();
void startExtra();
void gotoNextLine();

uint8 _sceneId;
const ConversationInfo &_convInfo;
@@ -52,11 +55,13 @@ class ConversationTask : public Task, public ConversationWidgetCallback {
IDLE,
SAYING_CHOICE,
SAYING_RESPONSE,
SAYING_NO_CHOICES
SAYING_NO_CHOICES,
RUNNING_EXTRA
};

Substate _substate;
bool _haveChoices;
ScriptExecutionContext *_innerExecCtx;
};

}

0 comments on commit d358a65

Please sign in to comment.