Initial commit
This commit is contained in:
1
engines/mutationofjb/POTFILES
Normal file
1
engines/mutationofjb/POTFILES
Normal file
@@ -0,0 +1 @@
|
||||
engines/mutationofjb/util.cpp
|
||||
240
engines/mutationofjb/animationdecoder.cpp
Normal file
240
engines/mutationofjb/animationdecoder.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/animationdecoder.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/util.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
AnimationDecoder::AnimationDecoder(const Common::Path &fileName) : _fileName(fileName), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {
|
||||
_surface.create(IMAGE_WIDTH, IMAGE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_owningSurface = true;
|
||||
}
|
||||
|
||||
AnimationDecoder::AnimationDecoder(const Common::Path &fileName, const Graphics::Surface &outSurface) : _fileName(fileName), _surface(outSurface), _owningSurface(false), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {}
|
||||
|
||||
bool AnimationDecoder::decode(AnimationDecoderCallback *callback) {
|
||||
EncryptedFile file;
|
||||
file.open(_fileName);
|
||||
|
||||
if (!file.isOpen()) {
|
||||
reportFileMissingError(_fileName.toString(Common::Path::kNativeSeparator).c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
file.seek(0, SEEK_END);
|
||||
const int32 endPos = file.pos();
|
||||
|
||||
// Skip header - we don't need it anyway.
|
||||
file.seek(0x80);
|
||||
|
||||
int frameNo = 0;
|
||||
|
||||
while (file.pos() != endPos) {
|
||||
// Record.
|
||||
const uint32 length = file.readUint32LE();
|
||||
const uint16 recordId = file.readUint16LE();
|
||||
const uint16 subrecords = file.readUint16LE();
|
||||
|
||||
// Skip 8 empty bytes.
|
||||
file.seek(8, SEEK_CUR);
|
||||
|
||||
// Subrecords.
|
||||
if (recordId == 0xF1FA) {
|
||||
if ((_fromFrame != -1 && frameNo < _fromFrame) || (_toFrame != -1 && frameNo > _toFrame)) {
|
||||
file.seek(length - 16, SEEK_CUR);
|
||||
} else {
|
||||
if (subrecords == 0) {
|
||||
if (callback) {
|
||||
callback->onFrame(frameNo, _surface); // Empty record, frame identical to the previous one.
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < subrecords; ++i) {
|
||||
int32 filePos = file.pos();
|
||||
|
||||
const uint32 subLength = file.readUint32LE();
|
||||
const uint16 type = file.readUint16LE();
|
||||
|
||||
if (type == 0x0B) {
|
||||
loadPalette(file);
|
||||
if (callback) {
|
||||
callback->onPaletteUpdated(_palette);
|
||||
}
|
||||
} else if (type == 0x0F) {
|
||||
loadFullFrame(file, subLength - 6);
|
||||
if (callback) {
|
||||
callback->onFrame(frameNo, _surface);
|
||||
}
|
||||
} else if (type == 0x0C) {
|
||||
loadDiffFrame(file, subLength - 6);
|
||||
if (callback) {
|
||||
callback->onFrame(frameNo, _surface);
|
||||
}
|
||||
} else {
|
||||
debug("Unsupported record type %02X.", type);
|
||||
file.seek(subLength - 6, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Makes decoding more robust, because for some reason records might have extra data at the end.
|
||||
file.seek(filePos + subLength, SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
frameNo++;
|
||||
} else {
|
||||
file.seek(length - 16, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationDecoder::setPartialMode(int fromFrame, int toFrame, const Common::Rect &area, uint8 threshold) {
|
||||
_fromFrame = fromFrame;
|
||||
_toFrame = toFrame;
|
||||
_area = area;
|
||||
_threshold = threshold;
|
||||
}
|
||||
|
||||
void AnimationDecoder::loadPalette(Common::SeekableReadStream &file) {
|
||||
uint16 packets = file.readUint16LE();
|
||||
const uint8 skipCount = file.readByte();
|
||||
int copyCount = file.readByte();
|
||||
if (copyCount == 0) {
|
||||
copyCount = PALETTE_COLORS;
|
||||
}
|
||||
|
||||
while (packets--) {
|
||||
file.read(_palette + skipCount * 3, copyCount * 3);
|
||||
|
||||
for (int j = skipCount * 3; j < (skipCount + copyCount) * 3; ++j) {
|
||||
_palette[j] <<= 2; // Uses 6-bit colors.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationDecoder::loadFullFrame(EncryptedFile &file, uint32 size) {
|
||||
uint8 *const pixels = reinterpret_cast<uint8 *>(_surface.getPixels());
|
||||
uint8 *ptr = pixels;
|
||||
uint32 readBytes = 0;
|
||||
uint32 lines = 0;
|
||||
|
||||
while (readBytes != size) {
|
||||
if (lines == 200) {
|
||||
// Some full frames have an unknown byte at the end,
|
||||
// so break when we encounter all 200 lines.
|
||||
break;
|
||||
}
|
||||
|
||||
uint8 no = file.readByte();
|
||||
readBytes++;
|
||||
while (no--) {
|
||||
uint8 n = file.readByte();
|
||||
readBytes++;
|
||||
if (n < 0x80) {
|
||||
// RLE - Copy color n times.
|
||||
uint8 color = file.readByte();
|
||||
readBytes++;
|
||||
while (n--) {
|
||||
*ptr++ = color;
|
||||
}
|
||||
} else {
|
||||
// Take next 0x100 - n bytes as they are.
|
||||
const uint32 rawlen = 0x100 - n;
|
||||
file.read(ptr, rawlen);
|
||||
readBytes += rawlen;
|
||||
ptr += rawlen;
|
||||
}
|
||||
}
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) {
|
||||
const uint16 firstLine = file.readUint16LE();
|
||||
const uint16 numLines = file.readUint16LE();
|
||||
|
||||
for (uint16 line = firstLine; line < firstLine + numLines; ++line) {
|
||||
uint8 *imageData = reinterpret_cast<uint8 *>(_surface.getBasePtr(0, line));
|
||||
uint16 lineOffset = 0;
|
||||
|
||||
// Optimization for skipping the whole line if outside of confined area.
|
||||
const bool skipLineOutput = !_area.isEmpty() && (line < _area.top || line >= _area.bottom);
|
||||
uint8 buf[0x80];
|
||||
|
||||
uint8 runs = file.readByte();
|
||||
while (runs--) {
|
||||
uint8 localOffset = file.readByte();
|
||||
uint8 num = file.readByte();
|
||||
|
||||
imageData += localOffset;
|
||||
lineOffset += localOffset;
|
||||
if (num == 0) {
|
||||
// Ignore?
|
||||
debug("Zero RLE number found.");
|
||||
} else if (num < 0x80) {
|
||||
if (!skipLineOutput) {
|
||||
if (_area.isEmpty() && _threshold == 0xFF) {
|
||||
file.read(imageData, num);
|
||||
} else {
|
||||
file.read(buf, num);
|
||||
for (uint16 i = 0; i < num; i++) {
|
||||
if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold)
|
||||
imageData[i] = buf[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file.skip(num);
|
||||
}
|
||||
|
||||
imageData += num;
|
||||
lineOffset += num;
|
||||
} else {
|
||||
const uint8 color = file.readByte();
|
||||
const int no = 0x100 - num;
|
||||
if (!skipLineOutput) {
|
||||
if (_area.isEmpty() && _threshold == 0xFF) {
|
||||
memset(imageData, color, no);
|
||||
} else {
|
||||
for (int i = 0; i < no; i++) {
|
||||
if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold)
|
||||
imageData[i] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
imageData += no;
|
||||
lineOffset += no;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimationDecoder::~AnimationDecoder() {
|
||||
if (_owningSurface)
|
||||
_surface.free();
|
||||
}
|
||||
|
||||
}
|
||||
86
engines/mutationofjb/animationdecoder.h
Normal file
86
engines/mutationofjb/animationdecoder.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ANIMATIONDECODER_H
|
||||
#define MUTATIONOFJB_ANIMATIONDECODER_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/path.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
enum {
|
||||
PALETTE_COLORS = 256,
|
||||
PALETTE_SIZE = PALETTE_COLORS * 3,
|
||||
IMAGE_WIDTH = 320,
|
||||
IMAGE_HEIGHT = 200
|
||||
};
|
||||
|
||||
class AnimationDecoderCallback {
|
||||
public:
|
||||
virtual void onFrame(int frameNo, Graphics::Surface &surface) = 0;
|
||||
virtual void onPaletteUpdated(byte palette[PALETTE_SIZE]) = 0;
|
||||
virtual ~AnimationDecoderCallback() {}
|
||||
};
|
||||
|
||||
class AnimationDecoder {
|
||||
public:
|
||||
AnimationDecoder(const Common::Path &fileName);
|
||||
AnimationDecoder(const Common::Path &fileName, const Graphics::Surface &outSurface);
|
||||
~AnimationDecoder();
|
||||
bool decode(AnimationDecoderCallback *callback);
|
||||
|
||||
/**
|
||||
* Enables partial decoding mode.
|
||||
*
|
||||
* @param fromFrame Frame to start decoding on (inclusive).
|
||||
* @param toFrame Frame to end decoding on (inclusive).
|
||||
* @param area Output surface will be confined to this area.
|
||||
* @param threshold Source pixels with color index above this threshold will not be replaced.
|
||||
*/
|
||||
void setPartialMode(int fromFrame, int toFrame, const Common::Rect &area = Common::Rect(), uint8 threshold = 0xFF);
|
||||
|
||||
private:
|
||||
void loadPalette(Common::SeekableReadStream &stream);
|
||||
void loadFullFrame(EncryptedFile &file, uint32 size);
|
||||
void loadDiffFrame(EncryptedFile &file, uint32 size);
|
||||
|
||||
Common::Path _fileName;
|
||||
Graphics::Surface _surface;
|
||||
bool _owningSurface;
|
||||
byte _palette[PALETTE_SIZE];
|
||||
int _fromFrame;
|
||||
int _toFrame;
|
||||
Common::Rect _area;
|
||||
uint8 _threshold;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
52
engines/mutationofjb/assets.cpp
Normal file
52
engines/mutationofjb/assets.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/assets.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
Assets::Assets(Game &game) : _toSayList("tosay.ger"), _responseList("response.ger"), _hardcodedStrings(game) {}
|
||||
|
||||
Font &Assets::getSystemFont() {
|
||||
return _systemFont;
|
||||
}
|
||||
|
||||
Font &Assets::getSpeechFont() {
|
||||
return _speechFont;
|
||||
}
|
||||
|
||||
ConversationLineList &Assets::getToSayList() {
|
||||
return _toSayList;
|
||||
}
|
||||
|
||||
ConversationLineList &Assets::getResponseList() {
|
||||
return _responseList;
|
||||
}
|
||||
|
||||
InventoryItemDefinitionList &Assets::getInventoryItemDefList() {
|
||||
return _invItemDefList;
|
||||
}
|
||||
|
||||
HardcodedStrings &Assets::getHardcodedStrings() {
|
||||
return _hardcodedStrings;
|
||||
}
|
||||
|
||||
}
|
||||
79
engines/mutationofjb/assets.h
Normal file
79
engines/mutationofjb/assets.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ASSETS_H
|
||||
#define MUTATIONOFJB_ASSETS_H
|
||||
|
||||
#include "mutationofjb/font.h"
|
||||
#include "mutationofjb/conversationlinelist.h"
|
||||
#include "mutationofjb/inventoryitemdefinitionlist.h"
|
||||
#include "mutationofjb/hardcodedstrings.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Game;
|
||||
|
||||
class Assets {
|
||||
public:
|
||||
Assets(Game &game);
|
||||
|
||||
Font &getSystemFont();
|
||||
Font &getSpeechFont();
|
||||
|
||||
/**
|
||||
* Access to "to say" list for conversations.
|
||||
*
|
||||
* @return Conversation line list.
|
||||
*/
|
||||
ConversationLineList &getToSayList();
|
||||
|
||||
/**
|
||||
* Access to "response" list for conversations.
|
||||
*
|
||||
* @return Conversation line list.
|
||||
*/
|
||||
ConversationLineList &getResponseList();
|
||||
|
||||
/**
|
||||
* Access to inventory definitions.
|
||||
*
|
||||
* @return Inventory item definition list.
|
||||
*/
|
||||
InventoryItemDefinitionList &getInventoryItemDefList();
|
||||
|
||||
/**
|
||||
* Access to strings hardcoded in game executable.
|
||||
*
|
||||
* @return Hardcoded strings.
|
||||
*/
|
||||
HardcodedStrings &getHardcodedStrings();
|
||||
private:
|
||||
SystemFont _systemFont;
|
||||
SpeechFont _speechFont;
|
||||
ConversationLineList _toSayList;
|
||||
ConversationLineList _responseList;
|
||||
InventoryItemDefinitionList _invItemDefList;
|
||||
HardcodedStrings _hardcodedStrings;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
52
engines/mutationofjb/commands/additemcommand.cpp
Normal file
52
engines/mutationofjb/commands/additemcommand.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/additemcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* "ADDITEM " <item>
|
||||
*
|
||||
* Adds item to inventory.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool AddItemCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("ADDITEM") || line.size() < 9) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new AddItemCommand(line.c_str() + 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult AddItemCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData()._inventory.addItem(_item);
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String AddItemCommand::debugString() const {
|
||||
return Common::String::format("ADDITEM '%s'", _item.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
49
engines/mutationofjb/commands/additemcommand.h
Normal file
49
engines/mutationofjb/commands/additemcommand.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ADDITEMCOMMAND_H
|
||||
#define MUTATIONOFJB_ADDITEMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class AddItemCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
AddItemCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class AddItemCommand : public SeqCommand {
|
||||
public:
|
||||
AddItemCommand(const Common::String &item) : _item(item) {}
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Common::String _item;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
57
engines/mutationofjb/commands/bitmapvisibilitycommand.cpp
Normal file
57
engines/mutationofjb/commands/bitmapvisibilitycommand.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/bitmapvisibilitycommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* "RB " <sceneId> " " <bitmapId> " " <visible>
|
||||
*
|
||||
* Changes visibility of a bitmap in the specified scene.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool BitmapVisibilityCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.size() < 10 || !line.hasPrefix("RB "))
|
||||
return false;
|
||||
|
||||
const uint8 sceneId = (uint8) atoi(line.c_str() + 3);
|
||||
const uint8 bitmapId = (uint8) atoi(line.c_str() + 6);
|
||||
const bool visible = (line[9] == '1');
|
||||
|
||||
command = new BitmapVisibilityCommand(sceneId, bitmapId, visible);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult BitmapVisibilityCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData().getScene(_sceneId)->getBitmap(_bitmapId)->_isVisible = _visible;
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String BitmapVisibilityCommand::debugString() const {
|
||||
return Common::String::format("SETBITMAPVIS %u %u %s", (unsigned int) _sceneId, (unsigned int) _bitmapId, _visible ? "true" : "false");
|
||||
}
|
||||
|
||||
}
|
||||
52
engines/mutationofjb/commands/bitmapvisibilitycommand.h
Normal file
52
engines/mutationofjb/commands/bitmapvisibilitycommand.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_BITMAPVISIBILITYCOMMAND_H
|
||||
#define MUTATIONOFJB_BITMAPVISIBILITYCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class BitmapVisibilityCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
BitmapVisibilityCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class BitmapVisibilityCommand : public SeqCommand {
|
||||
public:
|
||||
BitmapVisibilityCommand(uint8 sceneId, uint8 bitmapId, bool visible) : _sceneId(sceneId), _bitmapId(bitmapId), _visible(visible) {}
|
||||
const Common::String &getName() const;
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
uint8 _sceneId;
|
||||
uint8 _bitmapId;
|
||||
bool _visible;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
82
engines/mutationofjb/commands/callmacrocommand.cpp
Normal file
82
engines/mutationofjb/commands/callmacrocommand.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/callmacrocommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/game.h"
|
||||
|
||||
/** @file
|
||||
* "_" <name>
|
||||
*
|
||||
* Calls macro with the specified name.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool CallMacroCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 2 || line.firstChar() != '_') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Common::String macroName = line.c_str() + 1;
|
||||
command = new CallMacroCommand(macroName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CallMacroCommandParser::transition(ScriptParseContext &, Command *oldCommand, Command *newCommand, CommandParser *) {
|
||||
if (!oldCommand || !newCommand) {
|
||||
warning("Unexpected empty command in transition");
|
||||
return;
|
||||
}
|
||||
|
||||
static_cast<CallMacroCommand *>(oldCommand)->setReturnCommand(newCommand);
|
||||
}
|
||||
|
||||
|
||||
void CallMacroCommand::setReturnCommand(Command *cmd) {
|
||||
_returnCommand = cmd;
|
||||
}
|
||||
|
||||
Command *CallMacroCommand::getReturnCommand() const {
|
||||
return _returnCommand;
|
||||
}
|
||||
|
||||
Command::ExecuteResult CallMacroCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
_callCommand = scriptExecCtx.getMacro(_macroName);
|
||||
if (_callCommand) {
|
||||
scriptExecCtx.pushReturnCommand(_returnCommand);
|
||||
} else {
|
||||
warning("Macro '%s' not found.", _macroName.c_str());
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Command *CallMacroCommand::next() const {
|
||||
return _callCommand;
|
||||
}
|
||||
|
||||
Common::String CallMacroCommand::debugString() const {
|
||||
return Common::String::format("CALL '%s'", _macroName.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
57
engines/mutationofjb/commands/callmacrocommand.h
Normal file
57
engines/mutationofjb/commands/callmacrocommand.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_CALLMACROCOMMAND_H
|
||||
#define MUTATIONOFJB_CALLMACROCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class CallMacroCommandParser : public CommandParser {
|
||||
public:
|
||||
CallMacroCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
|
||||
};
|
||||
|
||||
class CallMacroCommand : public Command {
|
||||
public:
|
||||
CallMacroCommand(const Common::String ¯oName) : _macroName(macroName), _returnCommand(nullptr), _callCommand(nullptr) {}
|
||||
void setReturnCommand(Command *);
|
||||
|
||||
Command *getReturnCommand() const;
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Command *next() const override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Common::String _macroName;
|
||||
Command *_returnCommand;
|
||||
Command *_callCommand;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
58
engines/mutationofjb/commands/camefromcommand.cpp
Normal file
58
engines/mutationofjb/commands/camefromcommand.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/camefromcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "CAMEFROM " <sceneId>
|
||||
*
|
||||
* This command tests whether last scene (the scene player came from) is sceneId.
|
||||
* If true, the execution continues after this command.
|
||||
* Otherwise the execution continues after first '#' found.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool CameFromCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 10 || !line.hasPrefix("CAMEFROM")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8 sceneId = atoi(line.c_str() + 9);
|
||||
_tags.push(0);
|
||||
command = new CameFromCommand(sceneId);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult CameFromCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
_cachedResult = (scriptExecCtx.getGameData()._lastScene == _sceneId);
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String CameFromCommand::debugString() const {
|
||||
return Common::String::format("CAMEFROM %d", _sceneId);
|
||||
}
|
||||
|
||||
}
|
||||
47
engines/mutationofjb/commands/camefromcommand.h
Normal file
47
engines/mutationofjb/commands/camefromcommand.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_CAMEFROMCOMMAND_H
|
||||
#define MUTATIONOFJB_CAMEFROMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class CameFromCommandParser : public ConditionalCommandParser {
|
||||
public:
|
||||
CameFromCommandParser() : ConditionalCommandParser(true) {}
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class CameFromCommand : public ConditionalCommand {
|
||||
public:
|
||||
CameFromCommand(uint8 sceneId) : _sceneId(sceneId) {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
uint8 _sceneId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
558
engines/mutationofjb/commands/changecommand.cpp
Normal file
558
engines/mutationofjb/commands/changecommand.cpp
Normal file
@@ -0,0 +1,558 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/changecommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
/** @file
|
||||
* "CHANGE" <entity> " " <register> " " <sceneId> " " <entityId> " " <value>
|
||||
*
|
||||
* Changes entity register value for specified scene.
|
||||
* <entity> 1B Entity to change register for.
|
||||
* Possible values:
|
||||
* 'D' - door
|
||||
* 'O' - object
|
||||
* 'S' - static
|
||||
* '' - scene
|
||||
* <register> 2B Register name.
|
||||
* <sceneId> 2B Scene ID.
|
||||
* <entityid> 2B Entity ID.
|
||||
* <value> *B Value (variable length).
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool ChangeCommandParser::parseValueString(const Common::String &valueString, bool changeEntity, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister ®, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv) {
|
||||
if (changeEntity) {
|
||||
if (valueString.size() < 8) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (valueString.size() < 7) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sceneId = atoi(valueString.c_str() + 3);
|
||||
if (changeEntity) {
|
||||
entityId = atoi(valueString.c_str() + 6);
|
||||
}
|
||||
const char *val = "";
|
||||
if (changeEntity) {
|
||||
if (valueString.size() >= 9) {
|
||||
val = valueString.c_str() + 9;
|
||||
}
|
||||
} else {
|
||||
if (valueString.size() >= 6) {
|
||||
val = valueString.c_str() + 6;
|
||||
}
|
||||
}
|
||||
|
||||
if (valueString.hasPrefix("NM")) {
|
||||
reg = ChangeCommand::NM;
|
||||
op = ChangeCommand::SetValue;
|
||||
Common::strlcpy(ccv._strVal, val, MAX_ENTITY_NAME_LENGTH + 1);
|
||||
} else if (valueString.hasPrefix("LT")) {
|
||||
reg = ChangeCommand::LT;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("SX")) {
|
||||
reg = ChangeCommand::SX;
|
||||
ccv._wordVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("SY")) {
|
||||
reg = ChangeCommand::SY;
|
||||
ccv._wordVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("XX")) {
|
||||
reg = ChangeCommand::XX;
|
||||
ccv._wordVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("YY")) {
|
||||
reg = ChangeCommand::YY;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("XL")) {
|
||||
reg = ChangeCommand::XL;
|
||||
ccv._wordVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("YL")) {
|
||||
reg = ChangeCommand::YL;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("WX")) {
|
||||
reg = ChangeCommand::WX;
|
||||
ccv._wordVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("WY")) {
|
||||
reg = ChangeCommand::WY;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("AC")) {
|
||||
reg = ChangeCommand::AC;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("FA")) {
|
||||
reg = ChangeCommand::FA;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("FR")) {
|
||||
reg = ChangeCommand::FR;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("NA")) {
|
||||
reg = ChangeCommand::NA;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("FS")) {
|
||||
reg = ChangeCommand::FS;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("CA")) {
|
||||
reg = ChangeCommand::CA;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("DS")) {
|
||||
reg = ChangeCommand::DS;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("DL")) {
|
||||
reg = ChangeCommand::DL;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("ND")) {
|
||||
reg = ChangeCommand::ND;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("NO")) {
|
||||
reg = ChangeCommand::NO;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("NS")) {
|
||||
reg = ChangeCommand::NS;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("PF")) {
|
||||
reg = ChangeCommand::PF;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("PL")) {
|
||||
reg = ChangeCommand::PL;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
} else if (valueString.hasPrefix("PD")) {
|
||||
reg = ChangeCommand::PD;
|
||||
ccv._byteVal = parseInteger(val, op);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ChangeDoorCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("CHANGED ")) {
|
||||
return false;
|
||||
}
|
||||
uint8 sceneId = 0;
|
||||
uint8 objectId = 0;
|
||||
ChangeCommand::ChangeRegister reg;
|
||||
ChangeCommand::ChangeOperation op;
|
||||
ChangeCommandValue val;
|
||||
if (!parseValueString(line.c_str() + 8, true, sceneId, objectId, reg, op, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new ChangeDoorCommand(sceneId, objectId, reg, op, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeObjectCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("CHANGEO ")) {
|
||||
return false;
|
||||
}
|
||||
uint8 sceneId = 0;
|
||||
uint8 objectId = 0;
|
||||
ChangeCommand::ChangeRegister reg;
|
||||
ChangeCommand::ChangeOperation op;
|
||||
ChangeCommandValue val;
|
||||
if (!parseValueString(line.c_str() + 8, true, sceneId, objectId, reg, op, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new ChangeObjectCommand(sceneId, objectId, reg, op, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeStaticCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("CHANGES ")) {
|
||||
return false;
|
||||
}
|
||||
uint8 sceneId = 0;
|
||||
uint8 objectId = 0;
|
||||
ChangeCommand::ChangeRegister reg;
|
||||
ChangeCommand::ChangeOperation op;
|
||||
ChangeCommandValue val;
|
||||
if (!parseValueString(line.c_str() + 8, true, sceneId, objectId, reg, op, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new ChangeStaticCommand(sceneId, objectId, reg, op, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeSceneCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("CHANGE ")) {
|
||||
return false;
|
||||
}
|
||||
uint8 sceneId = 0;
|
||||
uint8 objectId = 0;
|
||||
ChangeCommand::ChangeRegister reg;
|
||||
ChangeCommand::ChangeOperation op;
|
||||
ChangeCommandValue val;
|
||||
if (!parseValueString(line.c_str() + 7, false, sceneId, objectId, reg, op, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new ChangeSceneCommand(sceneId, objectId, reg, op, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
int ChangeCommandParser::parseInteger(const char *val, ChangeCommand::ChangeOperation &op) {
|
||||
op = ChangeCommand::SetValue;
|
||||
|
||||
if (!val || !(*val)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (val[0] == '\\') {
|
||||
op = ChangeCommand::SetValue;
|
||||
val++;
|
||||
} else if (val[0] == '+') {
|
||||
op = ChangeCommand::AddValue;
|
||||
val++;
|
||||
} else if (val[0] == '-') {
|
||||
op = ChangeCommand::SubtractValue;
|
||||
val++;
|
||||
}
|
||||
|
||||
return atoi(val);
|
||||
}
|
||||
|
||||
|
||||
const char *ChangeCommand::getRegisterAsString() const {
|
||||
switch (_register) {
|
||||
case NM:
|
||||
return "NM";
|
||||
case LT:
|
||||
return "LT";
|
||||
case SX:
|
||||
return "SX";
|
||||
case SY:
|
||||
return "SY";
|
||||
case XX:
|
||||
return "XX";
|
||||
case YY:
|
||||
return "YY";
|
||||
case XL:
|
||||
return "XL";
|
||||
case YL:
|
||||
return "YL";
|
||||
case WX:
|
||||
return "WX";
|
||||
case WY:
|
||||
return "WY";
|
||||
case SP:
|
||||
return "SP";
|
||||
case AC:
|
||||
return "AC";
|
||||
case FA:
|
||||
return "FA";
|
||||
case FR:
|
||||
return "FR";
|
||||
case NA:
|
||||
return "NA";
|
||||
case FS:
|
||||
return "FS";
|
||||
case CA:
|
||||
return "CA";
|
||||
case DS:
|
||||
return "DS";
|
||||
case DL:
|
||||
return "DL";
|
||||
case ND:
|
||||
return "ND";
|
||||
case NO:
|
||||
return "NO";
|
||||
case NS:
|
||||
return "NS";
|
||||
case PF:
|
||||
return "PF";
|
||||
case PL:
|
||||
return "PL";
|
||||
case PD:
|
||||
return "PD";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
Common::String ChangeCommand::getValueAsString() const {
|
||||
switch (_register) {
|
||||
case NM:
|
||||
return Common::String::format("\"%s\"", _value._strVal);
|
||||
case LT:
|
||||
case YY:
|
||||
case YL:
|
||||
case WY:
|
||||
case SP:
|
||||
case AC:
|
||||
case FA:
|
||||
case FR:
|
||||
case NA:
|
||||
case FS:
|
||||
case CA:
|
||||
case DS:
|
||||
case DL:
|
||||
case ND:
|
||||
case NO:
|
||||
case NS:
|
||||
case PF:
|
||||
case PL:
|
||||
case PD:
|
||||
return Common::String::format("%d", static_cast<int>(_value._byteVal));
|
||||
case SX:
|
||||
case SY:
|
||||
case XX:
|
||||
case XL:
|
||||
case WX:
|
||||
return Common::String::format("%d", static_cast<int>(_value._wordVal));
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
const char *ChangeCommand::getOperationAsString() const {
|
||||
switch (_operation) {
|
||||
case SetValue:
|
||||
return "=";
|
||||
case AddValue:
|
||||
return "+=";
|
||||
case SubtractValue:
|
||||
return "-=";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
Command::ExecuteResult ChangeDoorCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Door *const door = scene->getDoor(_entityId);
|
||||
if (!door) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
switch (_register) {
|
||||
case NM:
|
||||
Common::strlcpy(door->_name, _value._strVal, MAX_ENTITY_NAME_LENGTH + 1);
|
||||
break;
|
||||
case LT:
|
||||
door->_destSceneId = _value._byteVal;
|
||||
break;
|
||||
case SX:
|
||||
door->_destX = _value._wordVal;
|
||||
break;
|
||||
case SY:
|
||||
door->_destY = _value._wordVal;
|
||||
break;
|
||||
case XX:
|
||||
door->_x = _value._wordVal;
|
||||
break;
|
||||
case YY:
|
||||
door->_y = _value._byteVal;
|
||||
break;
|
||||
case XL:
|
||||
door->_width = _value._wordVal;
|
||||
break;
|
||||
case YL:
|
||||
door->_height = _value._byteVal;
|
||||
break;
|
||||
case WX:
|
||||
door->_walkToX = _value._wordVal;
|
||||
break;
|
||||
case WY:
|
||||
door->_walkToY = _value._byteVal;
|
||||
break;
|
||||
case SP:
|
||||
door->_SP = _value._byteVal;
|
||||
break;
|
||||
default:
|
||||
warning("Object does not support changing this register.");
|
||||
break;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String ChangeDoorCommand::debugString() const {
|
||||
return Common::String::format("SCENE%d.DOOR%d.%s %s %s", _sceneId, _entityId, getRegisterAsString(), getOperationAsString(), getValueAsString().c_str());
|
||||
}
|
||||
|
||||
Command::ExecuteResult ChangeObjectCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Object *const object = scene->getObject(_entityId, true);
|
||||
if (!object) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
switch (_register) {
|
||||
case AC:
|
||||
object->_active = _value._byteVal;
|
||||
break;
|
||||
case FA:
|
||||
object->_firstFrame = _value._byteVal;
|
||||
break;
|
||||
case FR:
|
||||
object->_randomFrame = _value._byteVal;
|
||||
break;
|
||||
case NA:
|
||||
object->_numFrames = _value._byteVal;
|
||||
break;
|
||||
case FS:
|
||||
object->_roomFrameLSB = _value._byteVal;
|
||||
break;
|
||||
case CA:
|
||||
object->_currentFrame = _value._byteVal;
|
||||
break;
|
||||
case XX:
|
||||
object->_x = _value._wordVal;
|
||||
break;
|
||||
case YY:
|
||||
object->_y = _value._byteVal;
|
||||
break;
|
||||
case XL:
|
||||
object->_width = _value._wordVal;
|
||||
break;
|
||||
case YL:
|
||||
object->_height = _value._byteVal;
|
||||
break;
|
||||
case WX:
|
||||
object->_WX = _value._wordVal;
|
||||
break;
|
||||
case WY:
|
||||
object->_roomFrameMSB = _value._byteVal;
|
||||
break;
|
||||
case SP:
|
||||
object->_SP = _value._byteVal;
|
||||
break;
|
||||
default:
|
||||
warning("Object does not support changing this register.");
|
||||
break;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String ChangeObjectCommand::debugString() const {
|
||||
return Common::String::format("SCENE%d.OBJECT%d.%s %s %s", _sceneId, _entityId, getRegisterAsString(), getOperationAsString(), getValueAsString().c_str());
|
||||
}
|
||||
|
||||
Command::ExecuteResult ChangeStaticCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Static *const stat = scene->getStatic(_entityId);
|
||||
if (!stat) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
switch (_register) {
|
||||
case AC:
|
||||
stat->_active = _value._byteVal;
|
||||
break;
|
||||
case NM:
|
||||
Common::strlcpy(stat->_name, _value._strVal, MAX_ENTITY_NAME_LENGTH + 1);
|
||||
break;
|
||||
case XX:
|
||||
stat->_x = _value._wordVal;
|
||||
break;
|
||||
case YY:
|
||||
stat->_y = _value._byteVal;
|
||||
break;
|
||||
case XL:
|
||||
stat->_width = _value._wordVal;
|
||||
break;
|
||||
case YL:
|
||||
stat->_height = _value._byteVal;
|
||||
break;
|
||||
case WX:
|
||||
stat->_walkToX = _value._wordVal;
|
||||
break;
|
||||
case WY:
|
||||
stat->_walkToY = _value._byteVal;
|
||||
break;
|
||||
case SP:
|
||||
stat->_walkToFrame = _value._byteVal;
|
||||
break;
|
||||
default:
|
||||
warning("Object does not support changing this register.");
|
||||
break;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String ChangeStaticCommand::debugString() const {
|
||||
return Common::String::format("SCENE%d.STATIC%d.%s %s %s", _sceneId, _entityId, getRegisterAsString(), getOperationAsString(), getValueAsString().c_str());
|
||||
}
|
||||
|
||||
Command::ExecuteResult ChangeSceneCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
switch (_register) {
|
||||
case DS:
|
||||
scene->_startup = _value._byteVal;
|
||||
break;
|
||||
case DL:
|
||||
scene->_delay = _value._byteVal;
|
||||
break;
|
||||
case ND:
|
||||
scene->_noDoors = _value._byteVal;
|
||||
break;
|
||||
case NO:
|
||||
scene->_noObjects = _value._byteVal;
|
||||
break;
|
||||
case NS:
|
||||
scene->_noStatics = _value._byteVal;
|
||||
break;
|
||||
case PF:
|
||||
scene->_palRotFirst = _value._byteVal;
|
||||
break;
|
||||
case PL:
|
||||
scene->_palRotLast = _value._byteVal;
|
||||
break;
|
||||
case PD:
|
||||
scene->_palRotDelay = _value._byteVal;
|
||||
break;
|
||||
default:
|
||||
warning("Scene does not support changing this register.");
|
||||
break;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String ChangeSceneCommand::debugString() const {
|
||||
return Common::String::format("SCENE%d.%s %s %s", _sceneId, getRegisterAsString(), getOperationAsString(), getValueAsString().c_str());
|
||||
}
|
||||
|
||||
}
|
||||
146
engines/mutationofjb/commands/changecommand.h
Normal file
146
engines/mutationofjb/commands/changecommand.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
union ChangeCommandValue {
|
||||
uint8 _byteVal;
|
||||
uint16 _wordVal;
|
||||
char _strVal[MAX_ENTITY_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
class ChangeCommand : public SeqCommand {
|
||||
public:
|
||||
enum ChangeRegister {
|
||||
NM, // Name
|
||||
LT, // Destination scene ID
|
||||
SX, // Destination X
|
||||
SY, // Destination Y
|
||||
XX, // X
|
||||
YY, // Y
|
||||
XL, // Width
|
||||
YL, // Height
|
||||
WX, // Walk to X
|
||||
WY, // Walk to Y
|
||||
SP, //
|
||||
AC, // Active
|
||||
FA, // First animation
|
||||
FR,
|
||||
NA,
|
||||
FS,
|
||||
CA,
|
||||
DS, // Startup
|
||||
DL,
|
||||
ND, // Number of doors
|
||||
NO, // Number of objects
|
||||
NS, // Number of statics
|
||||
PF, // Palette rotation first
|
||||
PL, // Palette rotation last
|
||||
PD // Palette rotation delay
|
||||
};
|
||||
|
||||
enum ChangeOperation {
|
||||
SetValue,
|
||||
AddValue,
|
||||
SubtractValue
|
||||
};
|
||||
|
||||
ChangeCommand(uint8 sceneId, uint8 entityId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue &val) :
|
||||
_sceneId(sceneId), _entityId(entityId), _register(reg), _operation(op), _value(val)
|
||||
{}
|
||||
protected:
|
||||
const char *getRegisterAsString() const;
|
||||
Common::String getValueAsString() const;
|
||||
const char *getOperationAsString() const;
|
||||
|
||||
uint8 _sceneId;
|
||||
uint8 _entityId;
|
||||
ChangeRegister _register;
|
||||
ChangeOperation _operation;
|
||||
ChangeCommandValue _value;
|
||||
};
|
||||
|
||||
class ChangeCommandParser : public SeqCommandParser {
|
||||
protected:
|
||||
bool parseValueString(const Common::String &valueString, bool changeEntity, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister ®, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv);
|
||||
int parseInteger(const char *val, ChangeCommand::ChangeOperation &op);
|
||||
};
|
||||
|
||||
class ChangeObjectCommandParser : public ChangeCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class ChangeDoorCommandParser : public ChangeCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class ChangeStaticCommandParser : public ChangeCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class ChangeSceneCommandParser : public ChangeCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class ChangeDoorCommand : public ChangeCommand {
|
||||
public:
|
||||
ChangeDoorCommand(uint8 sceneId, uint8 doorId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue &val)
|
||||
: ChangeCommand(sceneId, doorId, reg, op, val)
|
||||
{}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
};
|
||||
|
||||
class ChangeObjectCommand : public ChangeCommand {
|
||||
public:
|
||||
ChangeObjectCommand(uint8 sceneId, uint8 objectId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue &val)
|
||||
: ChangeCommand(sceneId, objectId, reg, op, val)
|
||||
{}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
};
|
||||
|
||||
class ChangeStaticCommand : public ChangeCommand {
|
||||
public:
|
||||
ChangeStaticCommand(uint8 sceneId, uint8 staticId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue &val)
|
||||
: ChangeCommand(sceneId, staticId, reg, op, val)
|
||||
{}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
};
|
||||
|
||||
class ChangeSceneCommand : public ChangeCommand {
|
||||
public:
|
||||
ChangeSceneCommand(uint8 sceneId, uint8 staticId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue &val)
|
||||
: ChangeCommand(sceneId, staticId, reg, op, val)
|
||||
{}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
};
|
||||
|
||||
}
|
||||
33
engines/mutationofjb/commands/command.cpp
Normal file
33
engines/mutationofjb/commands/command.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
void CommandParser::transition(ScriptParseContext &, Command *, Command *, CommandParser *) {}
|
||||
void CommandParser::finish(ScriptParseContext &) {}
|
||||
CommandParser::~CommandParser() {}
|
||||
|
||||
Command::~Command() {}
|
||||
|
||||
}
|
||||
103
engines/mutationofjb/commands/command.h
Normal file
103
engines/mutationofjb/commands/command.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_COMMAND_H
|
||||
#define MUTATIONOFJB_COMMAND_H
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 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 {
|
||||
None,
|
||||
Finished,
|
||||
InProgress
|
||||
};
|
||||
|
||||
virtual ~Command();
|
||||
|
||||
virtual ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) = 0;
|
||||
virtual Command *next() const = 0;
|
||||
|
||||
virtual Common::String debugString() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
73
engines/mutationofjb/commands/conditionalcommand.cpp
Normal file
73
engines/mutationofjb/commands/conditionalcommand.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
void ConditionalCommandParser::transition(ScriptParseContext &parseContext, Command *oldCommand, Command *newCommand, CommandParser *) {
|
||||
if (!oldCommand || !newCommand) {
|
||||
warning("Unexpected empty command in transition");
|
||||
return;
|
||||
}
|
||||
|
||||
ConditionalCommand *const condCommand = static_cast<ConditionalCommand *>(oldCommand);
|
||||
parseContext.addConditionalCommand(condCommand, _tags.pop(), _firstHash);
|
||||
condCommand->setTrueCommand(newCommand);
|
||||
}
|
||||
|
||||
void ConditionalCommandParser::finish(ScriptParseContext &) {
|
||||
_tags.clear();
|
||||
}
|
||||
|
||||
|
||||
ConditionalCommand::ConditionalCommand() :
|
||||
_trueCommand(nullptr),
|
||||
_falseCommand(nullptr),
|
||||
_cachedResult(false) {}
|
||||
|
||||
Command *ConditionalCommand::getTrueCommand() const {
|
||||
return _trueCommand;
|
||||
}
|
||||
|
||||
Command *ConditionalCommand::getFalseCommand() const {
|
||||
return _falseCommand;
|
||||
}
|
||||
|
||||
void ConditionalCommand::setTrueCommand(Command *command) {
|
||||
_trueCommand = command;
|
||||
}
|
||||
|
||||
void ConditionalCommand::setFalseCommand(Command *command) {
|
||||
_falseCommand = command;
|
||||
}
|
||||
|
||||
Command *ConditionalCommand::next() const {
|
||||
if (_cachedResult) {
|
||||
return _trueCommand;
|
||||
} else {
|
||||
return _falseCommand;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
engines/mutationofjb/commands/conditionalcommand.h
Normal file
61
engines/mutationofjb/commands/conditionalcommand.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_CONDITIONALCOMMAND_H
|
||||
#define MUTATIONOFJB_CONDITIONALCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/queue.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ConditionalCommandParser : public CommandParser {
|
||||
public:
|
||||
ConditionalCommandParser(bool firstHash = false) : _firstHash(firstHash) {}
|
||||
void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
|
||||
void finish(ScriptParseContext &parseCtx) override;
|
||||
protected:
|
||||
Common::Queue<char> _tags;
|
||||
private:
|
||||
bool _firstHash;
|
||||
};
|
||||
|
||||
class ConditionalCommand : public Command {
|
||||
public:
|
||||
ConditionalCommand();
|
||||
|
||||
Command *getTrueCommand() const;
|
||||
Command *getFalseCommand() const;
|
||||
|
||||
void setTrueCommand(Command *command);
|
||||
void setFalseCommand(Command *command);
|
||||
|
||||
Command *next() const override;
|
||||
protected:
|
||||
Command *_trueCommand;
|
||||
Command *_falseCommand;
|
||||
bool _cachedResult;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
99
engines/mutationofjb/commands/definestructcommand.cpp
Normal file
99
engines/mutationofjb/commands/definestructcommand.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/definestructcommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#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) {
|
||||
if (line.size() < 24 || !line.hasPrefix("DEFINE_STRUCT")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConversationInfo convInfo;
|
||||
|
||||
const int numLines = atoi(line.c_str() + 14);
|
||||
convInfo._context = atoi(line.c_str() + 18);
|
||||
convInfo._objectId = atoi(line.c_str() + 20);
|
||||
convInfo._color = Game::colorFromString(line.c_str() + 23);
|
||||
|
||||
for (int i = 0; i < numLines; ++i) {
|
||||
Common::String convLineStr;
|
||||
if (!parseCtx.readLine(convLineStr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (convLineStr.size() != 74) {
|
||||
debug("Conversation line in DEFINE_STRUCT with wrong length");
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *linePtr = convLineStr.c_str();
|
||||
|
||||
ConversationInfo::ItemGroup convGroup;
|
||||
|
||||
for (int j = 0; j < 5; ++j) {
|
||||
ConversationInfo::Item convItem;
|
||||
convItem._question = atoi(linePtr);
|
||||
linePtr += 6;
|
||||
convItem._response = atoi(linePtr);
|
||||
linePtr += 6;
|
||||
convItem._nextGroupIndex = atoi(linePtr);
|
||||
linePtr += 3;
|
||||
convGroup.push_back(convItem);
|
||||
}
|
||||
convInfo._itemGroups.push_back(convGroup);
|
||||
}
|
||||
|
||||
command = new DefineStructCommand(convInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult DefineStructCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData()._conversationInfo = _conversationInfo;
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Common::String DefineStructCommand::debugString() const {
|
||||
return "DEFINE_STRUCT <data omitted>";
|
||||
}
|
||||
|
||||
}
|
||||
41
engines/mutationofjb/commands/definestructcommand.h
Normal file
41
engines/mutationofjb/commands/definestructcommand.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class DefineStructCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class DefineStructCommand : public SeqCommand {
|
||||
public:
|
||||
DefineStructCommand(const ConversationInfo& convInfo) : _conversationInfo(convInfo) {}
|
||||
Command::ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
ConversationInfo _conversationInfo;
|
||||
};
|
||||
|
||||
}
|
||||
259
engines/mutationofjb/commands/endblockcommand.cpp
Normal file
259
engines/mutationofjb/commands/endblockcommand.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/endblockcommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "common/str.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
/** @file
|
||||
* <look> | <walk> | <talk> | <pickup> | <use> | <else> | <macro> | <extra> | <endRandom>
|
||||
*
|
||||
* 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
|
||||
* when the user starts corresponding action on the object or in case of "use" up to two objects.
|
||||
* The difference between '#' and '-' version is whether the player walks towards the object ('#') or not ('-').
|
||||
*
|
||||
* #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).
|
||||
*
|
||||
* TODO: TIMERPROC.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char firstChar = line.firstChar();
|
||||
if (firstChar != '#' && firstChar != '=' && firstChar != '-' && firstChar != '\\') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is the start or end of section/block.
|
||||
command = new EndBlockCommand();
|
||||
|
||||
if (line.size() >= 4 && (line.hasPrefix("#L ") || line.hasPrefix("-L "))) {
|
||||
ActionInfo ai = {ActionInfo::Look, line.c_str() + 3, "", firstChar == '#', nullptr};
|
||||
parseCtx._actionInfos.push_back(ai);
|
||||
_pendingActionInfos.push_back(parseCtx._actionInfos.size() - 1);
|
||||
} else if (line.size() >= 4 && (line.hasPrefix("#W ") || line.hasPrefix("-W "))) {
|
||||
ActionInfo ai = {ActionInfo::Walk, line.c_str() + 3, "", firstChar == '#', nullptr};
|
||||
parseCtx._actionInfos.push_back(ai);
|
||||
_pendingActionInfos.push_back(parseCtx._actionInfos.size() - 1);
|
||||
} else if (line.size() >= 4 && (line.hasPrefix("#T ") || line.hasPrefix("-T "))) {
|
||||
ActionInfo ai = {ActionInfo::Talk, line.c_str() + 3, "", firstChar == '#', nullptr};
|
||||
parseCtx._actionInfos.push_back(ai);
|
||||
_pendingActionInfos.push_back(parseCtx._actionInfos.size() - 1);
|
||||
} else if (line.size() >= 4 && (line.hasPrefix("#P ") || line.hasPrefix("-P "))) {
|
||||
ActionInfo ai = {ActionInfo::PickUp, line.c_str() + 3, "", firstChar == '#', nullptr};
|
||||
parseCtx._actionInfos.push_back(ai);
|
||||
_pendingActionInfos.push_back(parseCtx._actionInfos.size() - 1);
|
||||
} else if (line.size() >= 4 && (line.hasPrefix("#U ") || line.hasPrefix("-U "))) {
|
||||
int secondObjPos = -1;
|
||||
for (uint i = 3; i < line.size(); ++i) {
|
||||
if (line[i] == ' ') {
|
||||
secondObjPos = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String obj1;
|
||||
Common::String obj2;
|
||||
if (secondObjPos == -1) {
|
||||
obj1 = line.c_str() + 3;
|
||||
} else {
|
||||
obj1 = Common::String(line.c_str() + 3, secondObjPos - 4);
|
||||
obj2 = line.c_str() + secondObjPos;
|
||||
}
|
||||
|
||||
ActionInfo ai = {
|
||||
ActionInfo::Use,
|
||||
obj1,
|
||||
obj2,
|
||||
firstChar == '#',
|
||||
nullptr
|
||||
};
|
||||
parseCtx._actionInfos.push_back(ai);
|
||||
_pendingActionInfos.push_back(parseCtx._actionInfos.size() - 1);
|
||||
} else if ((line.hasPrefix("#ELSE") || line.hasPrefix("=ELSE"))) {
|
||||
_elseFound = true;
|
||||
_ifTag = 0;
|
||||
if (line.size() >= 6) {
|
||||
_ifTag = line[5];
|
||||
}
|
||||
} else if (line.size() >= 8 && line.hasPrefix("#MACRO")) {
|
||||
NameAndCommand nc = {line.c_str() + 7, command};
|
||||
_foundMacros.push_back(nc);
|
||||
} else if (line.size() >= 10 && line.hasPrefix("#STARTUP")) {
|
||||
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 == '#') {
|
||||
_hashFound = true;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EndBlockCommandParser::transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) {
|
||||
if (_elseFound || _hashFound) {
|
||||
if (newCommand) {
|
||||
ScriptParseContext::ConditionalCommandInfos::iterator it = parseCtx._pendingCondCommands.begin();
|
||||
|
||||
while (it != parseCtx._pendingCondCommands.end()) {
|
||||
if ((it->_firstHash && _hashFound) || (!it->_firstHash && it->_tag == _ifTag)) {
|
||||
it->_command->setFalseCommand(newCommand);
|
||||
it = parseCtx._pendingCondCommands.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_elseFound = false;
|
||||
_hashFound = false;
|
||||
_ifTag = 0;
|
||||
}
|
||||
|
||||
if (!_foundMacros.empty()) {
|
||||
if (newCommand) {
|
||||
for (NameAndCommandArray::iterator it = _foundMacros.begin(); it != _foundMacros.end();) {
|
||||
if (it->_command != oldCommand) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parseCtx._macros.contains(it->_name)) {
|
||||
parseCtx._macros[it->_name] = newCommand;
|
||||
} else {
|
||||
warning("Macro '%s' already exists", it->_name.c_str());
|
||||
}
|
||||
it = _foundMacros.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_foundStartups.empty()) {
|
||||
if (newCommand) {
|
||||
for (IdAndCommandArray::iterator it = _foundStartups.begin(); it != _foundStartups.end();) {
|
||||
if (it->_command != oldCommand) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parseCtx._startups.contains(it->_id)) {
|
||||
parseCtx._startups[it->_id] = newCommand;
|
||||
} else {
|
||||
warning("Startup %u already exists", (unsigned int) it->_id);
|
||||
}
|
||||
it = _foundStartups.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
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()) {
|
||||
for (Common::Array<uint>::iterator it = _pendingActionInfos.begin(); it != _pendingActionInfos.end(); ++it) {
|
||||
parseCtx._actionInfos[*it]._command = newCommand;
|
||||
}
|
||||
_pendingActionInfos.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndBlockCommandParser::finish(ScriptParseContext &) {
|
||||
_elseFound = false;
|
||||
_hashFound = false;
|
||||
_ifTag = 0;
|
||||
|
||||
if (!_pendingActionInfos.empty()) {
|
||||
debug("Problem: Pending action infos from end block parser is not empty!");
|
||||
}
|
||||
if (!_foundMacros.empty()) {
|
||||
debug("Problem: Found macros from end block parser is not empty!");
|
||||
}
|
||||
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) {
|
||||
_nextCmd = scriptExecCtx.popReturnCommand();
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Command *EndBlockCommand::next() const {
|
||||
return _nextCmd;
|
||||
}
|
||||
|
||||
Common::String EndBlockCommand::debugString() const {
|
||||
return "ENDBLOCK";
|
||||
}
|
||||
|
||||
}
|
||||
77
engines/mutationofjb/commands/endblockcommand.h
Normal file
77
engines/mutationofjb/commands/endblockcommand.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ENDBLOCKCOMMAND_H
|
||||
#define MUTATIONOFJB_ENDBLOCKCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
struct ActionInfo;
|
||||
|
||||
class EndBlockCommandParser : public CommandParser {
|
||||
public:
|
||||
EndBlockCommandParser() : _elseFound(false), _hashFound(false), _ifTag(0) {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
|
||||
void finish(ScriptParseContext &parseCtx) override;
|
||||
private:
|
||||
bool _elseFound;
|
||||
bool _hashFound;
|
||||
char _ifTag;
|
||||
|
||||
Common::Array<uint> _pendingActionInfos;
|
||||
struct NameAndCommand {
|
||||
Common::String _name;
|
||||
Command *_command;
|
||||
};
|
||||
struct IdAndCommand {
|
||||
uint8 _id;
|
||||
Command *_command;
|
||||
};
|
||||
typedef Common::Array<NameAndCommand> NameAndCommandArray;
|
||||
typedef Common::Array<IdAndCommand> IdAndCommandArray;
|
||||
NameAndCommandArray _foundMacros;
|
||||
IdAndCommandArray _foundStartups;
|
||||
NameAndCommandArray _foundExtras;
|
||||
};
|
||||
|
||||
class EndBlockCommand : public Command {
|
||||
public:
|
||||
EndBlockCommand() : _nextCmd(nullptr) {}
|
||||
static bool ParseFunc(const Common::String &line, ScriptParseContext &parseContext, Command *&command);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Command *next() const override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Command *_nextCmd;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
79
engines/mutationofjb/commands/gotocommand.cpp
Normal file
79
engines/mutationofjb/commands/gotocommand.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/gotocommand.h"
|
||||
#include "mutationofjb/commands/labelcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* "GOTO " <label>
|
||||
*
|
||||
* Jumps to a label.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool GotoCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.size() < 6 || !line.hasPrefix("GOTO")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String label = line.c_str() + 5;
|
||||
GotoCommand *gotoCmd = new GotoCommand();
|
||||
|
||||
if (parseCtx._labels.contains(label)) {
|
||||
// We already have the label, set it.
|
||||
gotoCmd->setLabelCommand(parseCtx._labels[label]);
|
||||
} else {
|
||||
// Label is after goto, add to pending list.
|
||||
parseCtx._pendingGotos[label].push_back(gotoCmd);
|
||||
}
|
||||
|
||||
command = gotoCmd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GotoCommand::setLabelCommand(LabelCommand *labelCmd) {
|
||||
_labelCommand = labelCmd;
|
||||
}
|
||||
|
||||
Command::ExecuteResult GotoCommand::execute(ScriptExecutionContext &) {
|
||||
// Intentionally empty.
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Command *GotoCommand::next() const {
|
||||
return _labelCommand;
|
||||
}
|
||||
|
||||
Common::String GotoCommand::debugString() const {
|
||||
if (!_labelCommand) {
|
||||
return "GOTO (null)";
|
||||
}
|
||||
|
||||
return Common::String::format("GOTO %s", _labelCommand->getName().c_str());
|
||||
}
|
||||
|
||||
}
|
||||
54
engines/mutationofjb/commands/gotocommand.h
Normal file
54
engines/mutationofjb/commands/gotocommand.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_GOTOCOMMAND_H
|
||||
#define MUTATIONOFJB_GOTOCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class LabelCommand;
|
||||
|
||||
class GotoCommandParser : public CommandParser {
|
||||
public:
|
||||
GotoCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class GotoCommand : public Command {
|
||||
public:
|
||||
GotoCommand() : _labelCommand(nullptr) {}
|
||||
|
||||
void setLabelCommand(LabelCommand *labelCmd);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Command *next() const override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
LabelCommand *_labelCommand;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
108
engines/mutationofjb/commands/ifcommand.cpp
Normal file
108
engines/mutationofjb/commands/ifcommand.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/ifcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "IF" <tag> <sceneId> <objectId> <value> ["!"]
|
||||
*
|
||||
* IF command compares the value of the WX pseudo-register of the object in the specified scene.
|
||||
* If the values match, execution continues to the next line.
|
||||
* Otherwise execution continues after first "#ELSE" or "=ELSE" with the same <tag>.
|
||||
* The logic can be reversed with exclamation mark at the end.
|
||||
*
|
||||
* <tag> is always 1 character long, <sceneId> and <objectId> 2 characters long.
|
||||
*
|
||||
* Please note that this does not work like you are used to from saner languages.
|
||||
* IF does not have any blocks. It only searches for first #ELSE, so you can have stuff like:
|
||||
* IF something
|
||||
* IF something else
|
||||
* #ELSE
|
||||
* ...
|
||||
* This is effectively logical AND.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool IfCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
// IFtss oo val!
|
||||
// <t> 1B Tag.
|
||||
// <ss> 2B Scene.
|
||||
// <oo> 2B Object ID.
|
||||
// <val> VL Value.
|
||||
// ! 1B Negation (optional).
|
||||
|
||||
if (line.size() < 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!line.hasPrefix("IF")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *const cstr = line.c_str();
|
||||
const char tag = cstr[2] == ' ' ? 0 : cstr[2];
|
||||
const uint8 sceneId = atoi(cstr + 3);
|
||||
const uint8 objectId = atoi(cstr + 6);
|
||||
const uint8 value = atoi(cstr + 9);
|
||||
const bool negative = (line.lastChar() == '!');
|
||||
|
||||
_tags.push(tag);
|
||||
|
||||
command = new IfCommand(sceneId, objectId, value, negative);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
IfCommand::IfCommand(uint8 sceneId, uint8 objectId, uint16 value, bool negative) :
|
||||
_sceneId(sceneId),
|
||||
_objectId(objectId),
|
||||
_value(value),
|
||||
_negative(negative) {}
|
||||
|
||||
Command::ExecuteResult IfCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Object *const object = scene->getObject(_objectId, true);
|
||||
if (!object) {
|
||||
return Finished;
|
||||
}
|
||||
|
||||
_cachedResult = (object->_WX == _value);
|
||||
if (_negative) {
|
||||
_cachedResult = !_cachedResult;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String IfCommand::debugString() const {
|
||||
return Common::String::format("IF scene%d.object%d.WX %s %d", _sceneId, _objectId, _negative ? "!=" : "==", _value);
|
||||
}
|
||||
|
||||
}
|
||||
54
engines/mutationofjb/commands/ifcommand.h
Normal file
54
engines/mutationofjb/commands/ifcommand.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_IFCOMMAND_H
|
||||
#define MUTATIONOFJB_IFCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ScriptParseContext;
|
||||
|
||||
class IfCommandParser : public ConditionalCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
private:
|
||||
};
|
||||
|
||||
class IfCommand : public ConditionalCommand {
|
||||
public:
|
||||
IfCommand(uint8 sceneId, uint8 objectId, uint16 value, bool negative);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
uint8 _sceneId;
|
||||
uint8 _objectId;
|
||||
uint16 _value;
|
||||
bool _negative;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
86
engines/mutationofjb/commands/ifitemcommand.cpp
Normal file
86
engines/mutationofjb/commands/ifitemcommand.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/ifitemcommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/util.h"
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "IFITEM " <item> [ "!" ]
|
||||
*
|
||||
* IFITEM command tests whether an item is in the inventory.
|
||||
* If it is, execution continues to the next line.
|
||||
* Otherwise execution continues after first "#ELSE" or "=ELSE".
|
||||
* The logic can be reversed with exclamation mark at the end.
|
||||
*
|
||||
* Please note that this does not work like you are used to from saner languages.
|
||||
* IFITEM does not have any blocks. It only searches for first #ELSE, so you can have stuff like:
|
||||
* IFITEM item1
|
||||
* IFITEM item2
|
||||
* #ELSE
|
||||
* ...
|
||||
* This is effectively logical AND.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool IfItemCommandParser::parse(const Common::String &line, ScriptParseContext &parseContext, Command *&command) {
|
||||
if (line.size() < 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!line.hasPrefix("IFITEM")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool negative = (line.lastChar() == '!');
|
||||
Common::String item(line.c_str() + 7);
|
||||
if (negative) {
|
||||
item.deleteLastChar(); // Remove '!'.
|
||||
}
|
||||
|
||||
_tags.push(0);
|
||||
command = new IfItemCommand(item, negative);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
IfItemCommand::IfItemCommand(const Common::String &item, bool negative) :
|
||||
_item(item),
|
||||
_negative(negative) {}
|
||||
|
||||
Command::ExecuteResult IfItemCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
_cachedResult = scriptExecCtx.getGameData()._inventory.hasItem(_item);
|
||||
if (_negative) {
|
||||
_cachedResult = !_cachedResult;
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String IfItemCommand::debugString() const {
|
||||
return Common::String::format("IFITEM %s%s", _negative ? "NOT " : "", _item.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
52
engines/mutationofjb/commands/ifitemcommand.h
Normal file
52
engines/mutationofjb/commands/ifitemcommand.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_IFITEMCOMMAND_H
|
||||
#define MUTATIONOFJB_IFITEMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ScriptParseContext;
|
||||
|
||||
class IfItemCommandParser : public ConditionalCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class IfItemCommand : public ConditionalCommand {
|
||||
public:
|
||||
IfItemCommand(const Common::String &item, bool negative);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
Common::String _item;
|
||||
bool _negative;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
68
engines/mutationofjb/commands/ifpiggycommand.cpp
Normal file
68
engines/mutationofjb/commands/ifpiggycommand.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/ifpiggycommand.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/util.h"
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "IFPIGGY"
|
||||
*
|
||||
* IFPIGGY command tests whether current loaded APK file (character animation) is "piggy.apk".
|
||||
* If it is, execution continues to the next line.
|
||||
* Otherwise execution continues after first "#ELSE" or "=ELSE".
|
||||
*
|
||||
* Please note that this does not work like you are used to from saner languages.
|
||||
* IFPIGGY does not have any blocks. It only searches for first #ELSE, so you can have stuff like:
|
||||
* IFPIGGY
|
||||
* IFITEM someitem
|
||||
* #ELSE
|
||||
* ...
|
||||
* This is effectively logical AND.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool IfPiggyCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line != "IFPIGGY") {
|
||||
return false;
|
||||
}
|
||||
|
||||
_tags.push(0);
|
||||
command = new IfPiggyCommand();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult IfPiggyCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
_cachedResult = scriptExecCtx.getGameData()._currentAPK == "piggy.apk";
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String IfPiggyCommand::debugString() const {
|
||||
return "IFPIGGY";
|
||||
}
|
||||
|
||||
}
|
||||
48
engines/mutationofjb/commands/ifpiggycommand.h
Normal file
48
engines/mutationofjb/commands/ifpiggycommand.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_IFPIGGYCOMMAND_H
|
||||
#define MUTATIONOFJB_IFPIGGYCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ScriptParseContext;
|
||||
|
||||
class IfPiggyCommandParser : public ConditionalCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class IfPiggyCommand : public ConditionalCommand {
|
||||
public:
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
76
engines/mutationofjb/commands/labelcommand.cpp
Normal file
76
engines/mutationofjb/commands/labelcommand.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/labelcommand.h"
|
||||
#include "mutationofjb/commands/gotocommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* <label> ":"
|
||||
*
|
||||
* Creates a label.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool LabelCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.lastChar() != ':') {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String label = line;
|
||||
label.deleteLastChar();
|
||||
|
||||
LabelCommand *labelCmd = new LabelCommand(label);
|
||||
if (!parseCtx._labels.contains(label)) {
|
||||
parseCtx._labels[label] = labelCmd;
|
||||
} else {
|
||||
warning("Label '%s' already exists", label.c_str());
|
||||
}
|
||||
|
||||
if (parseCtx._pendingGotos.contains(label)) {
|
||||
GotoCommands &gotos = parseCtx._pendingGotos[label];
|
||||
for (GotoCommands::const_iterator it = gotos.begin(); it != gotos.end(); ++it) {
|
||||
(*it)->setLabelCommand(labelCmd);
|
||||
}
|
||||
gotos.clear();
|
||||
}
|
||||
|
||||
command = labelCmd;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const Common::String &LabelCommand::getName() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
Command::ExecuteResult LabelCommand::execute(ScriptExecutionContext &) {
|
||||
// Intentionally empty.
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String LabelCommand::debugString() const {
|
||||
return Common::String::format("LABEL %s", _name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
50
engines/mutationofjb/commands/labelcommand.h
Normal file
50
engines/mutationofjb/commands/labelcommand.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_LABELCOMMAND_H
|
||||
#define MUTATIONOFJB_LABELCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class LabelCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
LabelCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class LabelCommand : public SeqCommand {
|
||||
public:
|
||||
LabelCommand(const Common::String &name) : _name(name) {}
|
||||
const Common::String &getName() const;
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Common::String _name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
63
engines/mutationofjb/commands/loadplayercommand.cpp
Normal file
63
engines/mutationofjb/commands/loadplayercommand.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/loadplayercommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* "RABLOAD " <apkFrameFirst> " " <apkFrameLast> " " <playerFrameFirst> " " <palIndexFirst> " " <apkFilename>
|
||||
*
|
||||
* Load player frames from APK file specified by apkFileName.
|
||||
* Only frames between apkFrameFirst and apkFrameLast are loaded onto position defined by playerFrameFirst.
|
||||
* Player's palette is loaded at index defined by palIndexFirst.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool LoadPlayerCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 25 || !line.hasPrefix("RABLOAD ")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8 apkFrameFirst = atoi(line.c_str() + 8);
|
||||
const uint8 apkFrameLast = atoi(line.c_str() + 12);
|
||||
const uint8 playerFrameFirst = atoi(line.c_str() + 16);
|
||||
const uint8 palIndexFirst = atoi(line.c_str() + 20);
|
||||
const Common::String apkFileName = line.c_str() + 24;
|
||||
|
||||
command = new LoadPlayerCommand(apkFrameFirst, apkFrameLast, playerFrameFirst, palIndexFirst, apkFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult LoadPlayerCommand::execute(ScriptExecutionContext &scriptExeCtx) {
|
||||
scriptExeCtx.getGameData()._currentAPK = _apkFileName;
|
||||
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Common::String LoadPlayerCommand::debugString() const {
|
||||
return Common::String::format("LOADPLAYER %u %u %u %u %s", (unsigned int) _apkFrameFirst, (unsigned int) _apkFrameLast, (unsigned int) _playerFrameFirst, (unsigned int) _palIndexFirst, _apkFileName.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
56
engines/mutationofjb/commands/loadplayercommand.h
Normal file
56
engines/mutationofjb/commands/loadplayercommand.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_LOADPLAYERCOMMAND_H
|
||||
#define MUTATIONOFJB_LOADPLAYERCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "mutationofjb/tasks/task.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ConversationTask;
|
||||
|
||||
class LoadPlayerCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class LoadPlayerCommand : public SeqCommand {
|
||||
public:
|
||||
LoadPlayerCommand(uint8 apkFrameFirst, uint8 apkFrameLast, uint8 playerFrameFirst, uint8 palIndexFirst, const Common::String &apkFileName) : _apkFrameFirst(apkFrameFirst), _apkFrameLast(apkFrameLast), _playerFrameFirst(playerFrameFirst), _palIndexFirst(palIndexFirst), _apkFileName(apkFileName) {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
uint8 _apkFrameFirst;
|
||||
uint8 _apkFrameLast;
|
||||
uint8 _playerFrameFirst;
|
||||
uint8 _palIndexFirst;
|
||||
Common::String _apkFileName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
83
engines/mutationofjb/commands/newroomcommand.cpp
Normal file
83
engines/mutationofjb/commands/newroomcommand.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/newroomcommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "NEWROOM " <sceneId> " " <x> " " <y> [ " " <frame> ]
|
||||
*
|
||||
* NEWROOM changes the current scene. While doing that, it also executes STARTUP section for the new room.
|
||||
* However, after that, the execution goes back to the old script to finish commands after NEWROOM.
|
||||
*
|
||||
* All parameters are supposed to be 3 characters long.
|
||||
* SceneId is the scene to load, x and y are the player's new position and frame is the player's new frame (orientation).
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool NewRoomCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 19 || !line.hasPrefix("NEWROOM")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8 sceneId = atoi(line.c_str() + 8);
|
||||
const uint16 x = atoi(line.c_str() + 12);
|
||||
const uint16 y = atoi(line.c_str() + 16);
|
||||
uint8 frame = 0;
|
||||
if (line.size() >= 21)
|
||||
frame = atoi(line.c_str() + 20);
|
||||
command = new NewRoomCommand(sceneId, x, y, frame);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NewRoomCommand::NewRoomCommand(uint8 sceneId, uint16 x, uint16 y, uint8 frame) : _sceneId(sceneId), _x(x), _y(y), _frame(frame), _innerExecCtx(nullptr) {}
|
||||
|
||||
Command::ExecuteResult NewRoomCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Game &game = scriptExecCtx.getGame();
|
||||
|
||||
// Execute new startup section.
|
||||
ExecuteResult res;
|
||||
if (!_innerExecCtx) {
|
||||
Script *newScript = game.changeSceneDelayScript(_sceneId, game.getGameData()._partB);
|
||||
_innerExecCtx = new ScriptExecutionContext(scriptExecCtx.getGame(), newScript);
|
||||
res = _innerExecCtx->startStartupSection();
|
||||
} else {
|
||||
res = _innerExecCtx->runActiveCommand();
|
||||
}
|
||||
|
||||
if (res == Finished) {
|
||||
delete _innerExecCtx;
|
||||
_innerExecCtx = nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Common::String NewRoomCommand::debugString() const {
|
||||
return Common::String::format("NEWROOM %u %u %u %u", (unsigned int) _sceneId, (unsigned int) _x, (unsigned int) _y, (unsigned int) _frame);
|
||||
}
|
||||
|
||||
}
|
||||
55
engines/mutationofjb/commands/newroomcommand.h
Normal file
55
engines/mutationofjb/commands/newroomcommand.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_NEWROOMCOMMAND_H
|
||||
#define MUTATIONOFJB_NEWROOMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ScriptExecutionContext;
|
||||
|
||||
class NewRoomCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
NewRoomCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class NewRoomCommand : public SeqCommand {
|
||||
public:
|
||||
NewRoomCommand(uint8 sceneId, uint16 x, uint16 y, uint8 frame);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
uint8 _sceneId;
|
||||
uint16 _x;
|
||||
uint16 _y;
|
||||
uint8 _frame;
|
||||
|
||||
ScriptExecutionContext *_innerExecCtx;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
60
engines/mutationofjb/commands/playanimationcommand.cpp
Normal file
60
engines/mutationofjb/commands/playanimationcommand.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/playanimationcommand.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/room.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* ( "FLB " | "FLX" ) <fromFrame> " " <toFrame>
|
||||
*
|
||||
* Plays the specified frames from room animation.
|
||||
*
|
||||
* TODO: Parse all arguments of this command.
|
||||
* TODO: Actually play the animation instead of just showing last frame.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool PlayAnimationCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.size() < 11 || (!line.hasPrefix("FLB ") && !line.hasPrefix("FLX ")))
|
||||
return false;
|
||||
|
||||
const int fromFrame = atoi(line.c_str() + 4);
|
||||
const int toFrame = atoi(line.c_str() + 8);
|
||||
|
||||
command = new PlayAnimationCommand(fromFrame, toFrame);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult PlayAnimationCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGame().getRoom().drawFrames(_fromFrame - 1, _toFrame - 1);
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String PlayAnimationCommand::debugString() const {
|
||||
return Common::String::format("PLAYROOMANIM %u %u", (unsigned int) _fromFrame, (unsigned int) _toFrame);
|
||||
}
|
||||
|
||||
}
|
||||
51
engines/mutationofjb/commands/playanimationcommand.h
Normal file
51
engines/mutationofjb/commands/playanimationcommand.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_PLAYANIMATIONCOMMAND_H
|
||||
#define MUTATIONOFJB_PLAYANIMATIONCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class PlayAnimationCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
PlayAnimationCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class PlayAnimationCommand : public SeqCommand {
|
||||
public:
|
||||
PlayAnimationCommand(int fromFrame, int toFrame) : _fromFrame(fromFrame), _toFrame(toFrame) {}
|
||||
const Common::String &getName() const;
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
int _fromFrame;
|
||||
int _toFrame;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
114
engines/mutationofjb/commands/randomcommand.cpp
Normal file
114
engines/mutationofjb/commands/randomcommand.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/randomcommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/random.h"
|
||||
|
||||
/** @file
|
||||
* "RANDOM " <numChoices>
|
||||
*
|
||||
* RANDOM command randomly picks one of the command blocks that
|
||||
* follow it and jumps to its start.
|
||||
*
|
||||
* These blocks start with "/" and end with "\". The end of a random
|
||||
* block also ends the current section. The number of blocks must
|
||||
* match numChoices.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool RandomCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.size() < 8 || !line.hasPrefix("RANDOM")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int numChoices = atoi(line.c_str() + 7);
|
||||
if (parseCtx._pendingRandomCommand) {
|
||||
// Nested RANDOM commands are unused and not properly supported by the original game.
|
||||
warning("Ignoring nested RANDOM command.");
|
||||
} else if (numChoices >= 1) {
|
||||
RandomCommand *randomCommand = new RandomCommand(static_cast<uint>(numChoices));
|
||||
parseCtx._pendingRandomCommand = randomCommand;
|
||||
command = randomCommand;
|
||||
} else {
|
||||
warning("Ignoring malformed RANDOM command with %d choices.", numChoices);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool RandomBlockStartParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&) {
|
||||
if (line != "/") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parseCtx._pendingRandomCommand) {
|
||||
warning("Unexpected start of RANDOM block");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RandomBlockStartParser::transition(ScriptParseContext &parseCtx, Command *, Command *newCommand, CommandParser *) {
|
||||
RandomCommand *randomCommand = parseCtx._pendingRandomCommand;
|
||||
if (newCommand && randomCommand) {
|
||||
randomCommand->_choices.push_back(newCommand);
|
||||
|
||||
if (randomCommand->_choices.size() == randomCommand->_numChoices) {
|
||||
parseCtx._pendingRandomCommand = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RandomCommand::RandomCommand(uint numChoices)
|
||||
: _numChoices(numChoices),
|
||||
_chosenNext(nullptr) {
|
||||
_choices.reserve(numChoices);
|
||||
}
|
||||
|
||||
Command::ExecuteResult RandomCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
assert(!_choices.empty());
|
||||
|
||||
Common::RandomSource &rng = scriptExecCtx.getGame().getRandomSource();
|
||||
uint choice = rng.getRandomNumber(_choices.size() - 1);
|
||||
_chosenNext = _choices[choice];
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Command *RandomCommand::next() const {
|
||||
return _chosenNext;
|
||||
}
|
||||
|
||||
Common::String RandomCommand::debugString() const {
|
||||
return Common::String::format("RANDOM %u", _numChoices);
|
||||
}
|
||||
|
||||
const RandomCommand::Choices &RandomCommand::getChoices() const {
|
||||
return _choices;
|
||||
}
|
||||
|
||||
}
|
||||
69
engines/mutationofjb/commands/randomcommand.h
Normal file
69
engines/mutationofjb/commands/randomcommand.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_RANDOMCOMMAND_H
|
||||
#define MUTATIONOFJB_RANDOMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/array.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class RandomCommandParser : public CommandParser {
|
||||
public:
|
||||
RandomCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class RandomBlockStartParser : public CommandParser {
|
||||
public:
|
||||
RandomBlockStartParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
|
||||
};
|
||||
|
||||
class RandomCommand : public Command {
|
||||
friend class RandomBlockStartParser;
|
||||
|
||||
public:
|
||||
typedef Common::Array<Command *> Choices;
|
||||
|
||||
RandomCommand(uint numChoices);
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Command *next() const override;
|
||||
|
||||
Common::String debugString() const override;
|
||||
|
||||
const Choices &getChoices() const;
|
||||
|
||||
private:
|
||||
uint _numChoices;
|
||||
Choices _choices;
|
||||
Command *_chosenNext;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
52
engines/mutationofjb/commands/removeallitemscommand.cpp
Normal file
52
engines/mutationofjb/commands/removeallitemscommand.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/removeallitemscommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
/** @file
|
||||
* "DELALLITEMS"
|
||||
*
|
||||
* Removes all items from inventory.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool RemoveAllItemsCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line != "DELALLITEMS") {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new RemoveAllItemsCommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult RemoveAllItemsCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData()._inventory.removeAllItems();
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String RemoveAllItemsCommand::debugString() const {
|
||||
return "DELALLITEM";
|
||||
}
|
||||
|
||||
}
|
||||
47
engines/mutationofjb/commands/removeallitemscommand.h
Normal file
47
engines/mutationofjb/commands/removeallitemscommand.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_REMOVEALLITEMSCOMMAND_H
|
||||
#define MUTATIONOFJB_REMOVEALLITEMSCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class RemoveAllItemsCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
RemoveAllItemsCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class RemoveAllItemsCommand : public SeqCommand {
|
||||
public:
|
||||
RemoveAllItemsCommand() {}
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
52
engines/mutationofjb/commands/removeitemcommand.cpp
Normal file
52
engines/mutationofjb/commands/removeitemcommand.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/removeitemcommand.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
/** @file
|
||||
* "DELITEM " <item>
|
||||
*
|
||||
* Removes item from inventory.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool RemoveItemCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (!line.hasPrefix("DELITEM") || line.size() < 9) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new RemoveItemCommand(line.c_str() + 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult RemoveItemCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData()._inventory.removeItem(_item);
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String RemoveItemCommand::debugString() const {
|
||||
return Common::String::format("DELITEM '%s'", _item.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
49
engines/mutationofjb/commands/removeitemcommand.h
Normal file
49
engines/mutationofjb/commands/removeitemcommand.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_REMOVEITEMCOMMAND_H
|
||||
#define MUTATIONOFJB_REMOVEITEMCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class RemoveItemCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
RemoveItemCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class RemoveItemCommand : public SeqCommand {
|
||||
public:
|
||||
RemoveItemCommand(const Common::String &item) : _item(item) {}
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Common::String _item;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
78
engines/mutationofjb/commands/renamecommand.cpp
Normal file
78
engines/mutationofjb/commands/renamecommand.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/renamecommand.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "common/algorithm.h"
|
||||
|
||||
/** @file
|
||||
* "REN " <oldName> " " <newName>
|
||||
*
|
||||
* Renames every door, static (in the current scene) and inventory item
|
||||
* with the name oldName to newName.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool RenameCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 7 || !line.hasPrefix("REN")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String::const_iterator sep = Common::find(line.begin() + 4, line.end(), ' ');
|
||||
if (sep == line.end() || sep + 1 == line.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Common::String oldName(line.begin() + 4, sep);
|
||||
const Common::String newName(sep + 1, line.end());
|
||||
command = new RenameCommand(oldName, newName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult RenameCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Scene *const scene = scriptExecCtx.getGameData().getCurrentScene();
|
||||
|
||||
for (int i = 1; i <= scene->getNoDoors(); ++i) {
|
||||
Door *const door = scene->getDoor(i);
|
||||
if (strcmp(door->_name, _oldName.c_str()) == 0) {
|
||||
strncpy(door->_name, _newName.c_str(), MAX_ENTITY_NAME_LENGTH);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i <= scene->getNoStatics(); ++i) {
|
||||
Static *const stat = scene->getStatic(i);
|
||||
if (strcmp(stat->_name, _oldName.c_str()) == 0) {
|
||||
strncpy(stat->_name, _newName.c_str(), MAX_ENTITY_NAME_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
scriptExecCtx.getGameData().getInventory().renameItem(_oldName, _newName);
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String RenameCommand::debugString() const {
|
||||
return Common::String::format("RENAME '%s' '%s'", _oldName.c_str(), _newName.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
49
engines/mutationofjb/commands/renamecommand.h
Normal file
49
engines/mutationofjb/commands/renamecommand.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_RENAMECOMMAND_H
|
||||
#define MUTATIONOFJB_RENAMECOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class RenameCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class RenameCommand : public SeqCommand {
|
||||
public:
|
||||
RenameCommand(const Common::String &oldName, const Common::String &newName) : _oldName(oldName), _newName(newName) {}
|
||||
|
||||
Command::ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
Common::String _oldName;
|
||||
Common::String _newName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
169
engines/mutationofjb/commands/saycommand.cpp
Normal file
169
engines/mutationofjb/commands/saycommand.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/saycommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/tasks/saytask.h"
|
||||
#include "mutationofjb/tasks/taskmanager.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/debug-channels.h"
|
||||
|
||||
/** @file
|
||||
* <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.
|
||||
* The asterisk is ignored by the readLine function.
|
||||
*
|
||||
* Each of them plays a voice file (if present) and/or shows a message
|
||||
* (if voice file not present or subtitles are enabled).
|
||||
*
|
||||
* The difference between versions starting with "S" and "N" is that
|
||||
* the "N" version does not show talking animation.
|
||||
*
|
||||
* The "L" versions are "blocking", i.e. they wait for the previous say command to finish.
|
||||
*
|
||||
* If the line ends with "<!", it means the message continues to the next line.
|
||||
* Next line usually has "SM" (or other variant) repeated, but it does not have to.
|
||||
* Then we have the rest of the string to say (which is concatenated with the previous line)
|
||||
* and possibly the voice file or "<!" again.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool SayCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
bool waitForPrevious = false;
|
||||
bool talkingAnimation = false;
|
||||
|
||||
if (line.hasPrefix("SM")) {
|
||||
waitForPrevious = false;
|
||||
talkingAnimation = true;
|
||||
} else if (line.hasPrefix("SLM")) {
|
||||
waitForPrevious = true;
|
||||
talkingAnimation = true;
|
||||
} else if (line.hasPrefix("NM")) {
|
||||
waitForPrevious = false;
|
||||
talkingAnimation = false;
|
||||
} else if (line.hasPrefix("NLM")) {
|
||||
waitForPrevious = true;
|
||||
talkingAnimation = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String currentLine = line;
|
||||
|
||||
Common::String lineToSay;
|
||||
Common::String voiceFile;
|
||||
|
||||
bool cont = false;
|
||||
bool firstPass = true;
|
||||
|
||||
do {
|
||||
cont = false;
|
||||
|
||||
uint startPos;
|
||||
for (startPos = 0; startPos < currentLine.size(); ++startPos) {
|
||||
if (currentLine[startPos] == ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startPos == currentLine.size()) {
|
||||
if (!firstPass) {
|
||||
warning("Unable to parse line '%s'", currentLine.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startPos != currentLine.size()) {
|
||||
startPos++;
|
||||
}
|
||||
|
||||
uint endPos;
|
||||
for (endPos = startPos; endPos < currentLine.size(); ++endPos) {
|
||||
if (currentLine[endPos] == '<') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String talkStr(currentLine.c_str() + startPos, endPos - startPos);
|
||||
|
||||
if (endPos != currentLine.size()) {
|
||||
const char *end = currentLine.c_str() + endPos + 1;
|
||||
if (end[0] == '!') {
|
||||
cont = true;
|
||||
} else {
|
||||
voiceFile = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (talkStr.lastChar() == '~') {
|
||||
debug("Found say command ending with '~'. Please take a look.");
|
||||
}
|
||||
|
||||
if (lineToSay.empty()) {
|
||||
lineToSay = talkStr;
|
||||
} else {
|
||||
lineToSay += " " + talkStr;
|
||||
}
|
||||
|
||||
if (cont) {
|
||||
if (!parseCtx.readLine(currentLine)) {
|
||||
cont = false;
|
||||
}
|
||||
}
|
||||
|
||||
firstPass = false;
|
||||
} while (cont);
|
||||
|
||||
command = new SayCommand(lineToSay, voiceFile, waitForPrevious, talkingAnimation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult SayCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Game &game = scriptExecCtx.getGame();
|
||||
|
||||
if (_waitForPrevious) {
|
||||
if (game.getActiveSayTask()) {
|
||||
return InProgress;
|
||||
}
|
||||
}
|
||||
|
||||
TaskPtr task(new SayTask(_lineToSay, game.getGameData()._color));
|
||||
game.getTaskManager().startTask(task);
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String SayCommand::debugString() const {
|
||||
return Common::String::format("SHOWMSG%s%s '%s' '%s'", _waitForPrevious ? "+WAIT" : "", _talkingAnimation ? "+TALKANIM" : "", _lineToSay.c_str(), _voiceFile.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
55
engines/mutationofjb/commands/saycommand.h
Normal file
55
engines/mutationofjb/commands/saycommand.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SAYCOMMAND_H
|
||||
#define MUTATIONOFJB_SAYCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SayCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
SayCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class SayCommand : public SeqCommand {
|
||||
public:
|
||||
SayCommand(const Common::String &lineToSay, const Common::String &voiceFile, bool waitForPrevious, bool talkingAnimation) :
|
||||
_lineToSay(lineToSay),
|
||||
_voiceFile(voiceFile),
|
||||
_waitForPrevious(waitForPrevious),
|
||||
_talkingAnimation(talkingAnimation) {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
Common::String _lineToSay;
|
||||
Common::String _voiceFile;
|
||||
bool _waitForPrevious;
|
||||
bool _talkingAnimation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
45
engines/mutationofjb/commands/seqcommand.cpp
Normal file
45
engines/mutationofjb/commands/seqcommand.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
void SeqCommandParser::transition(ScriptParseContext &, Command *oldCommand, Command *newCommand, CommandParser *) {
|
||||
if (!oldCommand || !newCommand) {
|
||||
warning("Unexpected empty command in transition");
|
||||
return;
|
||||
}
|
||||
|
||||
static_cast<SeqCommand *>(oldCommand)->setNextCommand(newCommand);
|
||||
}
|
||||
|
||||
void SeqCommand::setNextCommand(Command *nextCommand) {
|
||||
_nextCommand = nextCommand;
|
||||
}
|
||||
|
||||
Command *SeqCommand::next() const {
|
||||
return _nextCommand;
|
||||
}
|
||||
|
||||
}
|
||||
50
engines/mutationofjb/commands/seqcommand.h
Normal file
50
engines/mutationofjb/commands/seqcommand.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SEQCOMMAND_H
|
||||
#define MUTATIONOFJB_SEQCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SeqCommandParser : public CommandParser {
|
||||
public:
|
||||
void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for sequential commands.
|
||||
*/
|
||||
class SeqCommand : public Command {
|
||||
public:
|
||||
SeqCommand() : _nextCommand(nullptr) {}
|
||||
void setNextCommand(Command *nextCommand);
|
||||
Command *next() const override;
|
||||
|
||||
private:
|
||||
Command *_nextCommand;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
59
engines/mutationofjb/commands/setcolorcommand.cpp
Normal file
59
engines/mutationofjb/commands/setcolorcommand.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/setcolorcommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "SETCOL " <colorString>
|
||||
*
|
||||
* Sets subtitle color used by SayCommand.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool SetColorCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 8 || !line.hasPrefix("SETCOL")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *const colorStr = line.c_str() + 7;
|
||||
const uint8 color = Game::colorFromString(colorStr);
|
||||
|
||||
command = new SetColorCommand(color);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult SetColorCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
scriptExecCtx.getGameData()._color = _color;
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String SetColorCommand::debugString() const {
|
||||
return Common::String::format("SETCOL %u", _color);
|
||||
}
|
||||
|
||||
}
|
||||
50
engines/mutationofjb/commands/setcolorcommand.h
Normal file
50
engines/mutationofjb/commands/setcolorcommand.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SETCOLORCOMMAND_H
|
||||
#define MUTATIONOFJB_SETCOLORCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SetColorCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
|
||||
class SetColorCommand : public SeqCommand {
|
||||
public:
|
||||
SetColorCommand(uint8 color) : _color(color) {}
|
||||
|
||||
Command::ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
uint8 _color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
63
engines/mutationofjb/commands/setobjectframecommand.cpp
Normal file
63
engines/mutationofjb/commands/setobjectframecommand.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/setobjectframecommand.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/room.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
/** @file
|
||||
* "SETANIM " <objectId> " " <frame>
|
||||
*
|
||||
* Draws the frame for the specified object without changing the object's current frame.
|
||||
* If the object is active, it is deactivated.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool SetObjectFrameCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
|
||||
if (line.size() < 13 || !line.hasPrefix("SETANIM "))
|
||||
return false;
|
||||
|
||||
const uint8 objectId = (uint8) atoi(line.c_str() + 8);
|
||||
const unsigned int frame = atoi(line.c_str() + 11);
|
||||
|
||||
command = new SetObjectFrameCommand(objectId, frame);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Command::ExecuteResult SetObjectFrameCommand::execute(ScriptExecutionContext &scriptExecCtx) {
|
||||
Object *const object = scriptExecCtx.getGameData().getCurrentScene()->getObject(_objectId);
|
||||
|
||||
object->_active = 0;
|
||||
// The object's current frame is not changed, so use frame override instead.
|
||||
scriptExecCtx.getGame().getRoom().drawObject(_objectId, _frame);
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
Common::String SetObjectFrameCommand::debugString() const {
|
||||
return Common::String::format("SETOBJECTFRAME %u %u", (unsigned int) _objectId, (unsigned int) _frame);
|
||||
}
|
||||
|
||||
}
|
||||
50
engines/mutationofjb/commands/setobjectframecommand.h
Normal file
50
engines/mutationofjb/commands/setobjectframecommand.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SETOBJECTFRAMECOMMAND_H
|
||||
#define MUTATIONOFJB_SETOBJECTFRAMECOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SetObjectFrameCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
SetObjectFrameCommandParser() {}
|
||||
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class SetObjectFrameCommand : public SeqCommand {
|
||||
public:
|
||||
SetObjectFrameCommand(uint8 objectId, uint8 frame) : _objectId(objectId), _frame(frame) {}
|
||||
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
private:
|
||||
uint8 _objectId;
|
||||
uint8 _frame;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
77
engines/mutationofjb/commands/specialshowcommand.cpp
Normal file
77
engines/mutationofjb/commands/specialshowcommand.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/specialshowcommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "SPECIALSHOW " <mode>
|
||||
*
|
||||
* Shows special screen.
|
||||
* The command supports multiple modes:
|
||||
* 1 - show puzzle hint,
|
||||
* 2 - show computer puzzle.
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool SpecialShowCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line.size() < 13 || !line.hasPrefix("SPECIALSHOW ")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int modeInt = atoi(line.c_str() + 12);
|
||||
|
||||
SpecialShowCommand::Mode mode = SpecialShowCommand::PUZZLE_HINT;
|
||||
|
||||
if (modeInt == 1) {
|
||||
mode = SpecialShowCommand::PUZZLE_HINT;
|
||||
} else if (modeInt == 2) {
|
||||
mode = SpecialShowCommand::COMPUTER_PUZZLE;
|
||||
} else {
|
||||
warning("Invalid special show mode %d", modeInt);
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new SpecialShowCommand(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult SpecialShowCommand::execute(ScriptExecutionContext &scriptExeCtx) {
|
||||
// TODO: Show UI.
|
||||
if (_mode == COMPUTER_PUZZLE) {
|
||||
scriptExeCtx.getGameData().getScene(32)->getObject(2, true)->_WX = 255;
|
||||
scriptExeCtx.getGameData().getScene(32)->getObject(1, true)->_active = 0;
|
||||
}
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Common::String SpecialShowCommand::debugString() const {
|
||||
const char *modes[] = {"PUZZLE_HINT", "COMPUTER_PUZZLE"};
|
||||
return Common::String::format("SPECIALSHOW %s", modes[static_cast<int>(_mode)]);
|
||||
}
|
||||
|
||||
}
|
||||
52
engines/mutationofjb/commands/specialshowcommand.h
Normal file
52
engines/mutationofjb/commands/specialshowcommand.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SPECIALSHOWCOMMAND_H
|
||||
#define MUTATIONOFJB_SPECIALSHOWCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SpecialShowCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class SpecialShowCommand : public SeqCommand {
|
||||
public:
|
||||
enum Mode {
|
||||
PUZZLE_HINT,
|
||||
COMPUTER_PUZZLE
|
||||
};
|
||||
|
||||
SpecialShowCommand(Mode mode) : _mode(mode) {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
Mode _mode;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
57
engines/mutationofjb/commands/switchpartcommand.cpp
Normal file
57
engines/mutationofjb/commands/switchpartcommand.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/switchpartcommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
/** @file
|
||||
* "SWITCHPART"
|
||||
*
|
||||
* Switches to the second part of the game (part B).
|
||||
*/
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
bool SwitchPartCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
|
||||
if (line != "SWITCHPART") {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new SwitchPartCommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult SwitchPartCommand::execute(ScriptExecutionContext &scriptExeCtx) {
|
||||
scriptExeCtx.getGame().switchToPartB();
|
||||
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Common::String SwitchPartCommand::debugString() const {
|
||||
return "SWITCHPART";
|
||||
}
|
||||
|
||||
}
|
||||
46
engines/mutationofjb/commands/switchpartcommand.h
Normal file
46
engines/mutationofjb/commands/switchpartcommand.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SWITCHPARTCOMMAND_H
|
||||
#define MUTATIONOFJB_SWITCHPARTCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ConversationTask;
|
||||
|
||||
class SwitchPartCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class SwitchPartCommand : public SeqCommand {
|
||||
public:
|
||||
SwitchPartCommand() {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
87
engines/mutationofjb/commands/talkcommand.cpp
Normal file
87
engines/mutationofjb/commands/talkcommand.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/talkcommand.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/tasks/conversationtask.h"
|
||||
#include "mutationofjb/tasks/taskmanager.h"
|
||||
|
||||
#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) {
|
||||
if (line.size() < 11 || !line.hasPrefix("TALK TO HIM")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int modeInt = 0;
|
||||
|
||||
if (line.size() >= 13) {
|
||||
modeInt = atoi(line.c_str() + 12);
|
||||
}
|
||||
|
||||
TalkCommand::Mode mode = TalkCommand::NORMAL_MODE;
|
||||
|
||||
if (modeInt == 1) {
|
||||
mode = TalkCommand::RAY_AND_BUTTLEG_MODE;
|
||||
} else if (modeInt == 3) {
|
||||
mode = TalkCommand::CARNIVAL_TICKET_SELLER_MODE;
|
||||
}
|
||||
|
||||
command = new TalkCommand(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
Command::ExecuteResult TalkCommand::execute(ScriptExecutionContext &scriptExeCtx) {
|
||||
if (!_task) {
|
||||
_task = TaskPtr(new ConversationTask(scriptExeCtx.getGameData()._currentScene, scriptExeCtx.getGame().getGameData()._conversationInfo, _mode));
|
||||
scriptExeCtx.getGame().getTaskManager().startTask(_task);
|
||||
}
|
||||
|
||||
if (_task->getState() == Task::FINISHED) {
|
||||
_task.reset();
|
||||
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
return Command::InProgress;
|
||||
}
|
||||
|
||||
Common::String TalkCommand::debugString() const {
|
||||
const char *modes[] = {"NORMAL", "RAY_AND_BUTTLEG", "CARNIVAL_TICKET_SELLER"};
|
||||
return Common::String::format("TALK %s", modes[static_cast<int>(_mode)]);
|
||||
}
|
||||
|
||||
}
|
||||
57
engines/mutationofjb/commands/talkcommand.h
Normal file
57
engines/mutationofjb/commands/talkcommand.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_TALKCOMMAND_H
|
||||
#define MUTATIONOFJB_TALKCOMMAND_H
|
||||
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "mutationofjb/tasks/task.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ConversationTask;
|
||||
|
||||
class TalkCommandParser : public SeqCommandParser {
|
||||
public:
|
||||
bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
|
||||
};
|
||||
|
||||
class TalkCommand : public SeqCommand {
|
||||
public:
|
||||
enum Mode {
|
||||
NORMAL_MODE,
|
||||
RAY_AND_BUTTLEG_MODE,
|
||||
CARNIVAL_TICKET_SELLER_MODE
|
||||
};
|
||||
|
||||
TalkCommand(Mode mode) : _mode(mode) {}
|
||||
ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
|
||||
Common::String debugString() const override;
|
||||
|
||||
private:
|
||||
Mode _mode;
|
||||
TaskPtr _task;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
3
engines/mutationofjb/configure.engine
Normal file
3
engines/mutationofjb/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine mutationofjb "Mutation of JB" no
|
||||
90
engines/mutationofjb/conversationlinelist.cpp
Normal file
90
engines/mutationofjb/conversationlinelist.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/conversationlinelist.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/util.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
ConversationLineList::ConversationLineList(const Common::Path &fileName) {
|
||||
parseFile(fileName);
|
||||
}
|
||||
|
||||
const ConversationLineList::Line *ConversationLineList::getLine(uint index) const {
|
||||
if (index > _lines.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_lines[index - 1];
|
||||
}
|
||||
|
||||
bool ConversationLineList::parseFile(const Common::Path &fileName) {
|
||||
EncryptedFile file;
|
||||
file.open(fileName);
|
||||
if (!file.isOpen()) {
|
||||
reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!file.eos()) {
|
||||
Common::String lineStr = file.readLine();
|
||||
if (lineStr.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Line line;
|
||||
|
||||
Common::String::iterator endIt = Common::find(lineStr.begin(), lineStr.end(), '|');
|
||||
if (endIt != lineStr.end()) {
|
||||
endIt++;
|
||||
if (endIt != lineStr.end() && *endIt == 'X') {
|
||||
line._extra = Common::String(endIt + 1, lineStr.end()); // Skip 'X' char.
|
||||
}
|
||||
}
|
||||
|
||||
Common::String::iterator startSpeechIt = lineStr.begin();
|
||||
Common::String::iterator endSpeechIt = startSpeechIt;
|
||||
|
||||
while (startSpeechIt < endIt) {
|
||||
endSpeechIt = Common::find(startSpeechIt, endIt, '\\');
|
||||
Common::String::iterator voiceFileIt = Common::find(startSpeechIt, endSpeechIt, '<');
|
||||
Speech speech;
|
||||
|
||||
if (voiceFileIt != endSpeechIt) {
|
||||
if (*voiceFileIt == 'S') {
|
||||
speech._voiceFile = Common::String(voiceFileIt + 1, endSpeechIt);
|
||||
}
|
||||
}
|
||||
|
||||
speech._text = Common::String(startSpeechIt, voiceFileIt);
|
||||
line._speeches.push_back(speech);
|
||||
|
||||
startSpeechIt = endSpeechIt + 1;
|
||||
}
|
||||
|
||||
_lines.push_back(line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
65
engines/mutationofjb/conversationlinelist.h
Normal file
65
engines/mutationofjb/conversationlinelist.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_CONVERSATIONLINELIST_H
|
||||
#define MUTATIONOFJB_CONVERSATIONLINELIST_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/path.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class ConversationLineList {
|
||||
public:
|
||||
struct Speech {
|
||||
Common::String _text;
|
||||
Common::String _voiceFile;
|
||||
|
||||
bool isRepeating() const {
|
||||
return _text.firstChar() == '*';
|
||||
}
|
||||
bool isFirstSpeaker() const {
|
||||
return _text.firstChar() == '~';
|
||||
}
|
||||
bool isSecondSpeaker() const {
|
||||
return _text.firstChar() == '`';
|
||||
}
|
||||
};
|
||||
|
||||
typedef Common::Array<Speech> Speeches;
|
||||
struct Line {
|
||||
Speeches _speeches;
|
||||
Common::String _extra;
|
||||
};
|
||||
|
||||
ConversationLineList(const Common::Path &fileName);
|
||||
const Line *getLine(uint index) const;
|
||||
|
||||
private:
|
||||
bool parseFile(const Common::Path &fileName);
|
||||
|
||||
Common::Array<Line> _lines;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
4
engines/mutationofjb/credits.pl
Normal file
4
engines/mutationofjb/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("MutationOfJB");
|
||||
add_person("Ľubomír Remák", "LubomirR", "");
|
||||
add_person("Miroslav Remák", "MiroslavR", "");
|
||||
end_section();
|
||||
491
engines/mutationofjb/debug.cpp
Normal file
491
engines/mutationofjb/debug.cpp
Normal file
@@ -0,0 +1,491 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/debug.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/inventory.h"
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "mutationofjb/commands/seqcommand.h"
|
||||
#include "mutationofjb/commands/conditionalcommand.h"
|
||||
#include "mutationofjb/commands/callmacrocommand.h"
|
||||
#include "mutationofjb/commands/randomcommand.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
/* Converts CP895 string to 7bit ASCII, so we can show it in the console. */
|
||||
static Common::String convertToASCII(const Common::String &str) {
|
||||
static const char conversionTable[] = {
|
||||
'C', 'u', 'e', 'd', 'a', 'D', 'T', 'c', 'e', 'E', 'L', 'I', 'l', 'l', 'A', 'A', /* 0x80-0x8F */
|
||||
'E', 'z', 'Z', 'o', 'o', 'O', 'u', 'U', 'y', 'O', 'U', 'S', 'L', 'Y', 'R', 't', /* 0x90-0x9F */
|
||||
'a', 'i', 'o', 'u', 'n', 'N', 'U', 'O', 's', 'r', 'r', 'R' /* 0xA0-0xAB */
|
||||
};
|
||||
|
||||
Common::String ret = str;
|
||||
for (Common::String::iterator it = ret.begin(); it != ret.end(); ++it) {
|
||||
const byte cp895Byte = reinterpret_cast<const byte &>(*it);
|
||||
if (cp895Byte >= 0x80 && cp895Byte <= 0xAB) {
|
||||
*it = conversionTable[cp895Byte - 0x80];
|
||||
} else if (cp895Byte == 0xE1) { // ß
|
||||
*it = 's';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Console::Console(MutationOfJBEngine *vm) : _vm(vm) {
|
||||
registerCmd("showallcommands", WRAP_METHOD(Console, cmd_showallcommands));
|
||||
registerCmd("listsections", WRAP_METHOD(Console, cmd_listsections));
|
||||
registerCmd("showsection", WRAP_METHOD(Console, cmd_showsection));
|
||||
registerCmd("listmacros", WRAP_METHOD(Console, cmd_listmacros));
|
||||
registerCmd("showmacro", WRAP_METHOD(Console, cmd_showmacro));
|
||||
registerCmd("liststartups", WRAP_METHOD(Console, cmd_liststartups));
|
||||
registerCmd("showstartup", WRAP_METHOD(Console, cmd_showstartup));
|
||||
registerCmd("changescene", WRAP_METHOD(Console, cmd_changescene));
|
||||
registerCmd("dumpsceneinfo", WRAP_METHOD(Console, cmd_dumpsceneinfo));
|
||||
registerCmd("dumpdoorinfo", WRAP_METHOD(Console, cmd_dumpdoorinfo));
|
||||
registerCmd("dumpobjectinfo", WRAP_METHOD(Console, cmd_dumpobjectinfo));
|
||||
registerCmd("dumpstaticinfo", WRAP_METHOD(Console, cmd_dumpstaticinfo));
|
||||
registerCmd("dumpbitmapinfo", WRAP_METHOD(Console, cmd_dumpbitmapinfo));
|
||||
registerCmd("listinventory", WRAP_METHOD(Console, cmd_listinventory));
|
||||
}
|
||||
|
||||
bool Console::cmd_showallcommands(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
const Commands &commands = script->getAllCommands();
|
||||
|
||||
for (Commands::const_iterator it = commands.begin(); it != commands.end(); ++it) {
|
||||
debugPrintf("%s\n", convertToASCII((*it)->debugString()).c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("showallcommands <G|L>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_listsections(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
ActionInfo::Action action = ActionInfo::Look;
|
||||
const char *word = nullptr;
|
||||
if (strcmp(argv[2], "L") == 0) {
|
||||
action = ActionInfo::Look;
|
||||
word = "Look";
|
||||
} else if (strcmp(argv[2], "W") == 0) {
|
||||
action = ActionInfo::Walk;
|
||||
word = "Walk";
|
||||
} else if (strcmp(argv[2], "T") == 0) {
|
||||
action = ActionInfo::Talk;
|
||||
word = "Talk";
|
||||
} else if (strcmp(argv[2], "U") == 0) {
|
||||
action = ActionInfo::Use;
|
||||
word = "Use";
|
||||
} else if (strcmp(argv[2], "P") == 0) {
|
||||
action = ActionInfo::PickUp;
|
||||
word = "Pick up";
|
||||
} else {
|
||||
debugPrintf("Choose 'L' (look), 'W' (walk), 'T' (talk), 'U' (use) or 'P' (pick up).\n");
|
||||
}
|
||||
if (word) {
|
||||
const ActionInfos &actionInfos = script->getActionInfos(action);
|
||||
for (ActionInfos::const_iterator it = actionInfos.begin(); it != actionInfos.end(); ++it) {
|
||||
const ActionInfo &actionInfo = *it;
|
||||
if (action != ActionInfo::Use || actionInfo._entity2Name.empty()) {
|
||||
debugPrintf("%s %s\n", word, convertToASCII(actionInfo._entity1Name).c_str());
|
||||
} else {
|
||||
debugPrintf("%s %s %s\n", word, convertToASCII(actionInfo._entity1Name).c_str(), convertToASCII(actionInfo._entity2Name).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("listsections <G|L> <L|W|T|U|P>\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Console::showIndent(int indentLevel) {
|
||||
for (int i = 0; i < indentLevel; ++i) {
|
||||
debugPrintf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void Console::showCommands(Command *command, int indentLevel) {
|
||||
while (command) {
|
||||
showIndent(indentLevel);
|
||||
debugPrintf("%s\n", convertToASCII(command->debugString()).c_str());
|
||||
|
||||
if (SeqCommand *const seqCmd = dynamic_cast<SeqCommand *>(command)) {
|
||||
command = seqCmd->next();
|
||||
} else if (ConditionalCommand *const condCmd = dynamic_cast<ConditionalCommand *>(command)) {
|
||||
showCommands(condCmd->getTrueCommand(), indentLevel + 1);
|
||||
showIndent(indentLevel);
|
||||
debugPrintf("ELSE\n");
|
||||
showCommands(condCmd->getFalseCommand(), indentLevel + 1);
|
||||
command = nullptr;
|
||||
} else if (CallMacroCommand *const callMacroCmd = dynamic_cast<CallMacroCommand *>(command)) {
|
||||
command = callMacroCmd->getReturnCommand();
|
||||
} else if (RandomCommand *const randomCmd = dynamic_cast<RandomCommand *>(command)) {
|
||||
const RandomCommand::Choices &choices = randomCmd->getChoices();
|
||||
for (RandomCommand::Choices::size_type i = 0; i < choices.size(); ++i) {
|
||||
showIndent(indentLevel + 1);
|
||||
debugPrintf("CASE %u\n", i);
|
||||
showCommands(choices[i], indentLevel + 2);
|
||||
}
|
||||
command = nullptr;
|
||||
} else {
|
||||
command = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::cmd_showsection(int argc, const char **argv) {
|
||||
if (argc >= 4) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
Command *command = nullptr;
|
||||
ActionInfo::Action action = ActionInfo::Look;
|
||||
bool correctAction = true;
|
||||
bool found = false;
|
||||
|
||||
if (strcmp(argv[2], "L") == 0) {
|
||||
action = ActionInfo::Look;
|
||||
} else if (strcmp(argv[2], "W") == 0) {
|
||||
action = ActionInfo::Walk;
|
||||
} else if (strcmp(argv[2], "T") == 0) {
|
||||
action = ActionInfo::Talk;
|
||||
} else if (strcmp(argv[2], "U") == 0) {
|
||||
action = ActionInfo::Use;
|
||||
} else if (strcmp(argv[2], "P") == 0) {
|
||||
action = ActionInfo::PickUp;
|
||||
} else {
|
||||
debugPrintf("Choose 'L' (look), 'W' (walk), 'T' (talk), 'U' (use) or 'P' (pick up).\n");
|
||||
correctAction = false;
|
||||
}
|
||||
|
||||
if (correctAction) {
|
||||
const ActionInfos &actionInfos = script->getActionInfos(action);
|
||||
for (ActionInfos::const_iterator it = actionInfos.begin(); it != actionInfos.end(); ++it) {
|
||||
const ActionInfo &actionInfo = *it;
|
||||
if (convertToASCII(actionInfo._entity1Name) == argv[3] && (action != ActionInfo::Use || ((argc == 4 && actionInfo._entity2Name.empty()) || (argc > 4 && convertToASCII(actionInfo._entity2Name) == argv[4])))) {
|
||||
found = true;
|
||||
command = actionInfo._command;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (command) {
|
||||
showCommands(command);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Section not found.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("showsection <G|L> <L|W|T|U|P> <sectionname>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_listmacros(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
const Macros ¯os = script->getMacros();
|
||||
for (Macros::const_iterator it = macros.begin(); it != macros.end(); ++it) {
|
||||
debugPrintf("%s\n", it->_key.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("listmacros <G|L>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_showmacro(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
Script *script = nullptr;
|
||||
if (strcmp(argv[1], "G") == 0) {
|
||||
script = _vm->getGame().getGlobalScript();
|
||||
} else if (strcmp(argv[1], "L") == 0) {
|
||||
script = _vm->getGame().getLocalScript();
|
||||
}
|
||||
if (!script) {
|
||||
debugPrintf("Choose 'G' (global) or 'L' (local) script.\n");
|
||||
} else {
|
||||
const Macros ¯os = script->getMacros();
|
||||
Macros::const_iterator itMacro = macros.find(argv[2]);
|
||||
if (itMacro != macros.end()) {
|
||||
if (itMacro->_value) {
|
||||
showCommands(itMacro->_value);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Macro not found.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("showmacro <G|L> <macroname>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_liststartups(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
const Startups &startups = script->getStartups();
|
||||
for (Startups::const_iterator it = startups.begin(); it != startups.end(); ++it) {
|
||||
debugPrintf("%u\n", (unsigned int) it->_key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("liststartups <G|L>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_showstartup(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
Script *const script = getScriptFromArg(argv[1]);
|
||||
if (script) {
|
||||
const Startups &startups = script->getStartups();
|
||||
Startups::const_iterator itMacro = startups.find(static_cast<uint8>(atoi(argv[2])));
|
||||
if (itMacro != startups.end()) {
|
||||
if (itMacro->_value) {
|
||||
showCommands(itMacro->_value);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Startup not found.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrintf("showstartup <G|L> <startupid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_changescene(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
const uint8 sceneId = atoi(argv[1]);
|
||||
const bool partB = argv[1][strlen(argv[1]) - 1] == 'B';
|
||||
|
||||
_vm->getGame().changeScene(sceneId, partB);
|
||||
} else {
|
||||
debugPrintf("changescene <scenename>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_dumpsceneinfo(int argc, const char **argv) {
|
||||
uint8 sceneId = _vm->getGame().getGameData()._currentScene;
|
||||
|
||||
if (argc == 2) {
|
||||
sceneId = atoi(argv[1]);
|
||||
} else if (argc != 1) {
|
||||
debugPrintf("dumpsceneinfo [<sceneid>]\n");
|
||||
}
|
||||
|
||||
if (Scene *const scene = _vm->getGame().getGameData().getScene(sceneId)) {
|
||||
debugPrintf("Scene ID: %u\n", (unsigned int) sceneId);
|
||||
debugPrintf("Startup: %u\n", (unsigned int) scene->_startup);
|
||||
debugPrintf("Delay: %u\n", (unsigned int) scene->_delay);
|
||||
debugPrintf("Doors: %u\n", (unsigned int) scene->_noDoors);
|
||||
debugPrintf("Objects: %u\n", (unsigned int) scene->_noObjects);
|
||||
debugPrintf("Statics: %u\n", (unsigned int) scene->_noStatics);
|
||||
debugPrintf("ObstacleY1: %u\n", (unsigned int) scene->_obstacleY1);
|
||||
debugPrintf("PalRotFirst: %u\n", (unsigned int) scene->_palRotFirst);
|
||||
debugPrintf("PalRotLast: %u\n", (unsigned int) scene->_palRotLast);
|
||||
debugPrintf("PalRotDelay: %u\n", (unsigned int) scene->_palRotDelay);
|
||||
} else {
|
||||
debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_dumpdoorinfo(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
const uint8 sceneId = atoi(argv[1]);
|
||||
const uint8 doorId = atoi(argv[2]);
|
||||
|
||||
Scene *const scene = _vm->getGame().getGameData().getScene(sceneId);
|
||||
if (scene) {
|
||||
Door *const door = scene->getDoor(doorId);
|
||||
if (door) {
|
||||
debugPrintf("Name: '%s'\n", convertToASCII(door->_name).c_str());
|
||||
debugPrintf("DestSceneId: %u\n", (unsigned int) door->_destSceneId);
|
||||
debugPrintf("DestX: %u\n", (unsigned int) door->_destX);
|
||||
debugPrintf("DestY: %u\n", (unsigned int) door->_destY);
|
||||
debugPrintf("X: %u\n", (unsigned int) door->_x);
|
||||
debugPrintf("Y: %u\n", (unsigned int) door->_y);
|
||||
debugPrintf("Width: %u\n", (unsigned int) door->_width);
|
||||
debugPrintf("Height: %u\n", (unsigned int) door->_height);
|
||||
debugPrintf("WalkToX: %u\n", (unsigned int) door->_walkToX);
|
||||
debugPrintf("WalkToY: %u\n", (unsigned int) door->_walkToY);
|
||||
debugPrintf("SP: %u\n", (unsigned int) door->_SP);
|
||||
} else {
|
||||
debugPrintf("Door %u not found.\n", (unsigned int) doorId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("dumpdoorinfo <sceneid> <doorid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Console::cmd_dumpobjectinfo(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
const uint8 sceneId = atoi(argv[1]);
|
||||
const uint8 objectId = atoi(argv[2]);
|
||||
|
||||
Scene *const scene = _vm->getGame().getGameData().getScene(sceneId);
|
||||
if (scene) {
|
||||
Object *const object = scene->getObject(objectId);
|
||||
if (object) {
|
||||
debugPrintf("AC: %u\n", (unsigned int) object->_active);
|
||||
debugPrintf("FA: %u\n", (unsigned int) object->_firstFrame);
|
||||
debugPrintf("FR: %u\n", (unsigned int) object->_randomFrame);
|
||||
debugPrintf("NA: %u\n", (unsigned int) object->_numFrames);
|
||||
debugPrintf("FS: %u\n", (unsigned int) object->_roomFrameLSB);
|
||||
debugPrintf("Jump chance: %u\n", (unsigned int) object->_jumpChance);
|
||||
debugPrintf("CA: %u\n", (unsigned int) object->_currentFrame);
|
||||
debugPrintf("X: %u\n", (unsigned int) object->_x);
|
||||
debugPrintf("Y: %u\n", (unsigned int) object->_y);
|
||||
debugPrintf("XL: %u\n", (unsigned int) object->_width);
|
||||
debugPrintf("YL: %u\n", (unsigned int) object->_height);
|
||||
debugPrintf("WX: %u\n", (unsigned int) object->_WX);
|
||||
debugPrintf("WY: %u\n", (unsigned int) object->_roomFrameMSB);
|
||||
debugPrintf("SP: %u\n", (unsigned int) object->_SP);
|
||||
} else {
|
||||
debugPrintf("Object %u not found.\n", (unsigned int) objectId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("dumpobjectinfo <sceneid> <objectid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_dumpstaticinfo(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
const uint8 sceneId = atoi(argv[1]);
|
||||
const uint8 staticId = atoi(argv[2]);
|
||||
|
||||
Scene *const scene = _vm->getGame().getGameData().getScene(sceneId);
|
||||
if (scene) {
|
||||
Static *const stat = scene->getStatic(staticId, true);
|
||||
if (stat) {
|
||||
debugPrintf("Active: %u\n", (unsigned int) stat->_active);
|
||||
debugPrintf("Name: '%s'\n", convertToASCII(stat->_name).c_str());
|
||||
debugPrintf("X: %u\n", (unsigned int) stat->_x);
|
||||
debugPrintf("Y: %u\n", (unsigned int) stat->_y);
|
||||
debugPrintf("Width: %u\n", (unsigned int) stat->_width);
|
||||
debugPrintf("Height: %u\n", (unsigned int) stat->_height);
|
||||
debugPrintf("WalkToX: %u\n", (unsigned int) stat->_walkToY);
|
||||
debugPrintf("WalkToY: %u\n", (unsigned int) stat->_walkToX);
|
||||
debugPrintf("WalkToFrame: %u\n", (unsigned int) stat->_walkToFrame);
|
||||
} else {
|
||||
debugPrintf("Static %u not found.\n", (unsigned int) staticId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("dumpstaticinfo <sceneid> <staticid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmd_dumpbitmapinfo(int argc, const char **argv) {
|
||||
if (argc == 3) {
|
||||
const uint8 sceneId = atoi(argv[1]);
|
||||
const uint8 bitmapId = atoi(argv[2]);
|
||||
|
||||
Scene *const scene = _vm->getGame().getGameData().getScene(sceneId);
|
||||
if (scene) {
|
||||
Bitmap *const bitmap = scene->getBitmap(bitmapId);
|
||||
if (bitmap) {
|
||||
debugPrintf("Room Frame: %u\n", (unsigned int) bitmap->_roomFrame);
|
||||
debugPrintf("Visible: %u\n", (unsigned int) bitmap->_isVisible);
|
||||
debugPrintf("X1: %u\n", (unsigned int) bitmap->_x1);
|
||||
debugPrintf("Y1: %u\n", (unsigned int) bitmap->_y1);
|
||||
debugPrintf("X2: %u\n", (unsigned int) bitmap->_x2);
|
||||
debugPrintf("Y2: %u\n", (unsigned int) bitmap->_y2);
|
||||
} else {
|
||||
debugPrintf("Bitmap %u not found.\n", (unsigned int) bitmapId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
|
||||
}
|
||||
} else {
|
||||
debugPrintf("dumpbitmapinfo <sceneid> <bitmapid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Script *Console::getScriptFromArg(const char *arg) {
|
||||
Script *script = nullptr;
|
||||
if (strcmp(arg, "G") == 0) {
|
||||
script = _vm->getGame().getGlobalScript();
|
||||
} else if (strcmp(arg, "L") == 0) {
|
||||
script = _vm->getGame().getLocalScript();
|
||||
}
|
||||
if (!script) {
|
||||
debugPrintf("Choose 'G' (global) or 'L' (local) script.\n");
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
bool Console::cmd_listinventory(int, const char **) {
|
||||
Inventory &inventory = _vm->getGame().getGameData().getInventory();
|
||||
const Inventory::Items &items = inventory.getItems();
|
||||
for (Inventory::Items::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||
debugPrintf("%s\n", convertToASCII(*it).c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
62
engines/mutationofjb/debug.h
Normal file
62
engines/mutationofjb/debug.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_DEBUG_H
|
||||
#define MUTATIONOFJB_DEBUG_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class MutationOfJBEngine;
|
||||
class Command;
|
||||
class Script;
|
||||
|
||||
class Console : public GUI::Debugger {
|
||||
public:
|
||||
Console(MutationOfJBEngine *vm);
|
||||
~Console(void) override {}
|
||||
private:
|
||||
bool cmd_showallcommands(int argc, const char **argv);
|
||||
bool cmd_listsections(int argc, const char **argv);
|
||||
bool cmd_showsection(int argc, const char **argv);
|
||||
bool cmd_listmacros(int argc, const char **argv);
|
||||
bool cmd_showmacro(int argc, const char **argv);
|
||||
bool cmd_liststartups(int argc, const char **argv);
|
||||
bool cmd_showstartup(int argc, const char **argv);
|
||||
bool cmd_changescene(int argc, const char **argv);
|
||||
bool cmd_dumpsceneinfo(int argc, const char **argv);
|
||||
bool cmd_dumpdoorinfo(int argc, const char **argv);
|
||||
bool cmd_dumpobjectinfo(int argc, const char **argv);
|
||||
bool cmd_dumpstaticinfo(int argc, const char **argv);
|
||||
bool cmd_dumpbitmapinfo(int argc, const char **argv);
|
||||
bool cmd_listinventory(int argc, const char **argv);
|
||||
|
||||
void showIndent(int indentLevel);
|
||||
void showCommands(Command *command, int indentLevel = 0);
|
||||
Script *getScriptFromArg(const char *arg);
|
||||
|
||||
MutationOfJBEngine *_vm;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
119
engines/mutationofjb/detection.cpp
Normal file
119
engines/mutationofjb/detection.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
static const PlainGameDescriptor mutationofjbGames[] = {
|
||||
{"mutationofjb", "Mutation of J.B."},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const ADGameDescription mutationofjbDescriptions[] = {
|
||||
{
|
||||
"mutationofjb",
|
||||
"",
|
||||
{
|
||||
{"jb.ex_", 0, "934164b09c72fa7167811f448ee0a426", 150048},
|
||||
{"startup.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"startupb.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"global.atn", 0, nullptr, AD_NO_SIZE},
|
||||
{"piggy.apk", 0, nullptr, AD_NO_SIZE},
|
||||
{"foogl.apk", 0, nullptr, AD_NO_SIZE},
|
||||
{"tosay.ger", 0, nullptr, AD_NO_SIZE},
|
||||
{"response.ger", 0, nullptr, AD_NO_SIZE},
|
||||
{"font1.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{"sysfnt.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
},
|
||||
Common::SK_SVK,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
"mutationofjb",
|
||||
"",
|
||||
{
|
||||
{"jb.ex_", 0, "8833f22f1763d05eeb909e8626cdec7b", 150800},
|
||||
{"startup.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"startupb.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"global.atn", 0, nullptr, AD_NO_SIZE},
|
||||
{"piggy.apk", 0, nullptr, AD_NO_SIZE},
|
||||
{"foogl.apk", 0, nullptr, AD_NO_SIZE},
|
||||
{"tosay.ger", 0, nullptr, AD_NO_SIZE},
|
||||
{"response.ger", 0, nullptr, AD_NO_SIZE},
|
||||
{"font1.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{"sysfnt.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
},
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{ // Demo from Riki Multimedia Magazine (Slovakia) #23 - Nov 1996
|
||||
"mutationofjb",
|
||||
"Demo",
|
||||
{
|
||||
{"jbdemo.exe", 0, "97943a569bacc4131447577436389276", 121696},
|
||||
{"strt.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"startupb.dat", 0, nullptr, AD_NO_SIZE},
|
||||
{"global.atn", 0, nullptr, AD_NO_SIZE},
|
||||
{"piggy.apk", 0, nullptr, AD_NO_SIZE},
|
||||
{"font1.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{"sysfnt.aft", 0, nullptr, AD_NO_SIZE},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
},
|
||||
Common::SK_SVK,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_DEMO,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
AD_TABLE_END_MARKER
|
||||
};
|
||||
|
||||
static const char *const mutationofjbDirectoryGlobs[] = {
|
||||
"data",
|
||||
nullptr
|
||||
};
|
||||
|
||||
class MutationOfJBMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
|
||||
public:
|
||||
MutationOfJBMetaEngineDetection() : AdvancedMetaEngineDetection(mutationofjbDescriptions, mutationofjbGames) {
|
||||
_maxScanDepth = 2;
|
||||
_directoryGlobs = mutationofjbDirectoryGlobs;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "mutationofjb";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Mutation of J.B.";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Mutation of J.B. (C) 1996 RIKI Computer Games";
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(MUTATIONOFJB_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, MutationOfJBMetaEngineDetection);
|
||||
63
engines/mutationofjb/encryptedfile.cpp
Normal file
63
engines/mutationofjb/encryptedfile.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "encryptedfile.h"
|
||||
|
||||
static const uint8 XOR_TABLE[] = {
|
||||
0x41, 0x2b, 0x7a, 0x0c, 0xc8, 0xe5, 0x0c, 0xde, 0x45, 0xa8, 0x00, 0xad,
|
||||
0x70, 0xac, 0x23, 0xe0, 0x0c, 0xde, 0xac, 0x16, 0xa1, 0x1a, 0x70, 0x17,
|
||||
0x1b, 0x90, 0x34, 0x6e, 0x53, 0xfe, 0xdd, 0x3c, 0xef, 0x74, 0x75, 0x3e,
|
||||
0x2e, 0xb0, 0x3d, 0x2b, 0x74, 0x6d, 0x59, 0xde, 0xc6, 0x20, 0xb8, 0xf3,
|
||||
0x7d, 0xfa, 0x4d, 0xbd, 0xdb, 0x3c, 0xc5, 0xcb, 0x57, 0x13, 0x40, 0x6b,
|
||||
0xb8, 0xad, 0xb9, 0xc1, 0x6a, 0x37, 0x39, 0x80, 0x94, 0xd3, 0xdf, 0x4b,
|
||||
0xe4, 0xe4, 0x7a, 0x4c, 0x0f, 0x21, 0x27, 0x9a, 0x7e, 0x52, 0x35, 0x58,
|
||||
0xb4, 0xbc, 0x5a, 0xc9, 0x48, 0x7f, 0xcc, 0xb6, 0x97, 0x7b, 0xf1, 0xd5,
|
||||
0x88, 0x8c, 0xa9, 0x27, 0xf7, 0x20, 0x68, 0x65, 0xad, 0x6f, 0x9e, 0x07,
|
||||
0xf8, 0xf6, 0x2c, 0x65, 0x4a, 0xe9, 0xd8, 0x13, 0x6a, 0xb5, 0x14, 0x6f,
|
||||
0x29, 0xdc, 0x68, 0xf8, 0xa0, 0xb6, 0x73, 0x03, 0x69, 0xe3, 0x4f, 0xb6,
|
||||
0x59, 0x79, 0xae, 0x93, 0xad, 0x40, 0x27, 0xd0, 0xb5, 0x7a, 0x68, 0x5d,
|
||||
0x5e, 0x19, 0x53, 0x4f, 0x40, 0x56, 0x3d, 0x10, 0xf8, 0x0a, 0xc6, 0x90,
|
||||
0x06, 0x45, 0x13, 0x4a, 0x6a, 0xfe, 0x56, 0xeb, 0xbc, 0xd9, 0xee, 0xe0,
|
||||
0x85, 0x5e, 0x98, 0x23, 0xf9, 0x19, 0x60, 0xf9, 0x7e, 0x8d, 0x61, 0xa0,
|
||||
0x7c, 0xe1, 0x84, 0xf2, 0x7a, 0xb8, 0xbe, 0x8e, 0x81, 0x9e, 0x87, 0x20,
|
||||
0x32, 0xf3, 0x8c, 0xb4, 0x2c, 0x4d, 0xc8, 0x50, 0x9b, 0xa5, 0x9c, 0x27,
|
||||
0x02, 0xd6, 0x7f, 0x2a, 0xaf, 0x46, 0x65, 0xd0, 0x6a, 0xae, 0xfa, 0x53,
|
||||
0x37, 0x6c, 0x49, 0xb9, 0x4d, 0xcd, 0x6c, 0x6b, 0xa7, 0x2d, 0x66, 0x32,
|
||||
0xb4, 0xf5, 0x41, 0xd5, 0x18, 0xc4, 0xfd, 0xbe, 0x8a, 0x47, 0x11, 0x50,
|
||||
0x3d, 0x97, 0x64, 0xda, 0x5a, 0x27, 0x18, 0x60, 0x78, 0x80, 0x86, 0x8a,
|
||||
0x2a, 0x72, 0x40, 0x89
|
||||
};
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
uint32 EncryptedFile::read(void *dataPtr, uint32 dataSize) {
|
||||
uint8 xorPos = static_cast<uint8>(pos() % ARRAYSIZE(XOR_TABLE));
|
||||
const uint32 readBytes = Common::File::read(dataPtr, dataSize);
|
||||
|
||||
for (uint32 i = 0; i < readBytes; ++i) {
|
||||
static_cast<uint8 *>(dataPtr)[i] ^= XOR_TABLE[xorPos];
|
||||
xorPos++;
|
||||
}
|
||||
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
}
|
||||
36
engines/mutationofjb/encryptedfile.h
Normal file
36
engines/mutationofjb/encryptedfile.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ENCRYPTEDFILE_H
|
||||
#define MUTATIONOFJB_ENCRYPTEDFILE_H
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class EncryptedFile : public Common::File {
|
||||
public:
|
||||
uint32 read(void *dataPtr, uint32 dataSize) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
163
engines/mutationofjb/font.cpp
Normal file
163
engines/mutationofjb/font.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/font.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/util.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
Font::Font(const Common::Path &fileName, int horizSpacing, int lineHeight) :
|
||||
_horizSpacing(horizSpacing),
|
||||
_lineHeight(lineHeight),
|
||||
_maxCharWidth(0) {
|
||||
|
||||
load(fileName);
|
||||
}
|
||||
|
||||
bool Font::load(const Common::Path &fileName) {
|
||||
EncryptedFile file;
|
||||
file.open(fileName);
|
||||
if (!file.isOpen()) {
|
||||
reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.seek(0x02D6, SEEK_SET); // Skip header + unknown data (unused palette?).
|
||||
|
||||
uint16 noGlyphs = 0;
|
||||
noGlyphs = file.readUint16LE();
|
||||
|
||||
file.seek(7, SEEK_CUR); // Skip unknown data (0s).
|
||||
|
||||
uint8 maxHeight = 0;
|
||||
|
||||
while (noGlyphs--) {
|
||||
const uint8 character = file.readByte();
|
||||
const uint8 width = file.readByte();
|
||||
const uint8 height = file.readByte();
|
||||
|
||||
Graphics::ManagedSurface &surf = _glyphs[character];
|
||||
surf.create(width, height);
|
||||
for (int h = 0; h < height; ++h) {
|
||||
file.read(surf.getBasePtr(0, h), width);
|
||||
}
|
||||
|
||||
if (width > _maxCharWidth) {
|
||||
_maxCharWidth = width;
|
||||
}
|
||||
|
||||
if (height > maxHeight) {
|
||||
maxHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lineHeight == -1) {
|
||||
_lineHeight = maxHeight;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Font::getFontHeight() const {
|
||||
return _lineHeight;
|
||||
}
|
||||
|
||||
int Font::getMaxCharWidth() const {
|
||||
return _maxCharWidth;
|
||||
}
|
||||
|
||||
int Font::getCharWidth(uint32 chr) const {
|
||||
GlyphMap::iterator it = _glyphs.find(chr);
|
||||
if (it == _glyphs.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->_value.w;
|
||||
}
|
||||
|
||||
int Font::getKerningOffset(uint32 left, uint32 right) const {
|
||||
if (left == 0) {
|
||||
// Do not displace the first character.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_glyphs.find(left) == _glyphs.end()) {
|
||||
// Missing glyphs must not create extra displacement.
|
||||
// FIXME: This way is not completely correct, as if the last character is
|
||||
// missing a glyph, it will still create extra displacement. This should
|
||||
// not affect the visuals but it might affect getStringWidth() / getBoundingBox().
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _horizSpacing;
|
||||
}
|
||||
|
||||
class FontBlitOperation {
|
||||
public:
|
||||
FontBlitOperation(const Font &font, const byte baseColor)
|
||||
: _font(font),
|
||||
_baseColor(baseColor) {}
|
||||
|
||||
byte operator()(const byte srcColor, const byte destColor) {
|
||||
if (srcColor == 0) {
|
||||
// Transparency - keep destination color.
|
||||
return destColor;
|
||||
}
|
||||
|
||||
// Replace destination with transformed source color.
|
||||
return _font.transformColor(_baseColor, srcColor);
|
||||
}
|
||||
|
||||
private:
|
||||
const Font &_font;
|
||||
const byte _baseColor;
|
||||
};
|
||||
|
||||
void Font::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
|
||||
GlyphMap::iterator it = _glyphs.find(chr);
|
||||
if (it == _glyphs.end()) {
|
||||
// Missing glyph is a common situation in the game and it's okay to ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface &glyphSurface = it->_value;
|
||||
blit_if(glyphSurface, *dst, Common::Point(x, y), FontBlitOperation(*this, color));
|
||||
}
|
||||
|
||||
uint8 Font::transformColor(uint8 baseColor, uint8 glyphColor) const {
|
||||
return baseColor + glyphColor - 0x10;
|
||||
}
|
||||
|
||||
SystemFont::SystemFont() : Font("sysfnt.aft", 1, 7) {}
|
||||
|
||||
SpeechFont::SpeechFont() : Font("font1.aft", -1, -1) {}
|
||||
|
||||
uint8 SpeechFont::transformColor(uint8 baseColor, uint8 glyphColor) const {
|
||||
// Hack in original game.
|
||||
if (glyphColor == 0x11) {
|
||||
return 0xC0;
|
||||
}
|
||||
|
||||
return Font::transformColor(baseColor, glyphColor);
|
||||
}
|
||||
|
||||
}
|
||||
77
engines/mutationofjb/font.h
Normal file
77
engines/mutationofjb/font.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_FONT_H
|
||||
#define MUTATIONOFJB_FONT_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/path.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Font : public Graphics::Font {
|
||||
friend class FontBlitOperation;
|
||||
public:
|
||||
Font(const Common::Path &fileName, int horizSpacing, int lineHeight);
|
||||
|
||||
int getFontHeight() const override;
|
||||
int getMaxCharWidth() const override;
|
||||
int getCharWidth(uint32 chr) const override;
|
||||
int getKerningOffset(uint32 left, uint32 right) const override;
|
||||
void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
|
||||
|
||||
protected:
|
||||
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) const;
|
||||
|
||||
private:
|
||||
bool load(const Common::Path &fileName);
|
||||
|
||||
int _horizSpacing;
|
||||
int _lineHeight;
|
||||
int _maxCharWidth;
|
||||
typedef Common::HashMap<uint8, Graphics::ManagedSurface> GlyphMap;
|
||||
GlyphMap _glyphs;
|
||||
};
|
||||
|
||||
class SystemFont : public Font {
|
||||
public:
|
||||
SystemFont();
|
||||
};
|
||||
|
||||
class SpeechFont : public Font {
|
||||
public:
|
||||
SpeechFont();
|
||||
|
||||
protected:
|
||||
uint8 transformColor(uint8 baseColor, uint8 glyphColor) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
278
engines/mutationofjb/game.cpp
Normal file
278
engines/mutationofjb/game.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
#include "mutationofjb/room.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/tasks/objectanimationtask.h"
|
||||
#include "mutationofjb/util.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
Game::Game(MutationOfJBEngine *vm)
|
||||
: _vm(vm),
|
||||
_randomSource("mutationofjb"),
|
||||
_delayedLocalScript(nullptr),
|
||||
_runDelayedScriptStartup(false),
|
||||
_gui(*this, _vm->getScreen()),
|
||||
_scriptExecCtx(*this),
|
||||
_taskManager(*this),
|
||||
_assets(*this) {
|
||||
|
||||
_gameData = new GameData;
|
||||
loadGameData(false);
|
||||
|
||||
EncryptedFile globalScriptFile;
|
||||
globalScriptFile.open("global.atn");
|
||||
_globalScript = new Script;
|
||||
_globalScript->loadFromStream(globalScriptFile);
|
||||
globalScriptFile.close();
|
||||
|
||||
_localScript = nullptr;
|
||||
_room = new Room(this, _vm->getScreen());
|
||||
|
||||
_gui.init();
|
||||
|
||||
_taskManager.startTask(TaskPtr(new ObjectAnimationTask));
|
||||
}
|
||||
|
||||
MutationOfJBEngine &Game::getEngine() {
|
||||
return *_vm;
|
||||
}
|
||||
|
||||
Common::RandomSource &Game::getRandomSource() {
|
||||
return _randomSource;
|
||||
}
|
||||
|
||||
GameData &Game::getGameData() {
|
||||
return *_gameData;
|
||||
}
|
||||
|
||||
Room &Game::getRoom() {
|
||||
return *_room;
|
||||
}
|
||||
|
||||
Script *Game::getGlobalScript() const {
|
||||
return _globalScript;
|
||||
}
|
||||
|
||||
Script *Game::getLocalScript() const {
|
||||
return _localScript;
|
||||
}
|
||||
|
||||
bool Game::loadGameData(bool partB) {
|
||||
EncryptedFile file;
|
||||
const char *fileName = !partB ? "startup.dat" : "startupb.dat";
|
||||
file.open(fileName);
|
||||
if (!file.isOpen()) {
|
||||
reportFileMissingError(fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
_gameData->loadInitialState(file);
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Script *Game::changeSceneLoadScript(uint8 sceneId, bool partB) {
|
||||
if (isCurrentSceneMap()) {
|
||||
_gui.markDirty();
|
||||
}
|
||||
|
||||
_gameData->_lastScene = _gameData->_currentScene;
|
||||
_gameData->_currentScene = sceneId;
|
||||
_gameData->_partB = partB;
|
||||
|
||||
_room->load(_gameData->_currentScene, partB);
|
||||
_gui.refreshAfterSceneChanged();
|
||||
|
||||
EncryptedFile scriptFile;
|
||||
Common::Path fileName(Common::String::format("scrn%d%s.atn", sceneId, partB ? "b" : ""));
|
||||
scriptFile.open(fileName);
|
||||
if (!scriptFile.isOpen()) {
|
||||
reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO Actually parse this.
|
||||
Common::String dummy;
|
||||
dummy = scriptFile.readLine(); // Skip first line.
|
||||
scriptFile.seek(126, SEEK_CUR); // Skip 126 bytes.
|
||||
|
||||
Script *localScript = new Script;
|
||||
localScript->loadFromStream(scriptFile);
|
||||
scriptFile.close();
|
||||
|
||||
return localScript;
|
||||
}
|
||||
|
||||
void Game::changeScene(uint8 sceneId, bool partB) {
|
||||
if (_localScript) {
|
||||
delete _localScript;
|
||||
_localScript = nullptr;
|
||||
}
|
||||
|
||||
_localScript = changeSceneLoadScript(sceneId, partB);
|
||||
if (_localScript) {
|
||||
_scriptExecCtx.startStartupSection();
|
||||
}
|
||||
}
|
||||
|
||||
Script *Game::changeSceneDelayScript(uint8 sceneId, bool partB, bool runDelayedScriptStartup) {
|
||||
_delayedLocalScript = changeSceneLoadScript(sceneId, partB);
|
||||
_runDelayedScriptStartup = runDelayedScriptStartup;
|
||||
return _delayedLocalScript;
|
||||
}
|
||||
|
||||
static Command *findActionInfoCommand(const ActionInfos &infos, const Common::String &entity1Name, const Common::String &entity2Name = Common::String()) {
|
||||
for (ActionInfos::const_iterator it = infos.begin(); it != infos.end(); ++it) {
|
||||
if (it->_entity1Name == entity1Name && it->_entity2Name == entity2Name) {
|
||||
return it->_command;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Game::startActionSection(ActionInfo::Action action, const Common::String &entity1Name, const Common::String &entity2Name) {
|
||||
Script *const localScript = getLocalScript();
|
||||
Script *const globalScript = getGlobalScript();
|
||||
|
||||
Command *command = nullptr;
|
||||
if (localScript) {
|
||||
command = findActionInfoCommand(localScript->getActionInfos(action), entity1Name, entity2Name);
|
||||
}
|
||||
if (!command && globalScript) {
|
||||
command = findActionInfoCommand(globalScript->getActionInfos(action), entity1Name, entity2Name);
|
||||
}
|
||||
if (command) {
|
||||
_scriptExecCtx.startCommand(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Game::isCurrentSceneMap() const {
|
||||
return _gameData->_currentScene == 12;
|
||||
}
|
||||
|
||||
void Game::update() {
|
||||
Command::ExecuteResult res = _scriptExecCtx.runActiveCommand();
|
||||
if (res == Command::Finished && _delayedLocalScript) {
|
||||
delete _localScript;
|
||||
_localScript = _delayedLocalScript;
|
||||
|
||||
if (_localScript && _runDelayedScriptStartup)
|
||||
_scriptExecCtx.startStartupSection();
|
||||
|
||||
_delayedLocalScript = nullptr;
|
||||
_runDelayedScriptStartup = false;
|
||||
}
|
||||
|
||||
_taskManager.update();
|
||||
}
|
||||
|
||||
GameScreen &Game::getGameScreen() {
|
||||
return _gui;
|
||||
}
|
||||
|
||||
uint8 Game::colorFromString(const char *colorStr) {
|
||||
struct {
|
||||
const char *str;
|
||||
uint8 color;
|
||||
} colors[] = {
|
||||
{"white", WHITE},
|
||||
{"darkgray", DARKGRAY},
|
||||
{"lightgray", LIGHTGRAY},
|
||||
{"green", GREEN},
|
||||
{"orange", ORANGE},
|
||||
{"darkblue", DARKBLUE},
|
||||
{"lightblue", LIGHTBLUE},
|
||||
{"brown", BROWN}
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(colors); ++i) {
|
||||
if (strcmp(colors[i].str, colorStr) == 0) {
|
||||
return colors[i].color;
|
||||
}
|
||||
}
|
||||
|
||||
if (*colorStr == 'n') {
|
||||
return static_cast<uint8>(atoi(colorStr + 1));
|
||||
}
|
||||
|
||||
warning("Color not found");
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
TaskManager &Game::getTaskManager() {
|
||||
return _taskManager;
|
||||
}
|
||||
|
||||
Assets &Game::getAssets() {
|
||||
return _assets;
|
||||
}
|
||||
|
||||
Graphics::Screen &Game::getScreen() {
|
||||
return *_vm->getScreen();
|
||||
}
|
||||
|
||||
TaskPtr Game::getActiveSayTask() const {
|
||||
return _activeSayTask;
|
||||
}
|
||||
|
||||
void Game::setActiveSayTask(const TaskPtr &sayTask) {
|
||||
_activeSayTask = sayTask;
|
||||
}
|
||||
|
||||
bool Game::loadSaveAllowed() const {
|
||||
if (_scriptExecCtx.isCommandRunning())
|
||||
return false;
|
||||
|
||||
if (isCurrentSceneMap())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Language Game::getLanguage() const {
|
||||
return _vm->getGameDescription()->language;
|
||||
}
|
||||
|
||||
void Game::switchToPartB() {
|
||||
getGameData().getInventory().removeAllItems();
|
||||
loadGameData(true);
|
||||
changeSceneDelayScript(3, true, true);
|
||||
}
|
||||
|
||||
}
|
||||
114
engines/mutationofjb/game.h
Normal file
114
engines/mutationofjb/game.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_GAME_H
|
||||
#define MUTATIONOFJB_GAME_H
|
||||
|
||||
#include "mutationofjb/assets.h"
|
||||
#include "mutationofjb/gamescreen.h"
|
||||
#include "mutationofjb/tasks/taskmanager.h"
|
||||
|
||||
#include "common/language.h"
|
||||
#include "common/ptr.h"
|
||||
#include "common/random.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Command;
|
||||
class MutationOfJBEngine;
|
||||
class Script;
|
||||
class Room;
|
||||
class SayTask;
|
||||
struct GameData;
|
||||
struct Door;
|
||||
struct Static;
|
||||
struct Bitmap;
|
||||
|
||||
class Game {
|
||||
public:
|
||||
Game(MutationOfJBEngine *vm);
|
||||
MutationOfJBEngine &getEngine();
|
||||
|
||||
Common::RandomSource &getRandomSource();
|
||||
GameData &getGameData();
|
||||
Room &getRoom();
|
||||
Script *getGlobalScript() const;
|
||||
Script *getLocalScript() const;
|
||||
|
||||
void changeScene(uint8 sceneId, bool partB);
|
||||
Script *changeSceneDelayScript(uint8 sceneId, bool partB, bool runDelayedScriptStartup = false);
|
||||
|
||||
bool startActionSection(ActionInfo::Action action, const Common::String &entity1Name, const Common::String &entity2Name = Common::String());
|
||||
|
||||
bool isCurrentSceneMap() const;
|
||||
|
||||
void update();
|
||||
|
||||
GameScreen &getGameScreen();
|
||||
|
||||
static uint8 colorFromString(const char *colorStr);
|
||||
|
||||
TaskManager &getTaskManager();
|
||||
Assets &getAssets();
|
||||
|
||||
Graphics::Screen &getScreen();
|
||||
|
||||
TaskPtr getActiveSayTask() const;
|
||||
void setActiveSayTask(const TaskPtr &sayTask);
|
||||
|
||||
bool loadSaveAllowed() const;
|
||||
|
||||
Common::Language getLanguage() const;
|
||||
|
||||
void switchToPartB();
|
||||
|
||||
private:
|
||||
bool loadGameData(bool partB);
|
||||
void runActiveCommand();
|
||||
void startCommand(Command *cmd);
|
||||
Script *changeSceneLoadScript(uint8 sceneId, bool partB);
|
||||
|
||||
MutationOfJBEngine *_vm;
|
||||
Common::RandomSource _randomSource;
|
||||
|
||||
GameData *_gameData;
|
||||
Script *_globalScript;
|
||||
Script *_localScript;
|
||||
Script *_delayedLocalScript;
|
||||
bool _runDelayedScriptStartup;
|
||||
Room *_room;
|
||||
GameScreen _gui;
|
||||
|
||||
ScriptExecutionContext _scriptExecCtx;
|
||||
|
||||
TaskManager _taskManager;
|
||||
Assets _assets;
|
||||
TaskPtr _activeSayTask;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
428
engines/mutationofjb/gamedata.cpp
Normal file
428
engines/mutationofjb/gamedata.cpp
Normal file
@@ -0,0 +1,428 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
static bool readEntityNameString(Common::ReadStream &stream, char *str) {
|
||||
char buf[MAX_ENTITY_NAME_LENGTH];
|
||||
memset(str, 0, MAX_ENTITY_NAME_LENGTH + 1);
|
||||
|
||||
uint8 len = stream.readByte();
|
||||
stream.read(buf, MAX_ENTITY_NAME_LENGTH);
|
||||
|
||||
len = MIN(len, static_cast<uint8>(MAX_ENTITY_NAME_LENGTH));
|
||||
memcpy(str, buf, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void syncEntityNameString(char *cstr, Common::Serializer &sz) {
|
||||
if (sz.isLoading()) {
|
||||
Common::String str;
|
||||
sz.syncString(str);
|
||||
strncpy(cstr, str.c_str(), MAX_ENTITY_NAME_LENGTH);
|
||||
cstr[MAX_ENTITY_NAME_LENGTH] = 0;
|
||||
} else {
|
||||
Common::String str(cstr);
|
||||
sz.syncString(str);
|
||||
}
|
||||
}
|
||||
|
||||
bool Door::isActive() {
|
||||
return *_name != '\0';
|
||||
}
|
||||
|
||||
bool Door::loadInitialState(Common::ReadStream &stream) {
|
||||
readEntityNameString(stream, _name);
|
||||
|
||||
_destSceneId = stream.readByte();
|
||||
_destX = stream.readUint16LE();
|
||||
_destY = stream.readUint16LE();
|
||||
_x = stream.readUint16LE();
|
||||
_y = stream.readByte();
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readByte();
|
||||
_walkToX = stream.readUint16LE();
|
||||
_walkToY = stream.readByte();
|
||||
_SP = stream.readByte();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Door::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
syncEntityNameString(_name, sz);
|
||||
sz.syncAsByte(_destSceneId);
|
||||
sz.syncAsUint16LE(_destX);
|
||||
sz.syncAsUint16LE(_destY);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_walkToX);
|
||||
sz.syncAsByte(_walkToY);
|
||||
sz.syncAsByte(_SP);
|
||||
}
|
||||
|
||||
bool Door::allowsImplicitSceneChange() const {
|
||||
const size_t length = strlen(_name);
|
||||
if (length == 0)
|
||||
return false;
|
||||
|
||||
return _name[length - 1] != '+';
|
||||
}
|
||||
|
||||
bool Object::loadInitialState(Common::ReadStream &stream) {
|
||||
_active = stream.readByte();
|
||||
_firstFrame = stream.readByte();
|
||||
_randomFrame = stream.readByte();
|
||||
_numFrames = stream.readByte();
|
||||
_roomFrameLSB = stream.readByte();
|
||||
_jumpChance = stream.readByte();
|
||||
_currentFrame = stream.readByte();
|
||||
_x = stream.readUint16LE();
|
||||
_y = stream.readByte();
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readByte();
|
||||
_WX = stream.readUint16LE();
|
||||
_roomFrameMSB = stream.readByte();
|
||||
_SP = stream.readByte();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Object::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_active);
|
||||
sz.syncAsByte(_firstFrame);
|
||||
sz.syncAsByte(_randomFrame);
|
||||
sz.syncAsByte(_numFrames);
|
||||
sz.syncAsByte(_roomFrameLSB);
|
||||
sz.syncAsByte(_jumpChance);
|
||||
sz.syncAsByte(_currentFrame);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_WX);
|
||||
sz.syncAsByte(_roomFrameMSB);
|
||||
sz.syncAsByte(_SP);
|
||||
}
|
||||
|
||||
bool Static::loadInitialState(Common::ReadStream &stream) {
|
||||
_active = stream.readByte();
|
||||
readEntityNameString(stream, _name);
|
||||
_x = stream.readUint16LE();
|
||||
_y = stream.readByte();
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readByte();
|
||||
_walkToX = stream.readUint16LE();
|
||||
_walkToY = stream.readByte();
|
||||
_walkToFrame = stream.readByte();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Static::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_active);
|
||||
syncEntityNameString(_name, sz);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_walkToX);
|
||||
sz.syncAsByte(_walkToY);
|
||||
sz.syncAsByte(_walkToFrame);
|
||||
}
|
||||
|
||||
bool Static::isCombinable() const {
|
||||
const size_t length = strlen(_name);
|
||||
if (length == 0)
|
||||
return false;
|
||||
|
||||
return _name[length - 1] == '[';
|
||||
}
|
||||
|
||||
bool Static::allowsImplicitPickup() const {
|
||||
return _name[0] == '~';
|
||||
}
|
||||
|
||||
bool Bitmap::loadInitialState(Common::ReadStream &stream) {
|
||||
_roomFrame = stream.readByte();
|
||||
_isVisible = stream.readByte();
|
||||
_x1 = stream.readUint16LE();
|
||||
_y1 = stream.readByte();
|
||||
_x2 = stream.readUint16LE();
|
||||
_y2 = stream.readByte();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bitmap::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_roomFrame);
|
||||
sz.syncAsByte(_isVisible);
|
||||
sz.syncAsUint16LE(_x1);
|
||||
sz.syncAsByte(_y1);
|
||||
sz.syncAsUint16LE(_x2);
|
||||
sz.syncAsByte(_y2);
|
||||
}
|
||||
|
||||
bool Scene::loadInitialState(Common::ReadStream &stream) {
|
||||
int i;
|
||||
|
||||
_startup = stream.readByte();
|
||||
_unknown001 = stream.readByte();
|
||||
_unknown002 = stream.readByte();
|
||||
_unknown003 = stream.readByte();
|
||||
_delay = stream.readByte();
|
||||
|
||||
_noDoors = stream.readByte();
|
||||
_noDoors = MIN(_noDoors, static_cast<uint8>(ARRAYSIZE(_doors)));
|
||||
for (i = 0; i < ARRAYSIZE(_doors); ++i) {
|
||||
_doors[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_noObjects = stream.readByte();
|
||||
_noObjects = MIN(_noObjects, static_cast<uint8>(ARRAYSIZE(_objects)));
|
||||
for (i = 0; i < ARRAYSIZE(_objects); ++i) {
|
||||
_objects[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_noStatics = stream.readByte();
|
||||
_noStatics = MIN(_noStatics, static_cast<uint8>(ARRAYSIZE(_statics)));
|
||||
for (i = 0; i < ARRAYSIZE(_statics); ++i) {
|
||||
_statics[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(_bitmaps); ++i) {
|
||||
_bitmaps[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_obstacleY1 = stream.readUint16LE();
|
||||
_palRotFirst = stream.readByte();
|
||||
_palRotLast = stream.readByte();
|
||||
_palRotDelay = stream.readByte();
|
||||
_exhaustedConvItemNext = stream.readByte();
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(_exhaustedConvItems); ++i) {
|
||||
_exhaustedConvItems[i]._encodedData = stream.readByte();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scene::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_startup);
|
||||
sz.syncAsByte(_unknown001);
|
||||
sz.syncAsByte(_unknown002);
|
||||
sz.syncAsByte(_unknown003);
|
||||
sz.syncAsByte(_delay);
|
||||
|
||||
sz.syncAsByte(_noDoors);
|
||||
for (int i = 0; i < ARRAYSIZE(_doors); ++i) {
|
||||
_doors[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_noObjects);
|
||||
for (int i = 0; i < ARRAYSIZE(_objects); ++i) {
|
||||
_objects[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_noStatics);
|
||||
for (int i = 0; i < ARRAYSIZE(_statics); ++i) {
|
||||
_statics[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_bitmaps); ++i) {
|
||||
_bitmaps[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsUint16LE(_obstacleY1);
|
||||
sz.syncAsByte(_palRotFirst);
|
||||
sz.syncAsByte(_palRotLast);
|
||||
sz.syncAsByte(_palRotDelay);
|
||||
sz.syncAsByte(_exhaustedConvItemNext);
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_exhaustedConvItems); ++i) {
|
||||
sz.syncAsByte(_exhaustedConvItems[i]._encodedData);
|
||||
}
|
||||
}
|
||||
|
||||
Door *Scene::getDoor(uint8 doorId) {
|
||||
if (doorId == 0 || doorId > _noDoors) {
|
||||
warning("Door %d does not exist", doorId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_doors[doorId - 1];
|
||||
}
|
||||
|
||||
Object *Scene::getObject(uint8 objectId, bool ignoreNo) {
|
||||
if (objectId == 0 || objectId > getNoObjects(ignoreNo)) {
|
||||
warning("Object %d does not exist", objectId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_objects[objectId - 1];
|
||||
}
|
||||
|
||||
Static *Scene::getStatic(uint8 staticId, bool ignoreNo) {
|
||||
if (staticId == 0 || staticId > (!ignoreNo ? MIN(_noStatics, static_cast<uint8>(ARRAYSIZE(_statics))) : ARRAYSIZE(_statics))) {
|
||||
warning("Static %d does not exist", staticId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_statics[staticId - 1];
|
||||
}
|
||||
|
||||
Bitmap *Scene::getBitmap(uint8 bitmapId) {
|
||||
if (bitmapId == 0 || bitmapId > ARRAYSIZE(_bitmaps)) {
|
||||
warning("Bitmap %d does not exist", bitmapId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_bitmaps[bitmapId - 1];
|
||||
}
|
||||
|
||||
uint8 Scene::getNoDoors(bool ignoreNo) const {
|
||||
return (!ignoreNo ? MIN(_noDoors, static_cast<uint8>(ARRAYSIZE(_doors))) : ARRAYSIZE(_doors));
|
||||
}
|
||||
|
||||
uint8 Scene::getNoObjects(bool ignoreNo) const {
|
||||
return (!ignoreNo ? MIN(_noObjects, static_cast<uint8>(ARRAYSIZE(_objects))) : ARRAYSIZE(_objects));
|
||||
}
|
||||
|
||||
uint8 Scene::getNoStatics(bool ignoreNo) const {
|
||||
return (!ignoreNo ? MIN(_noStatics, static_cast<uint8>(ARRAYSIZE(_statics))) : ARRAYSIZE(_statics));
|
||||
}
|
||||
|
||||
uint8 Scene::getNoBitmaps() const {
|
||||
return ARRAYSIZE(_bitmaps);
|
||||
}
|
||||
|
||||
Door *Scene::findDoor(int16 x, int16 y, bool activeOnly, int *index) {
|
||||
for (int i = 0; i < getNoDoors(); ++i) {
|
||||
Door &door = _doors[i];
|
||||
if ((!activeOnly || door.isActive()) && (x >= door._x) && (x < door._x + door._width) && (y >= door._y) && (y < door._y + door._height)) {
|
||||
if (index) {
|
||||
*index = i + 1;
|
||||
}
|
||||
return &door;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Static *Scene::findStatic(int16 x, int16 y, bool activeOnly, int *index) {
|
||||
for (int i = 0; i < getNoStatics(); ++i) {
|
||||
Static &stat = _statics[i];
|
||||
if ((!activeOnly || stat._active) && (x >= stat._x) && (x < stat._x + stat._width) && (y >= stat._y) && (y < stat._y + stat._height)) {
|
||||
if (index) {
|
||||
*index = i + 1;
|
||||
}
|
||||
return &stat;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bitmap *Scene::findBitmap(int16 x, int16 y, int *index) {
|
||||
for (int i = 0; i < ARRAYSIZE(_bitmaps); ++i) {
|
||||
Bitmap &bitmap = _bitmaps[i];
|
||||
if ((x >= bitmap._x1) && (x <= bitmap._x2) && (y >= bitmap._y1) && (y <= bitmap._y2)) {
|
||||
if (index) {
|
||||
*index = i + 1;
|
||||
}
|
||||
return &bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Scene::addExhaustedConvItem(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) {
|
||||
_exhaustedConvItems[_exhaustedConvItemNext - 1] = ExhaustedConvItem(context, convItemIndex, convGroupIndex);
|
||||
_exhaustedConvItemNext++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
GameData::GameData()
|
||||
: _currentScene(0),
|
||||
_lastScene(0),
|
||||
_partB(false),
|
||||
_inventory(),
|
||||
_currentAPK("piggy.apk"),
|
||||
_color(WHITE) {}
|
||||
|
||||
Scene *GameData::getScene(uint8 sceneId) {
|
||||
if (sceneId == 0 || sceneId > ARRAYSIZE(_scenes)) {
|
||||
warning("Scene %d does not exist", sceneId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_scenes[sceneId - 1];
|
||||
}
|
||||
|
||||
Scene *GameData::getCurrentScene() {
|
||||
return getScene(_currentScene);
|
||||
}
|
||||
|
||||
Inventory &GameData::getInventory() {
|
||||
return _inventory;
|
||||
}
|
||||
|
||||
bool GameData::loadInitialState(Common::ReadStream &stream) {
|
||||
for (int i = 0; i < ARRAYSIZE(_scenes); ++i) {
|
||||
_scenes[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameData::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
for (int i = 0; i < ARRAYSIZE(_scenes); ++i) {
|
||||
_scenes[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_currentScene);
|
||||
sz.syncAsByte(_partB);
|
||||
_inventory.saveLoadWithSerializer(sz);
|
||||
sz.syncString(_currentAPK);
|
||||
}
|
||||
|
||||
}
|
||||
490
engines/mutationofjb/gamedata.h
Normal file
490
engines/mutationofjb/gamedata.h
Normal file
@@ -0,0 +1,490 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_GAMEDATA_H
|
||||
#define MUTATIONOFJB_GAMEDATA_H
|
||||
|
||||
#include "mutationofjb/inventory.h"
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Common {
|
||||
class ReadStream;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
enum {
|
||||
MAX_ENTITY_NAME_LENGTH = 0x14
|
||||
};
|
||||
|
||||
/** @file
|
||||
* There are 4 types of entities present in the game data:
|
||||
* - Door
|
||||
* - Object
|
||||
* - Static
|
||||
* - Bitmap
|
||||
*/
|
||||
|
||||
/**
|
||||
* An interactable scene changer with no visual representation.
|
||||
*/
|
||||
struct Door : public Common::Serializable {
|
||||
/**
|
||||
* Door name (NM register).
|
||||
*
|
||||
* Can be empty - deactivates door completely (you can't mouse over or interact with it at all).
|
||||
*
|
||||
* If it ends with '+', using the "go" verb on the door will not implicitly change the scene,
|
||||
* but the player will still walk towards the door.
|
||||
*/
|
||||
char _name[MAX_ENTITY_NAME_LENGTH + 1];
|
||||
/**
|
||||
* Scene ID where the door leads (LT register).
|
||||
* Can be 0 - you can hover your mouse over it, but clicking it doesn't do anything (unless scripted).
|
||||
*/
|
||||
uint8 _destSceneId;
|
||||
/** X coordinate for player's position after going through the door (SX register). */
|
||||
uint16 _destX;
|
||||
/** Y coordinate for player's position after going through the door (SY register). */
|
||||
uint16 _destY;
|
||||
/** X coordinate of the door rectangle (XX register). */
|
||||
uint16 _x;
|
||||
/** Y coordinate of the door rectangle (YY register). */
|
||||
uint8 _y;
|
||||
/** Width of the door rectangle (XL register). */
|
||||
uint16 _width;
|
||||
/** Height of the door rectangle (YL register). */
|
||||
uint8 _height;
|
||||
/** X coordinate for position player will walk towards after clicking the door (WX register). */
|
||||
uint16 _walkToX;
|
||||
/** Y coordinate for position player will walk towards after clicking the door (WY register). */
|
||||
uint8 _walkToY;
|
||||
/**
|
||||
* Encoded player frames.
|
||||
* 4 bits - destFrame
|
||||
* 4 bits - walkToFrame
|
||||
*/
|
||||
uint8 _SP;
|
||||
|
||||
/**
|
||||
* Check if this door can be interacted with.
|
||||
* @return True if this door can be interacted with, false otherwise.
|
||||
*/
|
||||
bool isActive();
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
/**
|
||||
* Check whether walk action used on this door causes implicit scene change.
|
||||
*
|
||||
* @return True if door implicitly changes current scene, false otherwise.
|
||||
*/
|
||||
bool allowsImplicitSceneChange() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* An animated image in the scene.
|
||||
*
|
||||
* Object frames consist of surfaces carved out of room frames (starting from _roomFrame
|
||||
* up until _roomFrame + _numFrames - 1) based on the object's rectangle. They are stored
|
||||
* in the shared object frame space that each object occupies a continuous part of from
|
||||
* the beginning.
|
||||
*
|
||||
* By using the term "frame" alone we will be referring to an object frame, not a room
|
||||
* frame.
|
||||
*
|
||||
* For details regarding animation playback, see objectanimationtask.cpp.
|
||||
*/
|
||||
struct Object : public Common::Serializable {
|
||||
/** Controls whether the animation is playing. */
|
||||
uint8 _active;
|
||||
/**
|
||||
* Number of the first frame this object has in the shared object frame space (FA register).
|
||||
*
|
||||
* For the first object, it is equal to 1.
|
||||
* For any subsequent object, it is equal to (_firstFrame + _numFrames) of the previous object.
|
||||
*
|
||||
* @note The numbering starts from 1.
|
||||
* @note Technically this field is useless because it can be calculated.
|
||||
*/
|
||||
uint8 _firstFrame;
|
||||
/**
|
||||
* The frame that is jumped to randomly based on _jumpChance (FR register).
|
||||
*
|
||||
* @note Numbered from 1 and relative to _firstFrame.
|
||||
* @note A value of 0 disables randomness completely.
|
||||
* @see objectanimationtask.cpp
|
||||
* @see _jumpChance
|
||||
*/
|
||||
uint8 _randomFrame;
|
||||
/** Number of animation frames (NA register). */
|
||||
uint8 _numFrames;
|
||||
/**
|
||||
* Low 8 bits of the 16-bit starting room frame (FS register).
|
||||
* This is in the room frame space.
|
||||
*
|
||||
* @see _roomFrameMSB
|
||||
*/
|
||||
uint8 _roomFrameLSB;
|
||||
/**
|
||||
* Chance (1 in x) of the animation jumping to _randomFrame.
|
||||
*
|
||||
* @see objectanimationtask.cpp
|
||||
*/
|
||||
uint8 _jumpChance;
|
||||
/**
|
||||
* Current animation frame (CA register).
|
||||
*
|
||||
* @note Index in the shared object frame space. Numbered from 1.
|
||||
*/
|
||||
uint8 _currentFrame;
|
||||
/** X coordinate of the object rectangle (XX register). */
|
||||
uint16 _x;
|
||||
/** Y coordinate of the object rectangle (YY register). */
|
||||
uint8 _y;
|
||||
/** Width of the object rectangle (XL register). */
|
||||
uint16 _width;
|
||||
/** Height of the object rectangle (YL register). */
|
||||
uint8 _height;
|
||||
/** A general-purpose register for use in scripts. Nothing to do with animation. */
|
||||
uint16 _WX;
|
||||
/**
|
||||
* High 8 bits of the 16-bit starting room frame (WY register).
|
||||
* This is in the room frame space.
|
||||
*
|
||||
* @see _roomFrameLSB
|
||||
*/
|
||||
uint8 _roomFrameMSB;
|
||||
/** Unknown. TODO: Figure out what this does. */
|
||||
uint8 _SP;
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* An interactable area, usually without a visual representation.
|
||||
*/
|
||||
struct Static : public Common::Serializable {
|
||||
/** Whether you can mouse over and interact with the static (AC register). */
|
||||
uint8 _active;
|
||||
/**
|
||||
* Static name (NM register).
|
||||
*
|
||||
* If it starts with '~', the static has an implicit "pickup" action that adds
|
||||
* an item with the same name (except '`' replaces '~') to your inventory and
|
||||
* disables the static. If there is a matching scripted "pickup" action, it
|
||||
* overrides the implicit action. This kind of static also has graphics in the
|
||||
* form of its rectangle extracted from room frame 2 (and 3 after pickup).
|
||||
*
|
||||
* If it ends with '[', the "use" action allows combining the static with another
|
||||
* entity.
|
||||
*
|
||||
* TODO: Support '~' statics.
|
||||
*/
|
||||
char _name[MAX_ENTITY_NAME_LENGTH + 1];
|
||||
/** X coordinate of the static rectangle (XX register). */
|
||||
uint16 _x;
|
||||
/** Y coordinate of the static rectangle (YY register). */
|
||||
uint8 _y;
|
||||
/** Width of the static rectangle (XL register). */
|
||||
uint16 _width;
|
||||
/** Height of the static rectangle (YL register). */
|
||||
uint8 _height;
|
||||
/** X coordinate of the position the player will walk towards after clicking the static (WX register). */
|
||||
uint16 _walkToX;
|
||||
/** Y coordinate of the position the player will walk towards after clicking the static (WY register). */
|
||||
uint8 _walkToY;
|
||||
/** Player frame (rotation) set after the player finishes walking towards the walk to position (SP register). */
|
||||
uint8 _walkToFrame;
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
/**
|
||||
* Check whether this static is combinable.
|
||||
* Statics with names ending with '[' are allowed to be combined with other items.
|
||||
*
|
||||
* @return True if combinable, false otherwise.
|
||||
*/
|
||||
bool isCombinable() const;
|
||||
|
||||
/**
|
||||
* Check whether this static is implicitly picked up.
|
||||
* Statics with names starting with '~' are implicitly picked up.
|
||||
*
|
||||
* @return Returns true if this static is implicitly picked up by pick up action, false otherwise.
|
||||
*/
|
||||
bool allowsImplicitPickup() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A static image that is carved out of a room frame based on its rectangle.
|
||||
* The bitmap rectangle also specifies where to blit it on the screen.
|
||||
*/
|
||||
struct Bitmap : public Common::Serializable {
|
||||
/** Room frame that this bitmap carves out of. */
|
||||
uint8 _roomFrame;
|
||||
/** Whether to draw the bitmap. */
|
||||
uint8 _isVisible;
|
||||
/** X coordinate of the top left corner of the bitmap rectangle. */
|
||||
uint16 _x1;
|
||||
/** Y coordinate of the top left corner of the bitmap rectangle. */
|
||||
uint8 _y1;
|
||||
/** X coordinate of the bottom right corner of the bitmap rectangle. */
|
||||
uint16 _x2;
|
||||
/** Y coordinate of the bottom right corner of the bitmap rectangle. */
|
||||
uint8 _y2;
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoded exhausted convesation item.
|
||||
*/
|
||||
struct ExhaustedConvItem {
|
||||
/**
|
||||
* 1 bit - context.
|
||||
* 3 bits - conversation item index.
|
||||
* 4 bits - conversation group index.
|
||||
*/
|
||||
uint8 _encodedData;
|
||||
|
||||
uint8 getContext() const {
|
||||
return (_encodedData >> 7) & 0x1;
|
||||
}
|
||||
uint8 getConvItemIndex() const {
|
||||
return (_encodedData >> 4) & 0x7;
|
||||
}
|
||||
uint8 getConvGroupIndex() const {
|
||||
return _encodedData & 0xF;
|
||||
}
|
||||
|
||||
ExhaustedConvItem() : _encodedData(0) {}
|
||||
ExhaustedConvItem(uint8 context, uint8 convItemIndex, uint8 convGroupIndex) :
|
||||
_encodedData(((context & 0x1) << 7) | ((convItemIndex & 0x7) << 4) | (convGroupIndex & 0xF)) {}
|
||||
};
|
||||
|
||||
struct Scene : Common::Serializable {
|
||||
Door *getDoor(uint8 objectId);
|
||||
Object *getObject(uint8 objectId, bool ignoreNo = false);
|
||||
Static *getStatic(uint8 staticId, bool ignoreNo = false);
|
||||
Bitmap *getBitmap(uint8 bitmapId);
|
||||
|
||||
uint8 getNoDoors(bool ignoreNo = false) const;
|
||||
uint8 getNoObjects(bool ignoreNo = false) const;
|
||||
uint8 getNoStatics(bool ignoreNo = false) const;
|
||||
uint8 getNoBitmaps() const;
|
||||
|
||||
/**
|
||||
* Finds the door at the given position. By default, only active doors are considered.
|
||||
*
|
||||
* @param x X coordinate.
|
||||
* @param y Y coordinate.
|
||||
* @param activeOnly If true, consider only active doors; otherwise consider any.
|
||||
* @param index Output parameter for the found door's ID.
|
||||
* @return A door if found, nullptr otherwise.
|
||||
*/
|
||||
Door *findDoor(int16 x, int16 y, bool activeOnly = true, int *index = nullptr);
|
||||
/**
|
||||
* Finds the static at the given position. By default, only active statics are considered.
|
||||
*
|
||||
* @param x X coordinate.
|
||||
* @param y Y coordinate.
|
||||
* @param activeOnly If true, consider only active statics; otherwise consider any.
|
||||
* @param index Output parameter for the found static's ID.
|
||||
* @return A static if found, nullptr otherwise.
|
||||
*/
|
||||
Static *findStatic(int16 x, int16 y, bool activeOnly = true, int *index = nullptr);
|
||||
Bitmap *findBitmap(int16 x, int16 y, int *index = nullptr);
|
||||
|
||||
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;
|
||||
/**
|
||||
* These three variables control downscaling of the player character depending on his Y.
|
||||
* TODO: Find out more.
|
||||
*/
|
||||
uint8 _unknown001;
|
||||
uint8 _unknown002;
|
||||
uint8 _unknown003;
|
||||
uint8 _delay; /**< Delay between object animation advancements (DL register). */
|
||||
|
||||
uint8 _noDoors; /**< Number of doors in the scene (ND register). */
|
||||
Door _doors[5]; /**< Door definitions. */
|
||||
|
||||
uint8 _noObjects; /**< Number of animated objects in the scene (NO register). */
|
||||
Object _objects[9]; /**< Object definitions. */
|
||||
|
||||
uint8 _noStatics; /**< Number of statics in the scene (NS register). */
|
||||
Static _statics[15]; /**< Static definitions. */
|
||||
|
||||
Bitmap _bitmaps[10]; /**< Bitmap definitions. There is no corresponding _noBitmaps field. */
|
||||
|
||||
uint16 _obstacleY1; /**< Fixed Y coordinate for all static obstacles in the scene. Always 0 in data files. */
|
||||
|
||||
/** First index (inclusive and 0-indexed) of the rotating portion of the palette (PF register). */
|
||||
uint8 _palRotFirst;
|
||||
/** Last index (inclusive and 0-indexed) of the rotating portion of the palette (PL register). */
|
||||
uint8 _palRotLast;
|
||||
/** Delay between each right rotation of the palette portion (PD register). */
|
||||
uint8 _palRotDelay;
|
||||
|
||||
/**
|
||||
* Points to the first free item in exhausted conversation item array.
|
||||
* @note Indexed from 1.
|
||||
*/
|
||||
uint8 _exhaustedConvItemNext;
|
||||
ExhaustedConvItem _exhaustedConvItems[79];
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
struct ConversationInfo {
|
||||
struct Item {
|
||||
uint8 _question;
|
||||
uint8 _response;
|
||||
uint8 _nextGroupIndex;
|
||||
};
|
||||
|
||||
typedef Common::Array<Item> ItemGroup;
|
||||
|
||||
Common::Array<ItemGroup> _itemGroups;
|
||||
uint8 _context;
|
||||
uint8 _objectId;
|
||||
uint8 _color;
|
||||
};
|
||||
|
||||
struct GameData : public Common::Serializable {
|
||||
public:
|
||||
GameData();
|
||||
Scene *getScene(uint8 sceneId);
|
||||
Scene *getCurrentScene();
|
||||
Inventory &getInventory();
|
||||
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
uint8 _currentScene; // Persistent.
|
||||
uint8 _lastScene;
|
||||
bool _partB; // Persistent.
|
||||
Inventory _inventory; // Persistent.
|
||||
Common::String _currentAPK; // Persistent.
|
||||
ConversationInfo _conversationInfo;
|
||||
/** Current SayCommand color. */
|
||||
uint8 _color;
|
||||
private:
|
||||
Scene _scenes[45]; // Persistent.
|
||||
};
|
||||
|
||||
enum Colors {
|
||||
WHITE = 0xC6,
|
||||
DARKGRAY = 0xC2,
|
||||
LIGHTGRAY = 0xC4,
|
||||
GREEN = 0xC8,
|
||||
ORANGE = 0xCA,
|
||||
DARKBLUE = 0xD6,
|
||||
LIGHTBLUE = 0xDA,
|
||||
BROWN = 0xDC
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
422
engines/mutationofjb/gamescreen.cpp
Normal file
422
engines/mutationofjb/gamescreen.cpp
Normal file
@@ -0,0 +1,422 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/gamescreen.h"
|
||||
|
||||
#include "mutationofjb/animationdecoder.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
#include "mutationofjb/inventory.h"
|
||||
#include "mutationofjb/room.h"
|
||||
#include "mutationofjb/util.h"
|
||||
#include "mutationofjb/widgets/conversationwidget.h"
|
||||
#include "mutationofjb/widgets/gamewidget.h"
|
||||
#include "mutationofjb/widgets/imagewidget.h"
|
||||
#include "mutationofjb/widgets/inventorywidget.h"
|
||||
#include "mutationofjb/widgets/labelwidget.h"
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "graphics/screen.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
enum ButtonType {
|
||||
BUTTON_WALK = 0,
|
||||
BUTTON_TALK,
|
||||
BUTTON_LOOK,
|
||||
BUTTON_USE,
|
||||
BUTTON_PICKUP,
|
||||
BUTTON_SCROLL_LEFT,
|
||||
BUTTON_SCROLL_RIGHT,
|
||||
BUTTON_SETTINGS,
|
||||
NUM_BUTTONS
|
||||
};
|
||||
|
||||
enum {
|
||||
INVENTORY_START_X = 88,
|
||||
INVENTORY_START_Y = 149,
|
||||
INVENTORY_ITEM_WIDTH = 34,
|
||||
INVENTORY_ITEM_HEIGHT = 33,
|
||||
INVENTORY_ITEMS_PER_LINE = 8,
|
||||
INVENTORY_ITEMS_LINES = 5,
|
||||
CONVERSATION_X = 0,
|
||||
CONVERSATION_Y = 139,
|
||||
CONVERSATION_WIDTH = 320,
|
||||
CONVERSATION_HEIGHT = 61,
|
||||
STATUS_BAR_X = 0,
|
||||
STATUS_BAR_Y = 140,
|
||||
STATUS_BAR_WIDTH = 320,
|
||||
STATUS_BAR_HEIGHT = 8
|
||||
};
|
||||
|
||||
|
||||
GameScreen::GameScreen(Game &game, Graphics::Screen *screen)
|
||||
: GuiScreen(game, screen),
|
||||
_inventoryWidget(nullptr),
|
||||
_conversationWidget(nullptr),
|
||||
_statusBarWidget(nullptr),
|
||||
_currentAction(ActionInfo::Walk) {}
|
||||
|
||||
GameScreen::~GameScreen() {}
|
||||
|
||||
bool GameScreen::init() {
|
||||
if (!loadInventoryGfx()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!loadHudGfx()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_game.getGameData().getInventory().setObserver(this);
|
||||
|
||||
// Init widgets.
|
||||
|
||||
const Common::Rect backgroundRect(CONVERSATION_X, CONVERSATION_Y, CONVERSATION_X + CONVERSATION_WIDTH, CONVERSATION_Y + CONVERSATION_HEIGHT);
|
||||
const Graphics::Surface backgroundSurface = _hudSurfaces[0].getSubArea(backgroundRect);
|
||||
ImageWidget *image = new ImageWidget(*this, backgroundRect, backgroundSurface);
|
||||
addWidget(image);
|
||||
|
||||
_inventoryWidget = new InventoryWidget(*this, _inventorySurfaces);
|
||||
_inventoryWidget->setCallback(this);
|
||||
addWidget(_inventoryWidget);
|
||||
|
||||
const Common::Rect ButtonRects[] = {
|
||||
Common::Rect(0, 148, 67, 158), // Walk
|
||||
Common::Rect(0, 158, 67, 168), // Talk
|
||||
Common::Rect(0, 168, 67, 178), // Look
|
||||
Common::Rect(0, 178, 67, 188), // Use
|
||||
Common::Rect(0, 188, 67, 198), // PickUp
|
||||
Common::Rect(67, 149, 88, 174), // ScrollLeft
|
||||
Common::Rect(67, 174, 88, 199), // ScrollRight
|
||||
Common::Rect(301, 148, 320, 200) // Settings
|
||||
};
|
||||
|
||||
for (int i = 0; i < NUM_BUTTONS; ++i) {
|
||||
const Graphics::Surface normalSurface = _hudSurfaces[0].getSubArea(ButtonRects[i]);
|
||||
const Graphics::Surface pressedSurface = _hudSurfaces[1].getSubArea(ButtonRects[i]);
|
||||
ButtonWidget *button = new ButtonWidget(*this, ButtonRects[i], normalSurface, pressedSurface);
|
||||
button->setId(i);
|
||||
button->setCallback(this);
|
||||
_buttons.push_back(button);
|
||||
addWidget(button);
|
||||
}
|
||||
|
||||
const Common::Rect statusBarRect(STATUS_BAR_X, STATUS_BAR_Y, STATUS_BAR_X + STATUS_BAR_WIDTH, STATUS_BAR_Y + STATUS_BAR_HEIGHT);
|
||||
_statusBarWidget = new LabelWidget(*this, statusBarRect);
|
||||
addWidget(_statusBarWidget);
|
||||
|
||||
const Common::Rect conversationRect(CONVERSATION_X, CONVERSATION_Y, CONVERSATION_X + CONVERSATION_WIDTH, CONVERSATION_Y + CONVERSATION_HEIGHT);
|
||||
const Graphics::Surface conversationSurface = _hudSurfaces[2].getSubArea(conversationRect);
|
||||
_conversationWidget = new ConversationWidget(*this, conversationRect, conversationSurface);
|
||||
_conversationWidget->setVisible(false);
|
||||
addWidget(_conversationWidget);
|
||||
|
||||
_gameWidget = new GameWidget(*this);
|
||||
_gameWidget->setCallback(this);
|
||||
addWidget(_gameWidget);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameScreen::handleEvent(const Common::Event &event) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYUP: {
|
||||
switch (event.kbd.ascii) {
|
||||
case 'g':
|
||||
_currentAction = ActionInfo::Walk;
|
||||
_currentPickedItem.clear();
|
||||
break;
|
||||
case 'r':
|
||||
_currentAction = ActionInfo::Talk;
|
||||
_currentPickedItem.clear();
|
||||
break;
|
||||
case 's':
|
||||
_currentAction = ActionInfo::Look;
|
||||
_currentPickedItem.clear();
|
||||
break;
|
||||
case 'b':
|
||||
_currentAction = ActionInfo::Use;
|
||||
_currentPickedItem.clear();
|
||||
break;
|
||||
case 'n':
|
||||
_currentAction = ActionInfo::PickUp;
|
||||
_currentPickedItem.clear();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GuiScreen::handleEvent(event);
|
||||
}
|
||||
|
||||
ConversationWidget &GameScreen::getConversationWidget() {
|
||||
return *_conversationWidget;
|
||||
}
|
||||
|
||||
void GameScreen::showConversationWidget(bool show) {
|
||||
_gameWidget->setEnabled(!show);
|
||||
_conversationWidget->setVisible(show);
|
||||
_statusBarWidget->setText(Common::String());
|
||||
|
||||
for (Common::Array<ButtonWidget *>::const_iterator it = _buttons.begin(); it != _buttons.end(); ++it) {
|
||||
(*it)->setVisible(!show);
|
||||
}
|
||||
_inventoryWidget->setVisible(!show);
|
||||
}
|
||||
|
||||
void GameScreen::refreshAfterSceneChanged() {
|
||||
const Widgets &widgets = getWidgets();
|
||||
|
||||
if (!getGame().isCurrentSceneMap()) {
|
||||
_gameWidget->setArea(Common::Rect(GameWidget::GAME_NORMAL_AREA_WIDTH, GameWidget::GAME_NORMAL_AREA_HEIGHT));
|
||||
|
||||
for (Widgets::const_iterator it = widgets.begin(); it != widgets.end(); ++it) {
|
||||
if (*it == _gameWidget || *it == _conversationWidget)
|
||||
continue;
|
||||
|
||||
(*it)->setVisible(true);
|
||||
}
|
||||
} else {
|
||||
_gameWidget->setArea(Common::Rect(GameWidget::GAME_FULL_AREA_WIDTH, GameWidget::GAME_FULL_AREA_HEIGHT));
|
||||
for (Widgets::const_iterator it = widgets.begin(); it != widgets.end(); ++it) {
|
||||
if (*it == _gameWidget || *it == _conversationWidget)
|
||||
continue;
|
||||
|
||||
(*it)->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
_gameWidget->clearState();
|
||||
|
||||
// Fake mouse move event to update the cursor.
|
||||
Common::Event event;
|
||||
event.type = Common::EVENT_MOUSEMOVE;
|
||||
event.mouse = _game.getEngine().getEventManager()->getMousePos();
|
||||
_gameWidget->handleEvent(event);
|
||||
|
||||
_gameWidget->markDirty(GameWidget::DIRTY_AFTER_SCENE_CHANGE);
|
||||
_gameWidget->update(*_screen); // Force immediate update.
|
||||
}
|
||||
|
||||
class InventoryAnimationDecoderCallback : public AnimationDecoderCallback {
|
||||
public:
|
||||
InventoryAnimationDecoderCallback(GameScreen &gui) : _gui(gui) {}
|
||||
void onFrame(int frameNo, Graphics::Surface &surface) override;
|
||||
void onPaletteUpdated(byte palette[PALETTE_SIZE]) override;
|
||||
private:
|
||||
GameScreen &_gui;
|
||||
};
|
||||
|
||||
void InventoryAnimationDecoderCallback::onPaletteUpdated(byte palette[PALETTE_SIZE]) {
|
||||
_gui._screen->setPalette(palette + 0xC0 * 3, 0xC0, 0x20); // Load only 0x20 colors.
|
||||
}
|
||||
|
||||
void InventoryAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surface) {
|
||||
if (frameNo < 3) {
|
||||
Graphics::Surface outSurface;
|
||||
outSurface.copyFrom(surface);
|
||||
_gui._inventorySurfaces.push_back(outSurface);
|
||||
}
|
||||
}
|
||||
|
||||
bool GameScreen::loadInventoryGfx() {
|
||||
AnimationDecoder decoder("icons.dat");
|
||||
InventoryAnimationDecoderCallback callback(*this);
|
||||
return decoder.decode(&callback);
|
||||
}
|
||||
|
||||
class HudAnimationDecoderCallback : public AnimationDecoderCallback {
|
||||
public:
|
||||
HudAnimationDecoderCallback(GameScreen &gui) : _gui(gui) {}
|
||||
void onFrame(int frameNo, Graphics::Surface &surface) override;
|
||||
void onPaletteUpdated(byte palette[PALETTE_SIZE]) override;
|
||||
private:
|
||||
GameScreen &_gui;
|
||||
};
|
||||
|
||||
void HudAnimationDecoderCallback::onPaletteUpdated(byte [PALETTE_SIZE]) {
|
||||
}
|
||||
|
||||
void HudAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surface) {
|
||||
if (frameNo == 0 || frameNo == 1 || frameNo == 4) {
|
||||
Graphics::Surface outSurface;
|
||||
outSurface.copyFrom(surface);
|
||||
_gui._hudSurfaces.push_back(outSurface);
|
||||
}
|
||||
}
|
||||
|
||||
bool GameScreen::loadHudGfx() {
|
||||
AnimationDecoder decoder("room0.dat");
|
||||
HudAnimationDecoderCallback callback(*this);
|
||||
return decoder.decode(&callback);
|
||||
}
|
||||
|
||||
void GameScreen::updateStatusBarText(const Common::String &entity, bool inventory) {
|
||||
const bool hasPrevPickedItem = !_currentPickedItem.empty();
|
||||
const bool hasCurrentItem = !entity.empty();
|
||||
|
||||
if (!hasPrevPickedItem && !hasCurrentItem) {
|
||||
_statusBarWidget->setText(Common::String());
|
||||
return;
|
||||
}
|
||||
|
||||
HardcodedStrings::StringType actionStringType = HardcodedStrings::LOOK;
|
||||
|
||||
if (inventory) {
|
||||
switch (_currentAction) {
|
||||
case ActionInfo::Use:
|
||||
actionStringType = HardcodedStrings::USE;
|
||||
break;
|
||||
case ActionInfo::Look:
|
||||
default:
|
||||
actionStringType = HardcodedStrings::LOOK;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (_currentAction) {
|
||||
case ActionInfo::Look:
|
||||
default:
|
||||
actionStringType = HardcodedStrings::LOOK;
|
||||
break;
|
||||
case ActionInfo::Walk:
|
||||
actionStringType = HardcodedStrings::WALK;
|
||||
break;
|
||||
case ActionInfo::Talk:
|
||||
actionStringType = HardcodedStrings::TALK;
|
||||
break;
|
||||
case ActionInfo::Use:
|
||||
actionStringType = HardcodedStrings::USE;
|
||||
break;
|
||||
case ActionInfo::PickUp:
|
||||
actionStringType = HardcodedStrings::PICKUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String text = _game.getAssets().getHardcodedStrings().getString(actionStringType);
|
||||
|
||||
if (hasPrevPickedItem)
|
||||
text += " " + _currentPickedItem;
|
||||
if (hasCurrentItem)
|
||||
text += " " + entity;
|
||||
|
||||
_statusBarWidget->setText(text);
|
||||
}
|
||||
|
||||
void GameScreen::onInventoryChanged() {
|
||||
_inventoryWidget->markDirty();
|
||||
}
|
||||
|
||||
void GameScreen::onButtonClicked(ButtonWidget *button) {
|
||||
const int buttonId = button->getId();
|
||||
if (buttonId <= BUTTON_PICKUP) {
|
||||
const ActionInfo::Action actions[] = {ActionInfo::Walk, ActionInfo::Talk, ActionInfo::Look, ActionInfo::Use, ActionInfo::PickUp};
|
||||
_currentAction = actions[buttonId];
|
||||
_currentPickedItem.clear();
|
||||
} else if (buttonId == BUTTON_SCROLL_LEFT) {
|
||||
_game.getGameData().getInventory().scrollLeft();
|
||||
} else if (buttonId == BUTTON_SCROLL_RIGHT) {
|
||||
_game.getGameData().getInventory().scrollRight();
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::onInventoryItemHovered(InventoryWidget *, int posInWidget) {
|
||||
if (posInWidget == -1) {
|
||||
updateStatusBarText(Common::String(), true);
|
||||
} else {
|
||||
const Common::String &item = _game.getGameData().getInventory().getItems()[posInWidget];
|
||||
updateStatusBarText(item, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::onInventoryItemClicked(InventoryWidget *, int posInWidget) {
|
||||
// Position in widget should match the position in inventory.
|
||||
const Common::String &item = _game.getGameData().getInventory().getItems()[posInWidget];
|
||||
|
||||
if (_currentAction == ActionInfo::Use) {
|
||||
if (_currentPickedItem.empty()) {
|
||||
// Inventory items ending with '[' aren't supposed to be combined (e.g. Fisher's mask).
|
||||
if (item.lastChar() == '[')
|
||||
_game.startActionSection(ActionInfo::Use, item);
|
||||
else
|
||||
_currentPickedItem = item;
|
||||
} else {
|
||||
_game.startActionSection(ActionInfo::Use, _currentPickedItem, item);
|
||||
_currentPickedItem.clear();
|
||||
}
|
||||
} else {
|
||||
_game.startActionSection(ActionInfo::Look, item);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::onGameDoorClicked(GameWidget *, Door *door) {
|
||||
if (!_currentPickedItem.empty()) {
|
||||
_game.startActionSection(_currentAction, _currentPickedItem, door->_name);
|
||||
_currentPickedItem.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_game.startActionSection(_currentAction, door->_name) && _currentAction == ActionInfo::Walk && door->_destSceneId != 0) {
|
||||
if (door->allowsImplicitSceneChange())
|
||||
_game.changeScene(door->_destSceneId, _game.getGameData()._partB);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::onGameStaticClicked(GameWidget *, Static *stat) {
|
||||
if (_currentAction == ActionInfo::Use) {
|
||||
if (_currentPickedItem.empty()) {
|
||||
if (stat->isCombinable())
|
||||
_currentPickedItem = stat->_name;
|
||||
else
|
||||
_game.startActionSection(ActionInfo::Use, stat->_name);
|
||||
} else {
|
||||
_game.startActionSection(_currentAction, _currentPickedItem, stat->_name);
|
||||
_currentPickedItem.clear();
|
||||
}
|
||||
} else {
|
||||
if (!_game.startActionSection(_currentAction, stat->_name)) {
|
||||
if (_currentAction == ActionInfo::PickUp && stat->allowsImplicitPickup()) {
|
||||
Common::String inventoryName(stat->_name);
|
||||
inventoryName.setChar('`', 0);
|
||||
|
||||
_game.getGameData().getInventory().addItem(inventoryName);
|
||||
stat->_active = 0;
|
||||
_game.getRoom().drawStatic(stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::onGameEntityHovered(GameWidget *, const Common::String &entity) {
|
||||
updateStatusBarText(entity, false);
|
||||
}
|
||||
|
||||
}
|
||||
103
engines/mutationofjb/gamescreen.h
Normal file
103
engines/mutationofjb/gamescreen.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_GUI_H
|
||||
#define MUTATIONOFJB_GUI_H
|
||||
|
||||
#include "mutationofjb/inventory.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/guiscreen.h"
|
||||
#include "mutationofjb/widgets/buttonwidget.h"
|
||||
#include "mutationofjb/widgets/inventorywidget.h"
|
||||
#include "mutationofjb/widgets/gamewidget.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
class Screen;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Game;
|
||||
class Widget;
|
||||
class InventoryWidget;
|
||||
class ConversationWidget;
|
||||
class LabelWidget;
|
||||
class GameWidget;
|
||||
|
||||
class GameScreen : public GuiScreen, public InventoryObserver, public ButtonWidgetCallback, public InventoryWidgetCallback, public GameWidgetCallback {
|
||||
public:
|
||||
friend class InventoryAnimationDecoderCallback;
|
||||
friend class HudAnimationDecoderCallback;
|
||||
|
||||
GameScreen(Game &game, Graphics::Screen *screen);
|
||||
~GameScreen() override;
|
||||
|
||||
bool init();
|
||||
|
||||
void handleEvent(const Common::Event &event) override;
|
||||
|
||||
void onInventoryChanged() override;
|
||||
void onButtonClicked(ButtonWidget *) override;
|
||||
void onInventoryItemHovered(InventoryWidget *widget, int posInWidget) override;
|
||||
void onInventoryItemClicked(InventoryWidget *widget, int posInWidget) override;
|
||||
void onGameDoorClicked(GameWidget *, Door *door) override;
|
||||
void onGameStaticClicked(GameWidget *, Static *stat) override;
|
||||
void onGameEntityHovered(GameWidget *, const Common::String &entity) override;
|
||||
|
||||
ConversationWidget &getConversationWidget();
|
||||
|
||||
void showConversationWidget(bool show);
|
||||
void refreshAfterSceneChanged();
|
||||
|
||||
private:
|
||||
bool loadInventoryGfx();
|
||||
bool loadHudGfx();
|
||||
void drawInventoryItem(const Common::String &item, int pos);
|
||||
void drawInventory();
|
||||
|
||||
void updateStatusBarText(const Common::String &entity, bool inventory);
|
||||
|
||||
Common::Array<Graphics::Surface> _inventorySurfaces;
|
||||
Common::Array<Graphics::Surface> _hudSurfaces;
|
||||
|
||||
Common::Array<ButtonWidget *> _buttons;
|
||||
InventoryWidget *_inventoryWidget;
|
||||
ConversationWidget *_conversationWidget;
|
||||
LabelWidget *_statusBarWidget;
|
||||
GameWidget *_gameWidget;
|
||||
|
||||
ActionInfo::Action _currentAction;
|
||||
Common::String _currentPickedItem;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
77
engines/mutationofjb/guiscreen.cpp
Normal file
77
engines/mutationofjb/guiscreen.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/guiscreen.h"
|
||||
|
||||
#include "mutationofjb/widgets/widget.h"
|
||||
|
||||
#include "graphics/screen.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
GuiScreen::GuiScreen(Game &game, Graphics::Screen *screen)
|
||||
: _game(game),
|
||||
_screen(screen) {}
|
||||
|
||||
GuiScreen::~GuiScreen() {
|
||||
for (Common::Array<Widget *>::iterator it = _widgets.begin(); it != _widgets.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
Game &GuiScreen::getGame() {
|
||||
return _game;
|
||||
}
|
||||
|
||||
void GuiScreen::markDirty() {
|
||||
for (Common::Array<Widget *>::iterator it = _widgets.begin(); it != _widgets.end(); ++it) {
|
||||
if ((*it)->isVisible()) {
|
||||
(*it)->markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScreen::handleEvent(const Common::Event &event) {
|
||||
for (Common::Array<Widget *>::iterator it = _widgets.begin(); it != _widgets.end(); ++it) {
|
||||
if ((*it)->isVisible()) {
|
||||
(*it)->handleEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScreen::update() {
|
||||
for (Common::Array<Widget *>::iterator it = _widgets.begin(); it != _widgets.end(); ++it) {
|
||||
if ((*it)->isVisible()) {
|
||||
(*it)->update(*_screen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScreen::addWidget(Widget *widget) {
|
||||
_widgets.push_back(widget);
|
||||
widget->markDirty();
|
||||
}
|
||||
|
||||
const GuiScreen::Widgets &GuiScreen::getWidgets() const {
|
||||
return _widgets;
|
||||
}
|
||||
|
||||
}
|
||||
91
engines/mutationofjb/guiscreen.h
Normal file
91
engines/mutationofjb/guiscreen.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_GUISCREEN_H
|
||||
#define MUTATIONOFJB_GUISCREEN_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
class Screen;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Game;
|
||||
class Widget;
|
||||
|
||||
/**
|
||||
* Base class for GUI screens.
|
||||
*
|
||||
* GUI screen is a collection of widgets.
|
||||
*/
|
||||
class GuiScreen {
|
||||
public:
|
||||
|
||||
GuiScreen(Game &game, Graphics::Screen *screen);
|
||||
virtual ~GuiScreen();
|
||||
Game &getGame();
|
||||
|
||||
/**
|
||||
* Marks all visible widgets as dirty (needs redraw).
|
||||
*/
|
||||
void markDirty();
|
||||
|
||||
/**
|
||||
* Lets all visible widgets handle core events.
|
||||
*
|
||||
* @param event ScummVM event.
|
||||
*/
|
||||
virtual void handleEvent(const Common::Event &event);
|
||||
|
||||
/**
|
||||
* Updates all visible widgets.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* Adds a widget to the GUI screen.
|
||||
* The GUI screen will own the widget.
|
||||
*
|
||||
* @param widget Widget to add.
|
||||
*/
|
||||
void addWidget(Widget *widget);
|
||||
|
||||
protected:
|
||||
typedef Common::Array<Widget *> Widgets;
|
||||
|
||||
Game &_game;
|
||||
Graphics::Screen *_screen;
|
||||
|
||||
const Widgets &getWidgets() const;
|
||||
|
||||
private:
|
||||
Widgets _widgets;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
168
engines/mutationofjb/hardcodedstrings.cpp
Normal file
168
engines/mutationofjb/hardcodedstrings.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/hardcodedstrings.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/util.h"
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
HardcodedStrings::HardcodedStrings(Game &game) : _strings(STRING_TYPES_TOTAL) {
|
||||
loadStrings(game.getLanguage());
|
||||
}
|
||||
|
||||
const Common::String &HardcodedStrings::getString(HardcodedStrings::StringType strType) const {
|
||||
const StringArray::size_type index = static_cast<StringArray::size_type>(strType);
|
||||
assert(index < _strings.size());
|
||||
|
||||
return _strings[index];
|
||||
}
|
||||
|
||||
void HardcodedStrings::loadStrings(Common::Language lang) {
|
||||
Common::File file;
|
||||
const char *const fileName = "jb.ex_";
|
||||
if (!file.open(fileName)) {
|
||||
reportFileMissingError(fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lang == Common::SK_SVK)
|
||||
file.seek(0xBAA8);
|
||||
else if (lang == Common::DE_DEU)
|
||||
file.seek(0xBC48);
|
||||
else
|
||||
return;
|
||||
|
||||
Common::String str;
|
||||
|
||||
file.readPascalString(); // WALK TO
|
||||
file.readPascalString(); // TALK TO
|
||||
file.readPascalString(); // PICK UP
|
||||
file.readPascalString(); // LOOK AT
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::SK_SVK)
|
||||
_strings[WALK] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::DE_DEU)
|
||||
_strings[WALK] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::SK_SVK)
|
||||
_strings[LOOK] = str;
|
||||
|
||||
file.readPascalString();
|
||||
file.readPascalString();
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::DE_DEU)
|
||||
_strings[LOOK] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::SK_SVK)
|
||||
_strings[PICKUP] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::DE_DEU)
|
||||
_strings[PICKUP] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::SK_SVK)
|
||||
_strings[TALK] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::DE_DEU)
|
||||
_strings[TALK] = str;
|
||||
|
||||
file.readPascalString(); // USE
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::SK_SVK)
|
||||
_strings[USE] = str;
|
||||
|
||||
str = file.readPascalString();
|
||||
if (lang == Common::DE_DEU)
|
||||
_strings[USE] = str;
|
||||
|
||||
|
||||
if (lang == Common::SK_SVK)
|
||||
file.seek(0x1982F);
|
||||
else if (lang == Common::DE_DEU)
|
||||
file.seek(0x199F0);
|
||||
else
|
||||
return;
|
||||
|
||||
_strings[JOHNNY_CANNOT_USE_1] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_USE_1] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_USE_2] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_USE_2] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_USE_3] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_USE_3] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_USE_4] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_USE_4] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_TALK_1] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_TALK_1] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_TALK_2] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_TALK_2] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_TALK_3] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_TALK_3] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_TALK_4] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_TALK_4] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_LOOK_1] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_LOOK_1] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_LOOK_2] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_LOOK_2] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
if (lang != Common::SK_SVK) // This sentence seems to be missing from the Slovak executable.
|
||||
_strings[JOHNNY_CANNOT_LOOK_3] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_LOOK_3] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_LOOK_4] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_LOOK_4] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_PICKUP_1] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_PICKUP_1] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
if (lang != Common::SK_SVK) // This sentence seems to be missing from the Slovak executable.
|
||||
_strings[JOHNNY_CANNOT_PICKUP_2] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_PICKUP_2] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_PICKUP_3] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_PICKUP_3] = file.readPascalString();
|
||||
file.readPascalString();
|
||||
_strings[JOHNNY_CANNOT_PICKUP_4] = file.readPascalString();
|
||||
_strings[SKEPTO_CANNOT_PICKUP_4] = file.readPascalString();
|
||||
}
|
||||
|
||||
}
|
||||
106
engines/mutationofjb/hardcodedstrings.h
Normal file
106
engines/mutationofjb/hardcodedstrings.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_HARDCODEDSTRINGS_H
|
||||
#define MUTATIONOFJB_HARDCODEDSTRINGS_H
|
||||
|
||||
#include "common/language.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Game;
|
||||
|
||||
/**
|
||||
* Provides access to hardcoded strings.
|
||||
*
|
||||
* Currently, we do not have any agreement with the original author of the game,
|
||||
* so the strings are loaded from the gmae executable file.
|
||||
*/
|
||||
class HardcodedStrings {
|
||||
public:
|
||||
enum StringType {
|
||||
WALK,
|
||||
TALK,
|
||||
LOOK,
|
||||
USE,
|
||||
PICKUP,
|
||||
|
||||
JOHNNY_CANNOT_USE_1,
|
||||
SKEPTO_CANNOT_USE_1,
|
||||
JOHNNY_CANNOT_USE_2,
|
||||
SKEPTO_CANNOT_USE_2,
|
||||
JOHNNY_CANNOT_USE_3,
|
||||
SKEPTO_CANNOT_USE_3,
|
||||
JOHNNY_CANNOT_USE_4,
|
||||
SKEPTO_CANNOT_USE_4,
|
||||
|
||||
JOHNNY_CANNOT_TALK_1,
|
||||
SKEPTO_CANNOT_TALK_1,
|
||||
JOHNNY_CANNOT_TALK_2,
|
||||
SKEPTO_CANNOT_TALK_2,
|
||||
JOHNNY_CANNOT_TALK_3,
|
||||
SKEPTO_CANNOT_TALK_3,
|
||||
JOHNNY_CANNOT_TALK_4,
|
||||
SKEPTO_CANNOT_TALK_4,
|
||||
|
||||
JOHNNY_CANNOT_LOOK_1,
|
||||
SKEPTO_CANNOT_LOOK_1,
|
||||
JOHNNY_CANNOT_LOOK_2,
|
||||
SKEPTO_CANNOT_LOOK_2,
|
||||
JOHNNY_CANNOT_LOOK_3,
|
||||
SKEPTO_CANNOT_LOOK_3,
|
||||
JOHNNY_CANNOT_LOOK_4,
|
||||
SKEPTO_CANNOT_LOOK_4,
|
||||
|
||||
JOHNNY_CANNOT_PICKUP_1,
|
||||
SKEPTO_CANNOT_PICKUP_1,
|
||||
JOHNNY_CANNOT_PICKUP_2,
|
||||
SKEPTO_CANNOT_PICKUP_2,
|
||||
JOHNNY_CANNOT_PICKUP_3,
|
||||
SKEPTO_CANNOT_PICKUP_3,
|
||||
JOHNNY_CANNOT_PICKUP_4,
|
||||
SKEPTO_CANNOT_PICKUP_4,
|
||||
|
||||
STRING_TYPES_TOTAL
|
||||
};
|
||||
|
||||
HardcodedStrings(Game &game);
|
||||
|
||||
/**
|
||||
* Get hardcoded string.
|
||||
*
|
||||
* @param strType String type.
|
||||
* @return Hardcoded string.
|
||||
*/
|
||||
const Common::String &getString(StringType strType) const;
|
||||
|
||||
private:
|
||||
typedef Common::Array<Common::String> StringArray;
|
||||
|
||||
void loadStrings(Common::Language lang);
|
||||
|
||||
StringArray _strings;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
156
engines/mutationofjb/inventory.cpp
Normal file
156
engines/mutationofjb/inventory.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/inventory.h"
|
||||
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamescreen.h"
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
const Inventory::Items &Inventory::getItems() const {
|
||||
return _items;
|
||||
}
|
||||
|
||||
bool Inventory::hasItem(const Common::String &item) const {
|
||||
Items::const_iterator it = Common::find(_items.begin(), _items.end(), item);
|
||||
return (it != _items.end());
|
||||
}
|
||||
|
||||
void Inventory::addItem(const Common::String &item) {
|
||||
_items.push_back(item);
|
||||
|
||||
if (_items.size() > VISIBLE_ITEMS) {
|
||||
rotateItemsRight(VISIBLE_ITEMS);
|
||||
}
|
||||
if (_observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::removeItem(const Common::String &item) {
|
||||
Items::iterator it = Common::find(_items.begin(), _items.end(), item);
|
||||
if (it == _items.end()) {
|
||||
debug("Item '%s' not in inventory.", item.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_items.remove_at(it - _items.begin());
|
||||
if (_observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::removeAllItems() {
|
||||
_items.clear();
|
||||
if (_observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::renameItem(const Common::String &oldName, const Common::String &newName) {
|
||||
bool renamed = false;
|
||||
for (Items::iterator it = _items.begin(); it != _items.end(); ++it) {
|
||||
if (*it == oldName) {
|
||||
*it = newName;
|
||||
renamed = true;
|
||||
}
|
||||
}
|
||||
if (renamed && _observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::scrollLeft() {
|
||||
if (_items.size() > VISIBLE_ITEMS) {
|
||||
rotateItemsRight(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::scrollRight() {
|
||||
if (_items.size() > VISIBLE_ITEMS) {
|
||||
rotateItemsLeft(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::rotateItemsRight(uint n) {
|
||||
if (_items.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
n %= _items.size();
|
||||
reverseItems(0, _items.size() - 1);
|
||||
reverseItems(0, n - 1);
|
||||
reverseItems(n, _items.size() - 1);
|
||||
if (_observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::rotateItemsLeft(uint n) {
|
||||
if (_items.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
n %= _items.size();
|
||||
reverseItems(0, _items.size() - 1);
|
||||
reverseItems(_items.size() - n, _items.size() - 1);
|
||||
reverseItems(0, _items.size() - n - 1);
|
||||
if (_observer) {
|
||||
_observer->onInventoryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::setObserver(InventoryObserver *observer) {
|
||||
_observer = observer;
|
||||
}
|
||||
|
||||
void Inventory::reverseItems(uint from, uint to) {
|
||||
assert(from <= to);
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint size = to - from + 1;
|
||||
for (uint i = 0; i < size / 2; ++i) {
|
||||
SWAP(_items[from + i], _items[to - i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
if (sz.isLoading()) {
|
||||
uint32 length = 0;
|
||||
sz.syncAsUint32LE(length);
|
||||
_items.resize(length);
|
||||
} else {
|
||||
uint32 length = static_cast<uint32>(_items.size());
|
||||
sz.syncAsUint32LE(length);
|
||||
}
|
||||
|
||||
for (Items::size_type i = 0; i < _items.size(); ++i) {
|
||||
sz.syncString(_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
75
engines/mutationofjb/inventory.h
Normal file
75
engines/mutationofjb/inventory.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_INVENTORY_H
|
||||
#define MUTATIONOFJB_INVENTORY_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Game;
|
||||
|
||||
class InventoryObserver {
|
||||
public:
|
||||
virtual void onInventoryChanged() = 0;
|
||||
virtual ~InventoryObserver() {}
|
||||
};
|
||||
|
||||
class Inventory : public Common::Serializable {
|
||||
public:
|
||||
enum {
|
||||
VISIBLE_ITEMS = 6
|
||||
};
|
||||
|
||||
typedef Common::Array<Common::String> Items;
|
||||
|
||||
Inventory() : _observer(nullptr) {}
|
||||
|
||||
const Items &getItems() const;
|
||||
bool hasItem(const Common::String &item) const;
|
||||
void addItem(const Common::String &item);
|
||||
void removeItem(const Common::String &item);
|
||||
void removeAllItems();
|
||||
void renameItem(const Common::String &oldName, const Common::String &newName);
|
||||
|
||||
void scrollLeft();
|
||||
void scrollRight();
|
||||
|
||||
void setObserver(InventoryObserver *observer);
|
||||
|
||||
void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
private:
|
||||
void rotateItemsRight(uint n);
|
||||
void rotateItemsLeft(uint n);
|
||||
void reverseItems(uint from, uint to);
|
||||
|
||||
Items _items;
|
||||
InventoryObserver *_observer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
72
engines/mutationofjb/inventoryitemdefinitionlist.cpp
Normal file
72
engines/mutationofjb/inventoryitemdefinitionlist.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/inventoryitemdefinitionlist.h"
|
||||
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/util.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
InventoryItemDefinitionList::InventoryItemDefinitionList() {
|
||||
parseFile();
|
||||
}
|
||||
|
||||
int InventoryItemDefinitionList::findItemIndex(const Common::String &itemName) {
|
||||
const InventoryItemMap::const_iterator it = _inventoryItemMap.find(itemName);
|
||||
if (it == _inventoryItemMap.end())
|
||||
return -1;
|
||||
return it->_value;
|
||||
}
|
||||
|
||||
bool InventoryItemDefinitionList::parseFile() {
|
||||
EncryptedFile file;
|
||||
const char *fileName = "fixitems.dat";
|
||||
file.open(fileName);
|
||||
if (!file.isOpen()) {
|
||||
reportFileMissingError(fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
int itemIndex = 0;
|
||||
while (!file.eos()) {
|
||||
Common::String line = file.readLine();
|
||||
if (line.empty() || line.hasPrefix("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Common::String::const_iterator firstSpace = Common::find(line.begin(), line.end(), ' ');
|
||||
if (firstSpace == line.end()) {
|
||||
continue;
|
||||
}
|
||||
const int len = firstSpace - line.begin();
|
||||
if (!len) {
|
||||
continue;
|
||||
}
|
||||
Common::String item(line.c_str(), len);
|
||||
_inventoryItemMap[item] = itemIndex;
|
||||
itemIndex++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
49
engines/mutationofjb/inventoryitemdefinitionlist.h
Normal file
49
engines/mutationofjb/inventoryitemdefinitionlist.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_INVENTORYITEMDEFINITIONLIST_H
|
||||
#define MUTATIONOFJB_INVENTORYITEMDEFINITIONLIST_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
typedef Common::HashMap<Common::String, int> InventoryMap;
|
||||
|
||||
class InventoryItemDefinitionList {
|
||||
public:
|
||||
InventoryItemDefinitionList();
|
||||
const InventoryMap &getInventorMap() const;
|
||||
|
||||
int findItemIndex(const Common::String &itemName);
|
||||
|
||||
private:
|
||||
bool parseFile();
|
||||
|
||||
typedef Common::HashMap<Common::String, int> InventoryItemMap;
|
||||
InventoryItemMap _inventoryItemMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
86
engines/mutationofjb/metaengine.cpp
Normal file
86
engines/mutationofjb/metaengine.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
class MutationOfJBMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "mutationofjb";
|
||||
}
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
|
||||
*engine = new MutationOfJB::MutationOfJBEngine(syst, desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override {
|
||||
if (f == kSupportsListSaves || f == kSimpleSavesNames || f == kSupportsLoadingDuringStartup) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int getMaximumSaveSlot() const override {
|
||||
return 999;
|
||||
}
|
||||
|
||||
SaveStateList listSaves(const char *target) const override {
|
||||
Common::SaveFileManager *const saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".###";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
SaveStateList saveList;
|
||||
int slotNo = 0;
|
||||
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
slotNo = atoi(file->c_str() + file->size() - 3);
|
||||
|
||||
Common::InSaveFile *const in = saveFileMan->openForLoading(*file);
|
||||
if (in) {
|
||||
Common::Serializer sz(in, nullptr);
|
||||
|
||||
MutationOfJB::SaveHeader saveHdr;
|
||||
if (saveHdr.sync(sz)) {
|
||||
saveList.push_back(SaveStateDescriptor(this, slotNo, saveHdr._description));
|
||||
}
|
||||
}
|
||||
}
|
||||
return saveList;
|
||||
}
|
||||
};
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(MUTATIONOFJB)
|
||||
REGISTER_PLUGIN_DYNAMIC(MUTATIONOFJB, PLUGIN_TYPE_ENGINE, MutationOfJBMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(MUTATIONOFJB, PLUGIN_TYPE_ENGINE, MutationOfJBMetaEngine);
|
||||
#endif
|
||||
73
engines/mutationofjb/module.mk
Normal file
73
engines/mutationofjb/module.mk
Normal file
@@ -0,0 +1,73 @@
|
||||
MODULE := engines/mutationofjb
|
||||
|
||||
MODULE_OBJS := \
|
||||
commands/additemcommand.o \
|
||||
commands/bitmapvisibilitycommand.o \
|
||||
commands/callmacrocommand.o \
|
||||
commands/camefromcommand.o \
|
||||
commands/changecommand.o \
|
||||
commands/command.o \
|
||||
commands/conditionalcommand.o \
|
||||
commands/definestructcommand.o \
|
||||
commands/endblockcommand.o \
|
||||
commands/gotocommand.o \
|
||||
commands/ifcommand.o \
|
||||
commands/ifitemcommand.o \
|
||||
commands/ifpiggycommand.o \
|
||||
commands/labelcommand.o \
|
||||
commands/loadplayercommand.o \
|
||||
commands/newroomcommand.o \
|
||||
commands/playanimationcommand.o \
|
||||
commands/removeallitemscommand.o \
|
||||
commands/removeitemcommand.o \
|
||||
commands/renamecommand.o \
|
||||
commands/saycommand.o \
|
||||
commands/seqcommand.o \
|
||||
commands/setcolorcommand.o \
|
||||
commands/setobjectframecommand.o \
|
||||
commands/specialshowcommand.o \
|
||||
commands/switchpartcommand.o \
|
||||
commands/talkcommand.o \
|
||||
commands/randomcommand.o \
|
||||
tasks/conversationtask.o \
|
||||
tasks/objectanimationtask.o \
|
||||
tasks/saytask.o \
|
||||
tasks/sequentialtask.o \
|
||||
tasks/taskmanager.o \
|
||||
widgets/buttonwidget.o \
|
||||
widgets/conversationwidget.o \
|
||||
widgets/gamewidget.o \
|
||||
widgets/imagewidget.o \
|
||||
widgets/inventorywidget.o \
|
||||
widgets/labelwidget.o \
|
||||
widgets/widget.o \
|
||||
animationdecoder.o \
|
||||
assets.o \
|
||||
conversationlinelist.o \
|
||||
debug.o \
|
||||
encryptedfile.o \
|
||||
font.o \
|
||||
game.o \
|
||||
gamedata.o \
|
||||
gamescreen.o \
|
||||
guiscreen.o \
|
||||
hardcodedstrings.o \
|
||||
inventory.o \
|
||||
inventoryitemdefinitionlist.o \
|
||||
metaengine.o \
|
||||
mutationofjb.o \
|
||||
room.o \
|
||||
script.o \
|
||||
timer.o \
|
||||
util.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_MUTATIONOFJB), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
240
engines/mutationofjb/mutationofjb.cpp
Normal file
240
engines/mutationofjb/mutationofjb.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/savefile.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/gamescreen.h"
|
||||
#include "mutationofjb/debug.h"
|
||||
#include "mutationofjb/room.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
MutationOfJBEngine::MutationOfJBEngine(OSystem *syst, const ADGameDescription *gameDesc)
|
||||
: Engine(syst),
|
||||
_gameDesc(gameDesc),
|
||||
_screen(nullptr),
|
||||
_game(nullptr),
|
||||
_mapObjectId(0),
|
||||
_cursorState(CURSOR_IDLE),
|
||||
_currentScreen(nullptr) {
|
||||
|
||||
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "data");
|
||||
}
|
||||
|
||||
MutationOfJBEngine::~MutationOfJBEngine() {}
|
||||
|
||||
void MutationOfJBEngine::setupCursor() {
|
||||
const uint8 cursor[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
updateCursorPalette();
|
||||
|
||||
CursorMan.disableCursorPalette(true);
|
||||
CursorMan.pushCursor(cursor, 15, 15, 7, 7, 0);
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void MutationOfJBEngine::updateCursorPalette() {
|
||||
if (_cursorState == CURSOR_OFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8 white[] = {0xFF, 0xFF, 0xFF};
|
||||
const uint8 blue[] = {0x00, 0xFF, 0xC3};
|
||||
|
||||
_screen->setPalette(_cursorState == CURSOR_ACTIVE ? blue : white, 0xFF, 1);
|
||||
}
|
||||
|
||||
Graphics::Screen *MutationOfJBEngine::getScreen() const {
|
||||
return _screen;
|
||||
}
|
||||
|
||||
Game &MutationOfJBEngine::getGame() {
|
||||
return *_game;
|
||||
}
|
||||
|
||||
void MutationOfJBEngine::setCursorState(CursorState cursorState) {
|
||||
if (_cursorState == cursorState) {
|
||||
return;
|
||||
}
|
||||
|
||||
_cursorState = cursorState;
|
||||
updateCursorPalette();
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::hasFeature(Engine::EngineFeature f) const {
|
||||
if (f == kSupportsLoadingDuringRuntime || f == kSupportsSavingDuringRuntime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return _game->loadSaveAllowed();
|
||||
}
|
||||
|
||||
Common::Error MutationOfJBEngine::loadGameState(int slot) {
|
||||
const Common::String saveName = getSaveStateName(slot);
|
||||
Common::InSaveFile *const saveFile = g_system->getSavefileManager()->openForLoading(saveName);
|
||||
if (!saveFile)
|
||||
return Common::kReadingFailed;
|
||||
|
||||
Common::Serializer sz(saveFile, nullptr);
|
||||
|
||||
SaveHeader saveHdr;
|
||||
saveHdr.sync(sz);
|
||||
_game->getGameData().saveLoadWithSerializer(sz);
|
||||
delete saveFile;
|
||||
|
||||
_game->changeScene(_game->getGameData()._currentScene, _game->getGameData()._partB);
|
||||
_game->getGameScreen().markDirty();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return _game->loadSaveAllowed();
|
||||
}
|
||||
|
||||
Common::Error MutationOfJBEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
Common::OutSaveFile *const saveFile = g_system->getSavefileManager()->openForSaving(
|
||||
getSaveStateName(slot));
|
||||
if (!saveFile)
|
||||
return Common::kWritingFailed;
|
||||
|
||||
Common::Serializer sz(nullptr, saveFile);
|
||||
|
||||
SaveHeader saveHdr;
|
||||
saveHdr._description = desc;
|
||||
saveHdr.sync(sz);
|
||||
_game->getGameData().saveLoadWithSerializer(sz);
|
||||
saveFile->finalize();
|
||||
delete saveFile;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
const ADGameDescription *MutationOfJBEngine::getGameDescription() const {
|
||||
return _gameDesc;
|
||||
}
|
||||
|
||||
Common::Error MutationOfJBEngine::run() {
|
||||
initGraphics(320, 200);
|
||||
|
||||
setDebugger(new Console(this));
|
||||
_screen = new Graphics::Screen();
|
||||
_game = new Game(this);
|
||||
_currentScreen = &_game->getGameScreen();
|
||||
|
||||
setupCursor();
|
||||
|
||||
if (ConfMan.hasKey("save_slot")) {
|
||||
const Common::Error err = loadGameState(ConfMan.getInt("save_slot"));
|
||||
if (err.getCode() != Common::kNoError)
|
||||
return err;
|
||||
} else {
|
||||
_game->changeScene(13, false); // Initial scene.
|
||||
}
|
||||
|
||||
while (!shouldQuit()) {
|
||||
Common::Event event;
|
||||
while (_eventMan->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYDOWN: {
|
||||
if (event.kbd.keycode == Common::KEYCODE_F5 && event.kbd.hasFlags(0)) {
|
||||
openMainMenuDialog();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_currentScreen)
|
||||
_currentScreen->handleEvent(event);
|
||||
}
|
||||
|
||||
_game->update();
|
||||
if (_currentScreen)
|
||||
_currentScreen->update();
|
||||
|
||||
_system->delayMillis(10);
|
||||
_screen->update();
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool SaveHeader::sync(Common::Serializer &sz) {
|
||||
const uint32 SAVE_MAGIC_NUMBER = MKTAG('M', 'O', 'J', 'B');
|
||||
const uint32 SAVE_FILE_VERSION = 1;
|
||||
|
||||
if (sz.isLoading()) {
|
||||
uint32 magic = 0;
|
||||
sz.syncAsUint32BE(magic);
|
||||
if (magic != SAVE_MAGIC_NUMBER) {
|
||||
warning("Invalid save");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
uint32 magic = SAVE_MAGIC_NUMBER;
|
||||
sz.syncAsUint32BE(magic);
|
||||
}
|
||||
|
||||
sz.syncVersion(SAVE_FILE_VERSION);
|
||||
sz.syncString(_description);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
91
engines/mutationofjb/mutationofjb.h
Normal file
91
engines/mutationofjb/mutationofjb.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_MUTATIONOFJB_H
|
||||
#define MUTATIONOFJB_MUTATIONOFJB_H
|
||||
|
||||
#include "engines/engine.h"
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
struct ADGameDescription;
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
class Serializer;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
class Screen;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Console;
|
||||
class Game;
|
||||
class GuiScreen;
|
||||
|
||||
struct SaveHeader {
|
||||
bool sync(Common::Serializer &sz);
|
||||
|
||||
Common::String _description;
|
||||
};
|
||||
|
||||
class MutationOfJBEngine : public Engine {
|
||||
public:
|
||||
enum CursorState {
|
||||
CURSOR_OFF,
|
||||
CURSOR_IDLE,
|
||||
CURSOR_ACTIVE
|
||||
};
|
||||
|
||||
MutationOfJBEngine(OSystem *syst, const ADGameDescription *gameDesc);
|
||||
~MutationOfJBEngine() override;
|
||||
|
||||
Common::Error run() override;
|
||||
Graphics::Screen *getScreen() const;
|
||||
Game &getGame();
|
||||
void setCursorState(CursorState cursorState);
|
||||
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
|
||||
const ADGameDescription *getGameDescription() const;
|
||||
|
||||
private:
|
||||
bool loadGameData(bool partB);
|
||||
void setupCursor();
|
||||
void updateCursorPalette();
|
||||
|
||||
const ADGameDescription *_gameDesc;
|
||||
Graphics::Screen *_screen;
|
||||
Game *_game;
|
||||
uint8 _mapObjectId;
|
||||
|
||||
CursorState _cursorState;
|
||||
GuiScreen *_currentScreen;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
244
engines/mutationofjb/room.cpp
Normal file
244
engines/mutationofjb/room.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/room.h"
|
||||
|
||||
#include "mutationofjb/animationdecoder.h"
|
||||
#include "mutationofjb/encryptedfile.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/util.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "graphics/screen.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
enum {
|
||||
GAME_AREA_WIDTH = 320,
|
||||
GAME_AREA_HEIGHT = 139
|
||||
};
|
||||
|
||||
class RoomAnimationDecoderCallback : public AnimationDecoderCallback {
|
||||
public:
|
||||
RoomAnimationDecoderCallback(Room &room) : _room(room) {}
|
||||
void onFrame(int frameNo, Graphics::Surface &surface) override;
|
||||
void onPaletteUpdated(byte palette[PALETTE_SIZE]) override;
|
||||
private:
|
||||
Room &_room;
|
||||
};
|
||||
|
||||
void RoomAnimationDecoderCallback::onPaletteUpdated(byte palette[PALETTE_SIZE]) {
|
||||
_room._screen->setPalette(palette, 0x00, 0xC0); // Load only 0xC0 colors.
|
||||
}
|
||||
|
||||
void RoomAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surface) {
|
||||
if (frameNo == 0) {
|
||||
Common::Rect rect(0, 0, GAME_AREA_WIDTH, GAME_AREA_HEIGHT);
|
||||
if (_room._game->isCurrentSceneMap()) {
|
||||
rect = Common::Rect(0, 0, 320, 200);
|
||||
} else {
|
||||
_room._background.blitFrom(surface, rect, Common::Point(0, 0));
|
||||
}
|
||||
_room._screen->blitFrom(surface, rect, Common::Point(0, 0));
|
||||
}
|
||||
|
||||
const int frameNo1 = frameNo + 1;
|
||||
|
||||
Scene *scene = _room._game->getGameData().getCurrentScene();
|
||||
if (scene) {
|
||||
const uint8 noObjects = scene->getNoObjects();
|
||||
for (int i = 0; i < noObjects; ++i) {
|
||||
Object &object = scene->_objects[i];
|
||||
const uint16 startFrame = (object._roomFrameMSB << 8) + object._roomFrameLSB;
|
||||
if (frameNo1 >= startFrame && frameNo1 < startFrame + object._numFrames) {
|
||||
const int x = object._x;
|
||||
const int y = object._y;
|
||||
const int w = (object._width + 3) / 4 * 4; // Original code uses this to round up width to a multiple of 4.
|
||||
const int h = object._height;
|
||||
Common::Rect rect(x, y, x + w, y + h);
|
||||
|
||||
const Graphics::Surface sharedSurface = surface.getSubArea(rect);
|
||||
Graphics::Surface outSurface;
|
||||
outSurface.copyFrom(sharedSurface);
|
||||
_room._surfaces[_room._objectsStart[i] + frameNo1 - startFrame] = outSurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Room::Room(Game *game, Graphics::Screen *screen) : _game(game), _screen(screen), _background(GAME_AREA_WIDTH, GAME_AREA_HEIGHT) {}
|
||||
|
||||
bool Room::load(uint8 roomNumber, bool roomB) {
|
||||
_objectsStart.clear();
|
||||
_surfaces.clear(); // TODO: Fix memory leak.
|
||||
|
||||
Scene *const scene = _game->getGameData().getCurrentScene();
|
||||
if (scene) {
|
||||
const uint8 noObjects = scene->getNoObjects();
|
||||
for (int i = 0; i < noObjects; ++i) {
|
||||
uint8 firstIndex = 0;
|
||||
if (i != 0) {
|
||||
firstIndex = _objectsStart[i - 1] + scene->_objects[i - 1]._numFrames;
|
||||
}
|
||||
_objectsStart.push_back(firstIndex);
|
||||
|
||||
uint8 numAnims = scene->_objects[i]._numFrames;
|
||||
while (numAnims--) {
|
||||
_surfaces.push_back(Graphics::Surface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Common::Path fileName(Common::String::format("room%d%s.dat", roomNumber, roomB ? "b" : ""));
|
||||
AnimationDecoder decoder(fileName);
|
||||
RoomAnimationDecoderCallback callback(*this);
|
||||
return decoder.decode(&callback);
|
||||
}
|
||||
|
||||
// TODO: Take the threshold value from ATN data.
|
||||
struct ThresholdBlitOperation {
|
||||
byte operator()(const byte srcColor, const byte destColor) {
|
||||
if (destColor <= 0xBF) {
|
||||
// Within threshold - replace destination with source color.
|
||||
return srcColor;
|
||||
}
|
||||
|
||||
// Outside of threshold - keep destination color.
|
||||
return destColor;
|
||||
}
|
||||
};
|
||||
|
||||
void Room::drawObjectAnimation(uint8 objectId, int animOffset) {
|
||||
Scene *const scene = _game->getGameData().getCurrentScene();
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
Object *const object = scene->getObject(objectId);
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int startFrame = _objectsStart[objectId - 1];
|
||||
const int animFrame = startFrame + animOffset;
|
||||
|
||||
blit_if(_surfaces[animFrame], *_screen, Common::Point(object->_x, object->_y), ThresholdBlitOperation());
|
||||
if (!_game->isCurrentSceneMap())
|
||||
blit_if(_surfaces[animFrame], _background, Common::Point(object->_x, object->_y), ThresholdBlitOperation());
|
||||
}
|
||||
|
||||
void Room::drawObject(uint8 objectId, uint8 overrideFrame) {
|
||||
Scene *const currentScene = _game->getGameData().getCurrentScene();
|
||||
Object *const object = currentScene->getObject(objectId);
|
||||
|
||||
drawObjectAnimation(objectId, (overrideFrame ? overrideFrame : object->_currentFrame) - _objectsStart[objectId - 1] - 1);
|
||||
}
|
||||
|
||||
void Room::drawBitmap(uint8 bitmapId) {
|
||||
GameData &gameData = _game->getGameData();
|
||||
|
||||
Scene *const scene = gameData.getCurrentScene();
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
Bitmap *const bitmap = scene->getBitmap(bitmapId);
|
||||
if (!bitmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Rect bitmapArea(bitmap->_x1, bitmap->_y1, bitmap->_x2 + 1, bitmap->_y2 + 1);
|
||||
drawFrames(bitmap->_roomFrame - 1, bitmap->_roomFrame - 1, bitmapArea, 0xC0);
|
||||
}
|
||||
|
||||
void Room::drawStatic(Static *const stat) {
|
||||
if (!stat || !stat->allowsImplicitPickup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8 frame = stat->_active ? 1 : 2; // Hardcoded values. Active is taken from frame 1 and inactive from frame 2.
|
||||
const Common::Rect staticArea(stat->_x, stat->_y, stat->_x + stat->_width, stat->_y + stat->_height);
|
||||
drawFrames(frame, frame, staticArea, 0xC0); // Hardcoded threshold.
|
||||
}
|
||||
|
||||
void Room::drawFrames(int fromFrame, int toFrame, const Common::Rect &area, uint8 threshold) {
|
||||
GameData &gameData = _game->getGameData();
|
||||
|
||||
Scene *const scene = gameData.getCurrentScene();
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Common::Path fileName(Common::String::format("room%d%s.dat", gameData._currentScene, gameData._partB ? "b" : ""));
|
||||
|
||||
{
|
||||
AnimationDecoder decoder(fileName, *_screen);
|
||||
decoder.setPartialMode(fromFrame, toFrame, area, threshold);
|
||||
decoder.decode(nullptr);
|
||||
if (!area.isEmpty())
|
||||
_screen->getSubArea(area); // Add dirty rect.
|
||||
else
|
||||
_screen->makeAllDirty();
|
||||
}
|
||||
|
||||
if (!_game->isCurrentSceneMap()) {
|
||||
AnimationDecoder decoder(fileName, _background);
|
||||
decoder.setPartialMode(fromFrame, toFrame, area, threshold);
|
||||
decoder.decode(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Room::initialDraw() {
|
||||
Scene *const currentScene = _game->getGameData().getCurrentScene();
|
||||
|
||||
for (uint8 i = 0; i < currentScene->getNoStatics(); ++i) {
|
||||
Static *const stat = currentScene->getStatic(i + 1);
|
||||
if (stat->_active && stat->allowsImplicitPickup()) {
|
||||
drawStatic(stat);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < currentScene->getNoObjects(); ++i) {
|
||||
Object *const obj = currentScene->getObject(i + 1);
|
||||
if (obj->_active) {
|
||||
drawObjectAnimation(i + 1, obj->_currentFrame - _objectsStart[i] - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < currentScene->getNoBitmaps(); ++i) {
|
||||
Bitmap *const bitmap = currentScene->getBitmap(i + 1);
|
||||
if (bitmap->_isVisible && bitmap->_roomFrame > 0) {
|
||||
drawBitmap(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Room::redraw(bool useBackgroundBuffer) {
|
||||
if (useBackgroundBuffer && !_game->isCurrentSceneMap()) {
|
||||
Common::Rect rect(0, 0, GAME_AREA_WIDTH, GAME_AREA_HEIGHT);
|
||||
_screen->blitFrom(_background.rawSurface(), rect, Common::Point(0, 0));
|
||||
} else {
|
||||
initialDraw();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
79
engines/mutationofjb/room.h
Normal file
79
engines/mutationofjb/room.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_ROOM_H
|
||||
#define MUTATIONOFJB_ROOM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Graphics {
|
||||
class Screen;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class EncryptedFile;
|
||||
class Game;
|
||||
struct Static;
|
||||
|
||||
class Room {
|
||||
public:
|
||||
friend class RoomAnimationDecoderCallback;
|
||||
friend class GuiAnimationDecoderCallback;
|
||||
|
||||
Room(Game *game, Graphics::Screen *screen);
|
||||
bool load(uint8 roomNumber, bool roomB);
|
||||
void drawObjectAnimation(uint8 objectId, int animOffset);
|
||||
|
||||
/**
|
||||
* Draws an object.
|
||||
* By default, object's current frame is used, but that can be overridden.
|
||||
*
|
||||
* @param objectId ID of object to draw.
|
||||
* @param overrideFrame Optional frame override.
|
||||
*/
|
||||
void drawObject(uint8 objectId, uint8 overrideFrame = 0);
|
||||
void drawBitmap(uint8 bitmapId);
|
||||
|
||||
/**
|
||||
* Draws a static.
|
||||
* Only statics that allow implicit pickup are drawable.
|
||||
*
|
||||
* @param stat Static.
|
||||
*/
|
||||
void drawStatic(Static *stat);
|
||||
void drawFrames(int fromFrame, int toFrame, const Common::Rect &area = Common::Rect(), uint8 threshold = 0xFF);
|
||||
void initialDraw();
|
||||
void redraw(bool useBackgroundBuffer = true);
|
||||
private:
|
||||
Game *_game;
|
||||
Graphics::Screen *_screen;
|
||||
Graphics::ManagedSurface _background;
|
||||
Common::Array<Graphics::Surface> _surfaces;
|
||||
Common::Array<int> _objectsStart;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
331
engines/mutationofjb/script.cpp
Normal file
331
engines/mutationofjb/script.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/script.h"
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/debug.h"
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "mutationofjb/commands/ifcommand.h"
|
||||
#include "mutationofjb/commands/ifitemcommand.h"
|
||||
#include "mutationofjb/commands/ifpiggycommand.h"
|
||||
#include "mutationofjb/commands/endblockcommand.h"
|
||||
#include "mutationofjb/commands/changecommand.h"
|
||||
#include "mutationofjb/commands/saycommand.h"
|
||||
#include "mutationofjb/commands/additemcommand.h"
|
||||
#include "mutationofjb/commands/removeitemcommand.h"
|
||||
#include "mutationofjb/commands/removeallitemscommand.h"
|
||||
#include "mutationofjb/commands/labelcommand.h"
|
||||
#include "mutationofjb/commands/gotocommand.h"
|
||||
#include "mutationofjb/commands/camefromcommand.h"
|
||||
#include "mutationofjb/commands/callmacrocommand.h"
|
||||
#include "mutationofjb/commands/newroomcommand.h"
|
||||
#include "mutationofjb/commands/renamecommand.h"
|
||||
#include "mutationofjb/commands/definestructcommand.h"
|
||||
#include "mutationofjb/commands/talkcommand.h"
|
||||
#include "mutationofjb/commands/randomcommand.h"
|
||||
#include "mutationofjb/commands/setcolorcommand.h"
|
||||
#include "mutationofjb/commands/specialshowcommand.h"
|
||||
#include "mutationofjb/commands/switchpartcommand.h"
|
||||
#include "mutationofjb/commands/loadplayercommand.h"
|
||||
#include "mutationofjb/commands/bitmapvisibilitycommand.h"
|
||||
#include "mutationofjb/commands/playanimationcommand.h"
|
||||
#include "mutationofjb/commands/setobjectframecommand.h"
|
||||
#include "mutationofjb/game.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
static CommandParser **getParsers() {
|
||||
static CommandParser *parsers[] = {
|
||||
new IfPiggyCommandParser,
|
||||
new IfItemCommandParser,
|
||||
new IfCommandParser,
|
||||
new CameFromCommandParser,
|
||||
new CallMacroCommandParser,
|
||||
new EndBlockCommandParser,
|
||||
new ChangeDoorCommandParser,
|
||||
new ChangeObjectCommandParser,
|
||||
new ChangeStaticCommandParser,
|
||||
new ChangeSceneCommandParser,
|
||||
new DefineStructCommandParser,
|
||||
new SayCommandParser,
|
||||
new TalkCommandParser,
|
||||
new AddItemCommandParser,
|
||||
new RemoveItemCommandParser,
|
||||
new RemoveAllItemsCommandParser,
|
||||
new RenameCommandParser,
|
||||
new NewRoomCommandParser,
|
||||
new GotoCommandParser,
|
||||
new LabelCommandParser,
|
||||
new RandomCommandParser,
|
||||
new RandomBlockStartParser,
|
||||
new SetColorCommandParser,
|
||||
new SpecialShowCommandParser,
|
||||
new SwitchPartCommandParser,
|
||||
new LoadPlayerCommandParser,
|
||||
new BitmapVisibilityCommandParser,
|
||||
new PlayAnimationCommandParser,
|
||||
new SetObjectFrameCommandParser,
|
||||
nullptr
|
||||
};
|
||||
|
||||
return parsers;
|
||||
}
|
||||
|
||||
|
||||
ScriptParseContext::ScriptParseContext(Common::SeekableReadStream &stream) :
|
||||
_stream(stream),
|
||||
_currentCommand(nullptr),
|
||||
_lastCommand(nullptr),
|
||||
_pendingRandomCommand(nullptr) {}
|
||||
|
||||
bool ScriptParseContext::readLine(Common::String &line) {
|
||||
do {
|
||||
Common::String str = _stream.readLine();
|
||||
if (str.empty())
|
||||
continue;
|
||||
|
||||
if (str[0] != '.') {
|
||||
line = str;
|
||||
if (line[0] == '*') {
|
||||
line.deleteChar(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} while (!_stream.eos());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptParseContext::addConditionalCommand(ConditionalCommand *command, char tag, bool firstHash) {
|
||||
ConditionalCommandInfo cmi = {command, tag, firstHash};
|
||||
_pendingCondCommands.push_back(cmi);
|
||||
}
|
||||
|
||||
|
||||
void ScriptExecutionContext::pushReturnCommand(Command *cmd) {
|
||||
_callStack.push(cmd);
|
||||
}
|
||||
|
||||
Command *ScriptExecutionContext::popReturnCommand() {
|
||||
if (_callStack.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _callStack.pop();
|
||||
}
|
||||
|
||||
Game &ScriptExecutionContext::getGame() {
|
||||
return _game;
|
||||
}
|
||||
|
||||
GameData &ScriptExecutionContext::getGameData() {
|
||||
return _game.getGameData();
|
||||
}
|
||||
|
||||
void ScriptExecutionContext::clear() {
|
||||
_callStack.clear();
|
||||
}
|
||||
|
||||
Command::ExecuteResult ScriptExecutionContext::runActiveCommand() {
|
||||
while (_activeCommand) {
|
||||
const Command::ExecuteResult result = _activeCommand->execute(*this);
|
||||
if (result == Command::Finished) {
|
||||
_activeCommand = _activeCommand->next();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Command::ExecuteResult ScriptExecutionContext::startCommand(Command *cmd) {
|
||||
if (_activeCommand) {
|
||||
warning("Trying to start command while another one is running.");
|
||||
return Command::Finished;
|
||||
}
|
||||
getGameData()._color = WHITE; // The original game resets the color to WHITE beforing running script sections.
|
||||
clear();
|
||||
_activeCommand = cmd;
|
||||
return runActiveCommand();
|
||||
}
|
||||
|
||||
Command::ExecuteResult ScriptExecutionContext::startStartupSection() {
|
||||
Script *localScript = _localScriptOverride ? _localScriptOverride : _game.getLocalScript();
|
||||
|
||||
if (localScript) {
|
||||
Command *const startupCmd = localScript->getStartup(_game.getGameData().getCurrentScene()->_startup);
|
||||
if (startupCmd) {
|
||||
return startCommand(startupCmd);
|
||||
}
|
||||
}
|
||||
|
||||
return Command::Finished;
|
||||
}
|
||||
|
||||
Command *ScriptExecutionContext::getMacro(const Common::String &name) const {
|
||||
Command *cmd = nullptr;
|
||||
|
||||
Script *const localScript = _localScriptOverride ? _localScriptOverride : _game.getLocalScript();
|
||||
Script *const globalScript = _game.getGlobalScript();
|
||||
|
||||
if (localScript) {
|
||||
cmd = localScript->getMacro(name);
|
||||
}
|
||||
|
||||
if (!cmd && globalScript) {
|
||||
cmd = globalScript->getMacro(name);
|
||||
}
|
||||
|
||||
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 ScriptExecutionContext::isCommandRunning() const {
|
||||
return _activeCommand;
|
||||
}
|
||||
|
||||
bool Script::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
|
||||
CommandParser **parsers = getParsers();
|
||||
|
||||
ScriptParseContext parseCtx(stream);
|
||||
|
||||
Common::String line;
|
||||
|
||||
Command *lastCmd = nullptr;
|
||||
CommandParser *lastParser = nullptr;
|
||||
while (parseCtx.readLine(line)) {
|
||||
Command *currentCmd = nullptr;
|
||||
CommandParser *currentParser = nullptr;
|
||||
|
||||
for (CommandParser **parser = parsers; *parser; ++parser) {
|
||||
if ((*parser)->parse(line, parseCtx, currentCmd)) {
|
||||
currentParser = *parser;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!currentParser) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastParser) {
|
||||
lastParser->transition(parseCtx, lastCmd, currentCmd, currentParser);
|
||||
}
|
||||
|
||||
if (currentCmd) {
|
||||
_allCommands.push_back(currentCmd);
|
||||
}
|
||||
|
||||
lastCmd = currentCmd;
|
||||
lastParser = currentParser;
|
||||
}
|
||||
|
||||
for (CommandParser **parser = parsers; *parser; ++parser) {
|
||||
(*parser)->finish(parseCtx);
|
||||
}
|
||||
|
||||
for (ActionInfos::iterator it = parseCtx._actionInfos.begin(); it != parseCtx._actionInfos.end(); ++it) {
|
||||
_actionInfos[it->_action].push_back(*it);
|
||||
}
|
||||
|
||||
_macros = parseCtx._macros;
|
||||
_startups = parseCtx._startups;
|
||||
_extras = parseCtx._extras;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Script::destroy() {
|
||||
for (Commands::iterator it = _allCommands.begin(); it != _allCommands.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
_allCommands.clear();
|
||||
}
|
||||
|
||||
Script::~Script() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
const ActionInfos &Script::getActionInfos(ActionInfo::Action action) {
|
||||
return _actionInfos[action];
|
||||
}
|
||||
|
||||
const Commands &Script::getAllCommands() const {
|
||||
return _allCommands;
|
||||
}
|
||||
|
||||
const Macros &Script::getMacros() const {
|
||||
return _macros;
|
||||
}
|
||||
|
||||
Command *Script::getMacro(const Common::String &name) const {
|
||||
Macros::const_iterator it = _macros.find(name);
|
||||
if (it == _macros.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->_value;
|
||||
}
|
||||
|
||||
const Startups &Script::getStartups() const {
|
||||
return _startups;
|
||||
}
|
||||
|
||||
Command *Script::getStartup(uint8 startupId) const {
|
||||
Startups::const_iterator it = _startups.find(startupId);
|
||||
if (it == _startups.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
154
engines/mutationofjb/script.h
Normal file
154
engines/mutationofjb/script.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SCRIPT_H
|
||||
#define MUTATIONOFJB_SCRIPT_H
|
||||
|
||||
#include "mutationofjb/commands/command.h"
|
||||
#include "common/array.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class Command;
|
||||
class LabelCommand;
|
||||
class Game;
|
||||
class GotoCommand;
|
||||
class ConditionalCommand;
|
||||
class Script;
|
||||
class RandomCommand;
|
||||
struct GameData;
|
||||
|
||||
typedef Common::Array<Command *> Commands;
|
||||
|
||||
struct ActionInfo {
|
||||
enum Action {
|
||||
Look,
|
||||
Walk,
|
||||
Talk,
|
||||
Use,
|
||||
PickUp
|
||||
};
|
||||
|
||||
Action _action;
|
||||
Common::String _entity1Name;
|
||||
Common::String _entity2Name;
|
||||
bool _walkTo;
|
||||
Command *_command;
|
||||
};
|
||||
|
||||
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:
|
||||
ScriptParseContext(Common::SeekableReadStream &stream);
|
||||
bool readLine(Common::String &line);
|
||||
void addConditionalCommand(ConditionalCommand *command, char tag, bool firstHash);
|
||||
void addLookSection(const Common::String &item, bool walkTo);
|
||||
|
||||
Common::SeekableReadStream &_stream;
|
||||
Command *_currentCommand;
|
||||
Command *_lastCommand;
|
||||
|
||||
struct ConditionalCommandInfo {
|
||||
ConditionalCommand *_command;
|
||||
char _tag;
|
||||
bool _firstHash;
|
||||
};
|
||||
typedef Common::Array<ConditionalCommandInfo> ConditionalCommandInfos;
|
||||
ConditionalCommandInfos _pendingCondCommands;
|
||||
|
||||
typedef Common::HashMap<Common::String, LabelCommand *> LabelMap;
|
||||
LabelMap _labels;
|
||||
|
||||
typedef Common::HashMap<Common::String, GotoCommands> PendingGotoMap;
|
||||
PendingGotoMap _pendingGotos;
|
||||
|
||||
RandomCommand *_pendingRandomCommand;
|
||||
|
||||
ActionInfos _actionInfos;
|
||||
Macros _macros;
|
||||
Startups _startups;
|
||||
Extras _extras;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class ScriptExecutionContext {
|
||||
public:
|
||||
ScriptExecutionContext(Game &game, Script *localScriptOverride = nullptr) : _game(game), _activeCommand(nullptr), _localScriptOverride(localScriptOverride) {}
|
||||
void clear();
|
||||
|
||||
Command::ExecuteResult runActiveCommand();
|
||||
Command::ExecuteResult startCommand(Command *cmd);
|
||||
Command::ExecuteResult startStartupSection();
|
||||
|
||||
void pushReturnCommand(Command *);
|
||||
Command *popReturnCommand();
|
||||
Game &getGame();
|
||||
GameData &getGameData();
|
||||
Command *getMacro(const Common::String &name) const;
|
||||
Command *getExtra(const Common::String &name) const;
|
||||
bool isCommandRunning() const;
|
||||
|
||||
private:
|
||||
Game &_game;
|
||||
Command *_activeCommand;
|
||||
Common::Stack<Command *> _callStack;
|
||||
Script *_localScriptOverride;
|
||||
};
|
||||
|
||||
class Script {
|
||||
public:
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
~Script();
|
||||
|
||||
const ActionInfos &getActionInfos(ActionInfo::Action action);
|
||||
const Commands &getAllCommands() const;
|
||||
const Macros &getMacros() const;
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
284
engines/mutationofjb/tasks/conversationtask.cpp
Normal file
284
engines/mutationofjb/tasks/conversationtask.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/tasks/conversationtask.h"
|
||||
|
||||
#include "mutationofjb/assets.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/gamescreen.h"
|
||||
#include "mutationofjb/script.h"
|
||||
#include "mutationofjb/tasks/saytask.h"
|
||||
#include "mutationofjb/tasks/sequentialtask.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();
|
||||
game.getGameScreen().showConversationWidget(true);
|
||||
ConversationWidget &widget = game.getGameScreen().getConversationWidget();
|
||||
widget.setCallback(this);
|
||||
|
||||
_currentGroupIndex = 0;
|
||||
|
||||
showChoicesOrPick();
|
||||
}
|
||||
|
||||
void ConversationTask::update() {
|
||||
if (_sayTask) {
|
||||
if (_sayTask->getState() == Task::FINISHED) {
|
||||
_sayTask.reset();
|
||||
|
||||
switch (_substate) {
|
||||
case SAYING_NO_QUESTIONS:
|
||||
finish();
|
||||
break;
|
||||
case SAYING_QUESTION: {
|
||||
const ConversationLineList &responseList = getTaskManager()->getGame().getAssets().getResponseList();
|
||||
const ConversationLineList::Line *const line = responseList.getLine(_currentItem->_response);
|
||||
|
||||
_substate = SAYING_RESPONSE;
|
||||
createSayTasks(line);
|
||||
getTaskManager()->startTask(_sayTask);
|
||||
break;
|
||||
}
|
||||
case SAYING_RESPONSE: {
|
||||
startExtra();
|
||||
|
||||
if (_substate != RUNNING_EXTRA) {
|
||||
gotoNextGroup();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_innerExecCtx) {
|
||||
Command::ExecuteResult res = _innerExecCtx->runActiveCommand();
|
||||
if (res == Command::Finished) {
|
||||
delete _innerExecCtx;
|
||||
_innerExecCtx = nullptr;
|
||||
|
||||
gotoNextGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConversationTask::onChoiceClicked(ConversationWidget *convWidget, int, uint32 data) {
|
||||
const ConversationInfo::Item &item = getCurrentGroup()[data];
|
||||
convWidget->clearChoices();
|
||||
|
||||
const ConversationLineList &toSayList = getTaskManager()->getGame().getAssets().getToSayList();
|
||||
const ConversationLineList::Line *line = toSayList.getLine(item._question);
|
||||
|
||||
_substate = SAYING_QUESTION;
|
||||
createSayTasks(line);
|
||||
getTaskManager()->startTask(_sayTask);
|
||||
_currentItem = &item;
|
||||
|
||||
if (!line->_speeches[0].isRepeating()) {
|
||||
getTaskManager()->getGame().getGameData().getCurrentScene()->addExhaustedConvItem(_convInfo._context, data + 1, _currentGroupIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ConversationTask::showChoicesOrPick() {
|
||||
Game &game = getTaskManager()->getGame();
|
||||
GameData &gameData = game.getGameData();
|
||||
Scene *const scene = gameData.getScene(_sceneId);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Array<uint32> itemsWithValidQuestions;
|
||||
Common::Array<uint32> itemsWithValidResponses;
|
||||
Common::Array<uint32> itemsWithValidNext;
|
||||
|
||||
/*
|
||||
Collect valid questions (not exhausted and not empty).
|
||||
Collect valid responses (not exhausted and not empty).
|
||||
If there are at least two visible questions, we show them.
|
||||
If there is just one visible question, pick it automatically ONLY if this is not the first question in this conversation.
|
||||
Otherwise we don't start the conversation.
|
||||
If there are no visible questions, automatically pick the first valid response.
|
||||
If nothing above applies, don't start the conversation.
|
||||
*/
|
||||
|
||||
const ConversationInfo::ItemGroup ¤tGroup = getCurrentGroup();
|
||||
for (ConversationInfo::ItemGroup::size_type i = 0; i < currentGroup.size(); ++i) {
|
||||
const ConversationInfo::Item &item = currentGroup[i];
|
||||
|
||||
if (scene->isConvItemExhausted(_convInfo._context, static_cast<uint8>(i + 1), static_cast<uint8>(_currentGroupIndex + 1))) {
|
||||
continue;
|
||||
}
|
||||
const uint8 toSay = item._question;
|
||||
const uint8 response = item._response;
|
||||
const uint8 next = item._nextGroupIndex;
|
||||
|
||||
if (toSay != 0) {
|
||||
itemsWithValidQuestions.push_back(i);
|
||||
}
|
||||
|
||||
if (response != 0) {
|
||||
itemsWithValidResponses.push_back(i);
|
||||
}
|
||||
|
||||
if (next != 0) {
|
||||
itemsWithValidNext.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsWithValidQuestions.size() > 1) {
|
||||
ConversationWidget &widget = game.getGameScreen().getConversationWidget();
|
||||
const ConversationLineList &toSayList = game.getAssets().getToSayList();
|
||||
|
||||
for (Common::Array<uint32>::size_type i = 0; i < itemsWithValidQuestions.size() && i < ConversationWidget::CONVERSATION_MAX_CHOICES; ++i) {
|
||||
const ConversationInfo::Item &item = currentGroup[itemsWithValidQuestions[i]];
|
||||
const ConversationLineList::Line *const line = toSayList.getLine(item._question);
|
||||
const Common::String widgetText = toUpperCP895(line->_speeches[0]._text);
|
||||
widget.setChoice(static_cast<int>(i), widgetText, itemsWithValidQuestions[i]);
|
||||
}
|
||||
_substate = IDLE;
|
||||
_currentItem = nullptr;
|
||||
|
||||
_haveChoices = true;
|
||||
} else if (itemsWithValidQuestions.size() == 1 && _haveChoices) {
|
||||
const ConversationLineList &toSayList = game.getAssets().getToSayList();
|
||||
const ConversationInfo::Item &item = currentGroup[itemsWithValidQuestions.front()];
|
||||
const ConversationLineList::Line *const line = toSayList.getLine(item._question);
|
||||
|
||||
_substate = SAYING_QUESTION;
|
||||
createSayTasks(line);
|
||||
getTaskManager()->startTask(_sayTask);
|
||||
_currentItem = &item;
|
||||
|
||||
if (!line->_speeches[0].isRepeating()) {
|
||||
game.getGameData().getCurrentScene()->addExhaustedConvItem(_convInfo._context, itemsWithValidQuestions.front() + 1, _currentGroupIndex + 1);
|
||||
}
|
||||
|
||||
_haveChoices = true;
|
||||
} else if (!itemsWithValidResponses.empty() && _haveChoices) {
|
||||
const ConversationLineList &responseList = game.getAssets().getResponseList();
|
||||
const ConversationInfo::Item &item = currentGroup[itemsWithValidResponses.front()];
|
||||
const ConversationLineList::Line *const line = responseList.getLine(item._response);
|
||||
|
||||
_substate = SAYING_RESPONSE;
|
||||
createSayTasks(line);
|
||||
getTaskManager()->startTask(_sayTask);
|
||||
_currentItem = &item;
|
||||
|
||||
_haveChoices = true;
|
||||
} else if (!itemsWithValidNext.empty() && _haveChoices) {
|
||||
_currentGroupIndex = currentGroup[itemsWithValidNext.front()]._nextGroupIndex - 1;
|
||||
showChoicesOrPick();
|
||||
} else {
|
||||
if (_haveChoices) {
|
||||
finish();
|
||||
} else {
|
||||
_sayTask = TaskPtr(new SayTask("Nothing to talk about.", _convInfo._color)); // TODO: This is hardcoded in executable. Load it.
|
||||
getTaskManager()->startTask(_sayTask);
|
||||
_substate = SAYING_NO_QUESTIONS;
|
||||
_currentItem = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ConversationInfo::ItemGroup &ConversationTask::getCurrentGroup() const {
|
||||
assert(_currentGroupIndex < _convInfo._itemGroups.size());
|
||||
return _convInfo._itemGroups[_currentGroupIndex];
|
||||
}
|
||||
|
||||
void ConversationTask::finish() {
|
||||
setState(FINISHED);
|
||||
|
||||
Game &game = getTaskManager()->getGame();
|
||||
game.getGameScreen().showConversationWidget(false);
|
||||
ConversationWidget &widget = game.getGameScreen().getConversationWidget();
|
||||
widget.setCallback(nullptr);
|
||||
}
|
||||
|
||||
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::gotoNextGroup() {
|
||||
if (_currentItem->_nextGroupIndex == 0) {
|
||||
finish();
|
||||
} else {
|
||||
_currentGroupIndex = _currentItem->_nextGroupIndex - 1;
|
||||
showChoicesOrPick();
|
||||
}
|
||||
}
|
||||
|
||||
void ConversationTask::createSayTasks(const ConversationLineList::Line *line) {
|
||||
if (line->_speeches.size() == 1) {
|
||||
const ConversationLineList::Speech &speech = line->_speeches[0];
|
||||
_sayTask = TaskPtr(new SayTask(speech._text, getSpeechColor(speech)));
|
||||
} else {
|
||||
TaskPtrs tasks;
|
||||
for (ConversationLineList::Speeches::const_iterator it = line->_speeches.begin(); it != line->_speeches.end(); ++it) {
|
||||
tasks.push_back(TaskPtr(new SayTask(it->_text, getSpeechColor(*it))));
|
||||
}
|
||||
_sayTask = TaskPtr(new SequentialTask(tasks));
|
||||
}
|
||||
}
|
||||
|
||||
uint8 ConversationTask::getSpeechColor(const ConversationLineList::Speech &speech) {
|
||||
uint8 color = WHITE;
|
||||
if (_substate == SAYING_RESPONSE) {
|
||||
color = _convInfo._color;
|
||||
if (_mode == TalkCommand::RAY_AND_BUTTLEG_MODE) {
|
||||
if (speech.isFirstSpeaker()) {
|
||||
color = GREEN;
|
||||
} else if (speech.isSecondSpeaker()) {
|
||||
color = LIGHTBLUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
}
|
||||
71
engines/mutationofjb/tasks/conversationtask.h
Normal file
71
engines/mutationofjb/tasks/conversationtask.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/commands/talkcommand.h"
|
||||
#include "mutationofjb/conversationlinelist.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/tasks/task.h"
|
||||
#include "mutationofjb/widgets/conversationwidget.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SayTask;
|
||||
class ScriptExecutionContext;
|
||||
|
||||
class ConversationTask : public Task, public ConversationWidgetCallback {
|
||||
public:
|
||||
ConversationTask(uint8 sceneId, const ConversationInfo &convInfo, TalkCommand::Mode mode) : _sceneId(sceneId), _convInfo(convInfo), _mode(mode), _currentGroupIndex(0), _currentItem(nullptr), _substate(IDLE), _haveChoices(false), _innerExecCtx(nullptr) {}
|
||||
~ConversationTask() override {}
|
||||
|
||||
void start() override;
|
||||
void update() override;
|
||||
|
||||
void onChoiceClicked(ConversationWidget *, int response, uint32 data) override;
|
||||
private:
|
||||
void showChoicesOrPick();
|
||||
const ConversationInfo::ItemGroup &getCurrentGroup() const;
|
||||
void finish();
|
||||
void startExtra();
|
||||
void gotoNextGroup();
|
||||
void createSayTasks(const ConversationLineList::Line *line);
|
||||
uint8 getSpeechColor(const ConversationLineList::Speech &speech);
|
||||
|
||||
uint8 _sceneId;
|
||||
const ConversationInfo &_convInfo;
|
||||
TalkCommand::Mode _mode;
|
||||
uint _currentGroupIndex;
|
||||
const ConversationInfo::Item *_currentItem;
|
||||
TaskPtr _sayTask;
|
||||
|
||||
enum Substate {
|
||||
IDLE,
|
||||
SAYING_QUESTION,
|
||||
SAYING_RESPONSE,
|
||||
SAYING_NO_QUESTIONS,
|
||||
RUNNING_EXTRA
|
||||
};
|
||||
|
||||
Substate _substate;
|
||||
bool _haveChoices;
|
||||
ScriptExecutionContext *_innerExecCtx;
|
||||
};
|
||||
|
||||
}
|
||||
153
engines/mutationofjb/tasks/objectanimationtask.cpp
Normal file
153
engines/mutationofjb/tasks/objectanimationtask.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mutationofjb/tasks/objectanimationtask.h"
|
||||
|
||||
#include "mutationofjb/tasks/taskmanager.h"
|
||||
#include "mutationofjb/game.h"
|
||||
#include "mutationofjb/gamedata.h"
|
||||
#include "mutationofjb/room.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
static const int TICK_MILLIS = 100;
|
||||
|
||||
// TODO: Respect currentScene._delay.
|
||||
ObjectAnimationTask::ObjectAnimationTask() : _timer(TICK_MILLIS) {
|
||||
}
|
||||
|
||||
void ObjectAnimationTask::start() {
|
||||
setState(RUNNING);
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void ObjectAnimationTask::update() {
|
||||
_timer.update();
|
||||
if (_timer.isFinished()) {
|
||||
_timer.start();
|
||||
updateObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectAnimationTask::updateObjects() {
|
||||
Scene *const scene = getTaskManager()->getGame().getGameData().getCurrentScene();
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8 i = 1; i <= scene->getNoObjects(); ++i) {
|
||||
Object *const object = scene->getObject(i);
|
||||
// Skip if object animation not active.
|
||||
if (!object->_active)
|
||||
continue;
|
||||
|
||||
// Number of frames must be higher than 1.
|
||||
if (object->_numFrames <= 1)
|
||||
continue;
|
||||
|
||||
const uint8 currentAnimOffset = object->_currentFrame - object->_firstFrame;
|
||||
|
||||
const bool randomized = object->_randomFrame != 0;
|
||||
const bool belowRandomFrame = currentAnimOffset < (object->_randomFrame - 1);
|
||||
|
||||
uint8 maxAnimOffset = object->_numFrames - 1;
|
||||
if (randomized && belowRandomFrame) {
|
||||
maxAnimOffset = object->_randomFrame - 2;
|
||||
}
|
||||
|
||||
uint8 nextAnimationOffset = currentAnimOffset + 1;
|
||||
if (currentAnimOffset == maxAnimOffset) {
|
||||
if (randomized && object->_jumpChance != 0 && getTaskManager()->getGame().getRandomSource().getRandomNumber(object->_jumpChance) == 0)
|
||||
nextAnimationOffset = object->_randomFrame - 1;
|
||||
else
|
||||
nextAnimationOffset = 0;
|
||||
}
|
||||
|
||||
object->_currentFrame = nextAnimationOffset + object->_firstFrame;
|
||||
|
||||
const bool drawObject = handleHardcodedAnimation(object);
|
||||
if (drawObject) {
|
||||
getTaskManager()->getGame().getRoom().drawObject(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectAnimationTask::handleHardcodedAnimation(Object *const object) {
|
||||
GameData &gameData = getTaskManager()->getGame().getGameData();
|
||||
Scene *const scene = gameData.getCurrentScene();
|
||||
|
||||
const bool carnivalScene = gameData._currentScene == 30 && !gameData._partB;
|
||||
const bool tavernScene = gameData._currentScene == 8 && gameData._partB;
|
||||
|
||||
if (carnivalScene) {
|
||||
// This alternates between the two burglars' talking animations.
|
||||
// Each burglar gets to talk for a varying amount of time since
|
||||
// the switch occurs when his random frame is reached.
|
||||
if (object->_WX == 1 && object->_currentFrame == 79) {
|
||||
object->_currentFrame = 68;
|
||||
object->_active = 0;
|
||||
scene->getObject(6)->_active = 1;
|
||||
scene->getObject(7)->_active = 0;
|
||||
scene->getObject(8)->_active = 1;
|
||||
return false;
|
||||
} else if (object->_WX == 2 && object->_currentFrame == 91) {
|
||||
object->_currentFrame = 80;
|
||||
object->_active = 0;
|
||||
scene->getObject(5)->_active = 1;
|
||||
scene->getObject(7)->_active = 1;
|
||||
scene->getObject(8)->_active = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The following makes sure you can't interact with the glass
|
||||
// while the scientist is drinking from it.
|
||||
if (scene->getObject(4)->_currentFrame > 52 && scene->getObject(4)->_active) {
|
||||
scene->getStatic(9)->_active = 0; // disable scientist's glass
|
||||
} else {
|
||||
scene->getStatic(9)->_active = 1; // enable scientist's glass
|
||||
}
|
||||
|
||||
if (!scene->getObject(4)->_active) {
|
||||
scene->getStatic(9)->_active = 0; // disable scientist's glass
|
||||
}
|
||||
} else if (tavernScene) {
|
||||
// Similarly to the carnival burglars, this alternates between
|
||||
// the talking animations of the two soldiers in the tavern.
|
||||
//
|
||||
// At some point the script disables their conversation
|
||||
// by nulling their _WX registers.
|
||||
if (object->_WX == 3 && object->_currentFrame == 46) {
|
||||
object->_currentFrame = 30;
|
||||
object->_active = 0;
|
||||
scene->getObject(3)->_active = 1;
|
||||
return false;
|
||||
} else if (object->_WX == 4 && object->_currentFrame == 63) {
|
||||
object->_currentFrame = 47;
|
||||
object->_active = 0;
|
||||
scene->getObject(2)->_active = 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
69
engines/mutationofjb/tasks/objectanimationtask.h
Normal file
69
engines/mutationofjb/tasks/objectanimationtask.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_OBJECTANIMATIONTASK_H
|
||||
#define MUTATIONOFJB_OBJECTANIMATIONTASK_H
|
||||
|
||||
#include "mutationofjb/tasks/task.h"
|
||||
|
||||
#include "mutationofjb/timer.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
struct Object;
|
||||
|
||||
class ObjectAnimationTask : public Task {
|
||||
public:
|
||||
ObjectAnimationTask();
|
||||
|
||||
void start() override;
|
||||
void update() override;
|
||||
|
||||
/**
|
||||
* Advances every object animation in the current scene to the next frame.
|
||||
*
|
||||
* Normally the animation restarts after the last object frame. However, some animations have random
|
||||
* elements to them. If _randomFrame is set, the animation restarts when _randomFrame is reached.
|
||||
* Additionally, there is a chance with each frame until _randomFrame that the animation may jump
|
||||
* straight to _randomFrame and continue until the last frame, then wrap around to the first frame.
|
||||
*
|
||||
* Randomness is used to introduce variety - e.g. in the starting scene a perched bird occasionally
|
||||
* spreads its wings.
|
||||
*/
|
||||
void updateObjects();
|
||||
|
||||
/**
|
||||
* Nasty, hacky stuff the original game does to make some complex animations
|
||||
* in the Carnival and Tavern Earthquake scenes possible.
|
||||
*
|
||||
* @param object Object to process.
|
||||
* @return Whether to draw the object. It's important to respect this, otherwise
|
||||
* some of the hardcoded animations would suffer from graphical glitches.
|
||||
*/
|
||||
bool handleHardcodedAnimation(Object *const object);
|
||||
|
||||
private:
|
||||
Timer _timer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
103
engines/mutationofjb/tasks/saytask.cpp
Normal file
103
engines/mutationofjb/tasks/saytask.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 "mutationofjb/util.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(50 * toSay.size()) {}
|
||||
|
||||
void SayTask::start() {
|
||||
Game &game = getTaskManager()->getGame();
|
||||
if (game.getActiveSayTask()) {
|
||||
getTaskManager()->stopTask(game.getActiveSayTask());
|
||||
}
|
||||
game.setActiveSayTask(getTaskManager()->getTask(this));
|
||||
|
||||
setState(RUNNING);
|
||||
drawSubtitle(_toSay, 160, 0, _color); // TODO: Respect PTALK and LTALK commands.
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void SayTask::update() {
|
||||
_timer.update();
|
||||
|
||||
if (_timer.isFinished()) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
void SayTask::stop() {
|
||||
if (getState() == RUNNING) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
void SayTask::drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, uint8 color) {
|
||||
const int MAX_LINE_WIDTH = 250;
|
||||
|
||||
const Font &font = getTaskManager()->getGame().getAssets().getSpeechFont();
|
||||
|
||||
Common::Array<Common::String> lines;
|
||||
const int16 actualMaxWidth = font.wordWrapText(text, MAX_LINE_WIDTH, lines);
|
||||
|
||||
// Get the x, y coordinates of the top center point of the text's bounding box
|
||||
// from the (rather strange) talk coordinates coming from scripts.
|
||||
int16 x = talkX;
|
||||
int16 y = talkY - (lines.size() - 1) * font.getFontHeight() - 15;
|
||||
|
||||
// Clamp to screen edges.
|
||||
x = CLIP<int16>(x, 3 + actualMaxWidth / 2, 317 - actualMaxWidth / 2);
|
||||
y = MAX<int16>(y, 3);
|
||||
|
||||
// Remember the area occupied by the text.
|
||||
_boundingBox.left = x - actualMaxWidth / 2;
|
||||
_boundingBox.top = y;
|
||||
_boundingBox.setWidth(actualMaxWidth);
|
||||
_boundingBox.setHeight(lines.size() * font.getFontHeight());
|
||||
|
||||
// Draw lines.
|
||||
for (uint i = 0; i < lines.size(); i++) {
|
||||
font.drawString(&getTaskManager()->getGame().getScreen(), lines[i], _boundingBox.left, _boundingBox.top + i * font.getFontHeight(), _boundingBox.width(), color, Graphics::kTextAlignCenter);
|
||||
}
|
||||
}
|
||||
|
||||
void SayTask::finish() {
|
||||
getTaskManager()->getGame().getRoom().redraw(); // TODO: Only redraw the area occupied by the text.
|
||||
setState(FINISHED);
|
||||
|
||||
Game &game = getTaskManager()->getGame();
|
||||
if (game.getActiveSayTask().get() == this) {
|
||||
game.setActiveSayTask(Common::SharedPtr<SayTask>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
54
engines/mutationofjb/tasks/saytask.h
Normal file
54
engines/mutationofjb/tasks/saytask.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MUTATIONOFJB_SAYTASK_H
|
||||
#define MUTATIONOFJB_SAYTASK_H
|
||||
|
||||
#include "mutationofjb/tasks/task.h"
|
||||
|
||||
#include "mutationofjb/timer.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
class SayTask : public Task {
|
||||
public:
|
||||
SayTask(const Common::String &toSay, uint8 color);
|
||||
|
||||
void start() override;
|
||||
void update() override;
|
||||
void stop() override;
|
||||
|
||||
private:
|
||||
void drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, uint8 color);
|
||||
void finish();
|
||||
|
||||
Common::String _toSay;
|
||||
uint8 _color;
|
||||
Timer _timer;
|
||||
Common::Rect _boundingBox;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user