Permalink
Browse files

MUTATIONOFJB: Improve documentation and naming.

  • Loading branch information...
LubomirR committed Aug 4, 2018
1 parent b670a66 commit f2014a9f08dbd97b4ce7bfc8df675b3ce920b505
@@ -26,7 +26,7 @@
#include "common/str.h"

/** @file
* "CAMEFROM" <sceneId>
* "CAMEFROM " <sceneId>
*
* This command tests whether last scene (the scene player came from) is sceneId.
* If true, the execution continues after this command.
@@ -25,8 +25,6 @@
#include "mutationofjb/gamedata.h"
#include "common/translation.h"

namespace MutationOfJB {

/** @file
* "CHANGE" <entity> " " <register> " " <sceneId> " " <entityId> " " <value>
*
@@ -43,6 +41,8 @@ namespace MutationOfJB {
* <value> *B Value (variable length).
*/

namespace MutationOfJB {

bool ChangeCommandParser::parseValueString(const Common::String &valueString, bool changeEntity, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister &reg, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv) {
if (changeEntity) {
if (valueString.size() < 8) {
@@ -33,18 +33,56 @@ class Command;
class ScriptExecutionContext;
class ScriptParseContext;

/**
* Base class for command parsers.
*
* The parser's main job is to create a Command instance from input line.
*/
class CommandParser {
public:
virtual ~CommandParser();

/**
* Parses the specified line and possibly returns a Command instance.
*
* @param line Line to parse.
* @param parseCtx Parse context.
* @param command Output parameter for newly created command.
* @return True if the line has been successfully parsed by this parser, false otherwise.
* @note You may return true and set command to nullptr.
* That means the line has been successfully parsed, but no command is needed.
*/
virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) = 0;

/* Old command - created by this parser. */
/**
* Called when transitioning parsing between two commands.
*
* For example, cmdParserA->transition(parseCtx, cmdA, cmdB, cmdParserB) is called after command B is done parsing
* to notify command A parser about the transition from command A to command B.
* This is useful for sequential commands, because at the time command A is being parsed,
* we don't have any information about command B, so we cannot set the next pointer.
* Transition method can be used to set the next pointer after command B is available.
*
* @param parseCtx Parse context.
* @param oldCommand Old command (created by this parser).
* @param newCommand New command (created by newCommandParser).
* @param newCommandParser Command parser which created the new command.
*/
virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser);

/* Called after parsing. */
/**
* Called after the whole script is parsed.
*
* Can be used for cleanup.
*
* @param parseCtx Parse context.
*/
virtual void finish(ScriptParseContext &parseCtx);
};

/**
* Base class for script commands.
*/
class Command {
public:
enum ExecuteResult {
@@ -60,6 +98,7 @@ class Command {

virtual Common::String debugString() const = 0;
};

}

#endif
@@ -25,6 +25,22 @@
#include "mutationofjb/game.h"
#include "common/debug.h"

/** @file
* "DEFINE_STRUCT " <numItemGroups> " " <context> " " <objectId> " " <colorString> <CRLF>
* <itemGroup> { <CRLF> <itemGroup> }
*
* item ::= <questionIndex> " " <responseIndex> " " <nextGroup>
* itemGroup ::= <item> " " <item> " " <item> " " <item> " " <item>
*
* Defines the flow of an interactive conversation.
*
* Every item group consists of 5 conversation items.
* "questionIndex" and "responseIndex" specify what the player and the responder say when the conversation item is selected.
* They refer to the line numbers of TOSAY.GER and RESPONSE.GER, respectively.
* "nextGroup" refers to the group that follows when the conversation item is selected. A value of 0 indicates end of
* conversation.
*/

namespace MutationOfJB {

bool DefineStructCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
@@ -52,19 +68,19 @@ bool DefineStructCommandParser::parse(const Common::String &line, ScriptParseCon

const char *linePtr = convLineStr.c_str();

ConversationInfo::Line convLine;
ConversationInfo::ItemGroup convGroup;

for (int j = 0; j < 5; ++j) {
ConversationInfo::Item convItem;
convItem._choice = atoi(linePtr);
convItem._question = atoi(linePtr);
linePtr += 6;
convItem._response = atoi(linePtr);
linePtr += 6;
convItem._nextLineIndex = atoi(linePtr);
convItem._nextGroupIndex = atoi(linePtr);
linePtr += 3;
convLine._items.push_back(convItem);
convGroup.push_back(convItem);
}
convInfo._lines.push_back(convLine);
convInfo._itemGroups.push_back(convGroup);
}

command = new DefineStructCommand(convInfo);
@@ -28,16 +28,19 @@
#include "common/translation.h"

/** @file
* ("#L " | "-L ") <object>
* ("#W " | "-W ") <object>
* ("#T " | "-T ") <object>
* ("#P " | "-P ") <object1>
* ("#U " | "-U ") <object1> [<object2>]
* ("#ELSE" | "-ELSE") [<tag>]
* "#MACRO " <name>
* "#EXTRA" <name>
* <look> | <walk> | <talk> | <pickup> | <use> | <else> | <macro> | <extra> | <endRandom>
*
* If a line starts with '#', '=', '-', it is treated as the end of a section.
* look ::= ("#L " | "-L ") <object>
* walk ::= ("#W " | "-W ") <object>
* talk ::= ("#T " | "-T ") <object>
* pickup ::= ("#P " | "-P ") <object1>
* use ::= ("#U " | "-U ") <object1> [<object2>]
* else ::= ("#ELSE" | "-ELSE") [<tag>]
* macro ::= "#MACRO " <name>
* extra ::= "#EXTRA" <name>
* endRandom ::= "\"
*
* 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.
*
* #L (look), #W (walk), #T (talk), #U (use) sections are executed
@@ -49,6 +52,8 @@
* #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).
*
* TODO: TIMERPROC.
*/

namespace MutationOfJB {
@@ -28,7 +28,7 @@
#include "common/translation.h"

/** @file
* "IFITEM" <item> ["!"]
* "IFITEM " <item> [ "!" ]
*
* IFITEM command tests whether an item is in the inventory.
* If it is, execution continues to the next line.
@@ -25,7 +25,7 @@
#include "mutationofjb/gamedata.h"

/** @file
* "DELITEM" " " <item>
* "DELITEM " <item>
*
* Removes item from inventory.
*/
@@ -33,8 +33,10 @@
#include "common/debug-channels.h"

/** @file
* ("SM" | "SLM" | "NM" | "NLM") " " <lineToSay> ["<" <voiceFile> | "<!"]
* <skipped> " " <lineToSay> ("<" <voiceFile> | "<!")
* <firstLine> { <CRLF> <additionalLine> }
*
* firstLine ::= ("SM" | "SLM" | "NM" | "NLM") " " <lineToSay> [ "<" <voiceFile> | "<!" ]
* additionalLine ::= <skipped> " " <lineToSay> ( "<" <voiceFile> | "<!" )
*
* Say command comes in four variants: SM, SLM, NM and NLM.
* Note: In script files, they are usually written as *SM.
@@ -33,6 +33,9 @@ class SeqCommandParser : public CommandParser {
virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
};

/**
* Base class for sequential commands.
*/
class SeqCommand : public Command {
public:
SeqCommand() : _nextCommand(nullptr) {}
@@ -29,6 +29,17 @@

#include "common/str.h"

/** @file
* "TALK TO HIM" [ " " <mode> ]
*
* Begins interactive conversation defined by DefineStructCommand.
* The command supports multiple modes:
* 0 - normal mode,
* 1 - Ray and Buttleg mode (two responders),
* 2 - unknown (unused) mode,
* 3 - carnival ticket seller mode (special animation).
*/

namespace MutationOfJB {

bool TalkCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
@@ -136,10 +136,10 @@ bool Scene::loadFromStream(Common::ReadStream &stream) {
_palRotFirst = stream.readByte();
_palRotLast = stream.readByte();
_palRotDelay = stream.readByte();
_exhaustedChoiceNext = stream.readByte();
_exhaustedConvItemNext = stream.readByte();

for (i = 0; i < 79; ++i) {
_exhaustedChoices[i]._encodedData = stream.readByte();
_exhaustedConvItems[i]._encodedData = stream.readByte();
}

return true;
@@ -226,15 +226,15 @@ Bitmap *Scene::findBitmap(int16 x, int16 y, int *index) {
return nullptr;
}

void Scene::addExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceIndexList) {
_exhaustedChoices[_exhaustedChoiceNext - 1] = ExhaustedChoice(context, choiceIndex, choiceIndexList);
_exhaustedChoiceNext++;
void Scene::addExhaustedConvItem(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) {
_exhaustedConvItems[_exhaustedConvItemNext - 1] = ExhaustedConvItem(context, convItemIndex, convGroupIndex);
_exhaustedConvItemNext++;
}

bool Scene::isChoiceExhausted(uint8 context, uint8 choiceIndex, uint8 choiceListIndex) const {
for (uint i = 0; i < _exhaustedChoiceNext - 1; ++i) {
const ExhaustedChoice &choice = _exhaustedChoices[i];
if (choice.getContext() == context && choice.getChoiceIndex() == choiceIndex && choice.getChoiceListIndex() == choiceListIndex) {
bool Scene::isConvItemExhausted(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) const {
for (uint8 i = 0; i < _exhaustedConvItemNext - 1; ++i) {
const ExhaustedConvItem &convItem = _exhaustedConvItems[i];
if (convItem.getContext() == context && convItem.getConvItemIndex() == convItemIndex && convItem.getConvGroupIndex() == convGroupIndex) {
return true;
}
}
@@ -225,29 +225,29 @@ struct Bitmap {
};

/**
* Encoded exhausted choice.
* Encoded exhausted convesation item.
*/
struct ExhaustedChoice {
struct ExhaustedConvItem {
/**
* 1 bit - context
* 3 bits - choice index
* 4 bits - choice list index
* 1 bit - context.
* 3 bits - conversation item index.
* 4 bits - conversation group index.
*/
uint8 _encodedData;

uint8 getContext() const {
return (_encodedData >> 7) & 0x1;
}
uint8 getChoiceIndex() const {
uint8 getConvItemIndex() const {
return (_encodedData >> 4) & 0x7;
}
uint8 getChoiceListIndex() const {
uint8 getConvGroupIndex() const {
return _encodedData & 0xF;
}

ExhaustedChoice() : _encodedData(0) {}
ExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceListIndex) :
_encodedData(((context & 0x1) << 7) | ((choiceIndex & 0x7) << 4) | (choiceListIndex & 0xF)) {}
ExhaustedConvItem() : _encodedData(0) {}
ExhaustedConvItem(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) :
_encodedData(((context & 0x1) << 7) | ((convItemIndex & 0x7) << 4) | (convGroupIndex & 0xF)) {}
};

struct Scene {
@@ -263,8 +263,8 @@ struct Scene {
Static *findStatic(int16 x, int16 y, int *index = nullptr);
Bitmap *findBitmap(int16 x, int16 y, int *index = nullptr);

void addExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceIndexList);
bool isChoiceExhausted(uint8 context, uint8 choiceIndex, uint8 choiceIndexList) const;
void addExhaustedConvItem(uint8 context, uint8 convItemIndex, uint8 convGroupIndex);
bool isConvItemExhausted(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) const;

/** Refers to the script block that will be executed when you enter this scene (DS register). */
uint8 _startup;
@@ -298,28 +298,25 @@ struct Scene {
uint8 _palRotDelay;

/**
* Points to the first free item in exhausted choices list.
* Points to the first free item in exhausted conversation item array.
* @note Indexed from 1.
*/
uint8 _exhaustedChoiceNext;
ExhaustedChoice _exhaustedChoices[79];
uint8 _exhaustedConvItemNext;
ExhaustedConvItem _exhaustedConvItems[79];

bool loadFromStream(Common::ReadStream &stream);
};

struct ConversationInfo {
struct Item {
uint8 _choice;
uint8 _question;
uint8 _response;
uint8 _nextLineIndex;
uint8 _nextGroupIndex;
};

typedef Common::Array<Item> Items;
struct Line {
Items _items;
};
typedef Common::Array<Item> ItemGroup;

Common::Array<Line> _lines;
Common::Array<ItemGroup> _itemGroups;
uint8 _context;
uint8 _objectId;
uint8 _color;
Oops, something went wrong.

0 comments on commit f2014a9

Please sign in to comment.