Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1 @@
engines/qdengine/dialogs.cpp

View 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 qdengine "QD Engine" yes "" "" "vorbis 16bit highres mpeg2" "imgui mpc mpeg2"

View File

@@ -0,0 +1,39 @@
/* 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 "qdengine/console.h"
namespace QDEngine {
Console::Console() : GUI::Debugger() {
registerCmd("test", WRAP_METHOD(Console, Cmd_test));
}
Console::~Console() {
}
bool Console::Cmd_test(int argc, const char **argv) {
debugPrintf("Test\n");
return true;
}
} // namespace Qdengine

View File

@@ -0,0 +1,40 @@
/* 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 QDENGINE_CONSOLE_H
#define QDENGINE_CONSOLE_H
#include "gui/debugger.h"
namespace QDEngine {
class Console : public GUI::Debugger {
private:
bool Cmd_test(int argc, const char **argv);
public:
Console();
~Console() override;
};
} // End of namespace QDEngine
#endif // QDENGINE_CONSOLE_H

View File

@@ -0,0 +1,4 @@
begin_section("QDEngine");
add_person("Eugene Sandulenko", "sev", "");
add_person("Kunal Tiwari", "kunxl.gg", "");
end_section();

View File

@@ -0,0 +1,567 @@
/* 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 "backends/imgui/IconsMaterialSymbols.h"
#define IMGUI_DEFINE_MATH_OPERATORS
#include "backends/imgui/imgui.h"
#include "backends/imgui/imgui_fonts.h"
#include "common/archive.h"
#include "common/compression/unzip.h"
#include "common/debug.h"
#include "common/path.h"
#include "common/stack.h"
#include "common/system.h"
#include "graphics/managed_surface.h"
#include "qdengine/debugger/dt-internal.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_animation.h"
#include "qdengine/qdcore/qd_animation_frame.h"
#include "qdengine/qdcore/qd_file_manager.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
#include "qdengine/qdcore/qd_game_object.h"
#include "qdengine/qdcore/qd_game_object_moving.h"
#include "qdengine/qdcore/qd_game_scene.h"
#include "qdengine/qdengine.h"
#include "qdengine/system/graphics/gr_dispatcher.h"
namespace QDEngine {
const int TILES_ID = -1337;
ImGuiState *_state = nullptr;
ImGuiImage getImageID(Common::Path filename, int frameNum) {
Common::String key = Common::String::format("%s:%d", filename.toString().c_str(), frameNum);
if (_state->_frames.contains(key))
return _state->_frames[key];
int sx = 10, sy = 10;
Graphics::ManagedSurface *surface = nullptr;
if (_state->_displayMode == kDisplayQDA) {
// Load the animation
qdAnimation *animation = new qdAnimation();
animation->qda_load(filename);
_state->_qdaToDisplayFrameCount = animation->num_frames();
if (frameNum == TILES_ID) {
if (animation->tileAnimation()) {
surface = animation->tileAnimation()->dumpTiles(25);
sx = surface->w;
sy = surface->h;
}
} else if (frameNum < 0) { // Tiles
if (animation->tileAnimation()) {
surface = animation->tileAnimation()->dumpFrameTiles(-frameNum + 1, 0.91670f);
sx = surface->w;
sy = surface->h;
}
} else {
if (animation->tileAnimation()) {
Vect2i size = animation->tileAnimation()->frameSize();
sx = size.x;
sy = size.y;
} else {
qdAnimationFrame *frame = animation->get_frame(frameNum);
if (frame) {
sx = frame->size_x();
sy = frame->size_y();
}
}
surface = new Graphics::ManagedSurface(sx, sy, g_engine->_pixelformat);
animation->set_cur_frame(frameNum);
grDispatcher::instance()->surfaceOverride(surface);
animation->redraw(sx / 2, sy / 2, 0, 0.91670f, 0);
grDispatcher::instance()->resetSurfaceOverride();
}
delete animation;
} else if (_state->_displayMode == kDisplayTGA) {
qdSprite *sprite = new qdSprite();
if (sprite->load(filename)) {
sx = sprite->size_x();
sy = sprite->size_y();
surface = new Graphics::ManagedSurface(sx, sy, g_engine->_pixelformat);
grDispatcher::instance()->surfaceOverride(surface);
sprite->redraw(sx / 2, sy / 2, 0);
grDispatcher::instance()->resetSurfaceOverride();
} else {
warning("Error loading TGA file '%s'", transCyrillic(filename.toString()));
}
delete sprite;
}
if (surface)
_state->_frames[key] = { (ImTextureID)g_system->getImGuiTexture(*surface->surfacePtr()), sx, sy };
delete surface;
return _state->_frames[key];
}
void showImage(const ImGuiImage &image, const char *name, float scale) {
ImVec2 size = { (float)image.width * scale, (float)image.height * scale };
ImGui::BeginGroup();
ImVec2 screenPos = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRect(screenPos, screenPos + ImVec2(size.x, size.y), 0xFFFFFFFF);
ImGui::Image(image.id, size);
ImGui::EndGroup();
//setToolTipImage(image, name);
}
FileTree::FileTree(Common::Path *p, Common::String n, bool node, int i) {
id = i;
if (!node) {
name = (char *)transCyrillic(n);
} else {
path = *p;
name = (char *)transCyrillic(p->baseName());
}
}
void populateFileList() {
Common::Array<Common::Path> files;
// Iterate through the 3 resource pak files
for (int i = 0; i < qdFileManager::instance().get_num_packages(); i++) {
Common::Archive *archive = qdFileManager::instance().get_package(i);
Common::ArchiveMemberList members;
if (archive)
archive->listMembers(members);
for (auto &it : members)
files.push_back(it->getPathInArchive());
}
Common::sort(files.begin(), files.end());
// Now build a tree
Common::Path curr;
Common::Stack<FileTree *> treeStack;
_state->_files.name = "Resource";
treeStack.push(&_state->_files);
int id = 0;
for (unsigned int f = 0; f < files.size(); f++) {
// Skip duplicates between the archives
if (f && files[f] == files[f - 1])
continue;
Common::Path parent = files[f].getParent();
if (parent != curr) {
Common::StringArray curArr = curr.splitComponents();
Common::StringArray newArr = parent.splitComponents();
if (curArr.back().empty())
curArr.pop_back();
if (newArr.back().empty())
newArr.pop_back();
unsigned int pos = 0;
while (pos < curArr.size() && pos < newArr.size() && curArr[pos] == newArr[pos])
pos++;
// if we need to close directories
if (pos < curArr.size()) {
for (unsigned int i = pos; i < curArr.size(); i++)
(void)treeStack.pop();
}
for (; pos < newArr.size(); pos++) {
if (id == 0 && newArr[pos] == "Resource") // Skip the root node
continue;
treeStack.top()->children.push_back(new FileTree(nullptr, newArr[pos], false, ++id));
treeStack.push(treeStack.top()->children.back());
}
curr = parent;
}
treeStack.top()->children.push_back(new FileTree(&files[f], "", true, ++id));
id++;
}
}
static void displayQDA() {
int totalFrames = _state->_qdaToDisplayFrameCount;
ImGuiImage imgID;
if (!_state->_fileToDisplay.empty()) {
imgID = getImageID(_state->_fileToDisplay, _state->_qdaToDisplayFrame);
ImGui::Text("Frame %s: %d of %d [%d x %d]", transCyrillic(_state->_fileToDisplay.toString()), _state->_qdaToDisplayFrame + 1,
totalFrames, imgID.width, imgID.height);
} else {
ImGui::Text("Frame <none>");
}
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
if (ImGui::BeginTabBar("FrameTabBar", tab_bar_flags)) {
if (ImGui::BeginTabItem("Animation")) {
if (ImGui::Button(ICON_MS_FAST_REWIND)) {
_state->_qdaToDisplayFrame = 0;
_state->_qdaIsPlaying = false;
}
ImGui::SameLine();
if (ImGui::Button(ICON_MS_SKIP_PREVIOUS)) {
_state->_qdaToDisplayFrame = _state->_qdaToDisplayFrame + totalFrames - 1;
_state->_qdaToDisplayFrame %= totalFrames;
}
ImGui::SameLine();
if (ImGui::Button(ICON_MS_PLAY_ARROW))
_state->_qdaIsPlaying = !_state->_qdaIsPlaying;
ImGui::SameLine();
if (ImGui::Button(ICON_MS_SKIP_NEXT)) {
_state->_qdaToDisplayFrame += 1;
_state->_qdaToDisplayFrame %= totalFrames;
}
ImGui::SameLine();
if (ImGui::Button(ICON_MS_FAST_FORWARD)) {
_state->_qdaToDisplayFrame = totalFrames - 1;
_state->_qdaIsPlaying = false;
}
ImGui::SameLine();
// Frame Count
char buf[6];
snprintf(buf, 6, "%d", _state->_qdaToDisplayFrame);
ImGui::SetNextItemWidth(35);
ImGui::InputText("##frame", buf, 5, ImGuiInputTextFlags_CharsDecimal);
ImGui::SetItemTooltip("Frame");
ImGui::Separator();
if (!_state->_fileToDisplay.empty()) {
showImage(imgID, (char *)transCyrillic(_state->_fileToDisplay.toString()), 1.0);
} else {
ImGui::InvisibleButton("##canvas", ImVec2(32.f, 32.f));
}
ImGui::SameLine();
imgID = getImageID(_state->_fileToDisplay, -_state->_qdaToDisplayFrame - 1);
showImage(imgID, (char *)transCyrillic(_state->_fileToDisplay.toString()), 1.0);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Tiles")) {
if (!_state->_fileToDisplay.empty()) {
imgID = getImageID(_state->_fileToDisplay, TILES_ID);
showImage(imgID, (char *)transCyrillic(_state->_fileToDisplay.toString()), 1.0);
} else {
ImGui::InvisibleButton("##canvas", ImVec2(32.f, 32.f));
}
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
static void displayTGA() {
ImGuiImage imgID;
imgID = getImageID(_state->_fileToDisplay, 0);
ImGui::Text("TGA %s: [%d x %d]", transCyrillic(_state->_fileToDisplay.toString()), imgID.width, imgID.height);
ImGui::Separator();
showImage(imgID, (char *)transCyrillic(_state->_fileToDisplay.toString()), 1.0);
}
void displayTree(FileTree *tree) {
if (tree->children.empty()) { // It is a file
if (ImGui::Selectable(tree->name.c_str(), _state->_fileToDisplay == tree->path)) {
_state->_fileToDisplay = tree->path;
if (tree->name.hasSuffixIgnoreCase(".qda")) {
_state->_qdaToDisplayFrame = 0;
_state->_qdaIsPlaying = false;
_state->_displayMode = kDisplayQDA;
} else if (tree->name.hasSuffixIgnoreCase(".tga")) {
_state->_displayMode = kDisplayTGA;
} else {
_state->_displayMode = -1;
}
}
return;
}
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_DrawLinesFull;
if (ImGui::TreeNodeEx((void*)(intptr_t)(tree->id), base_flags, tree->name.c_str())) {
for (auto &it : tree->children)
displayTree(it);
ImGui::TreePop();
}
}
void showArchives() {
if (!_state->_showArchives)
return;
// Calculate the viewport size
ImVec2 viewportSize = ImGui::GetMainViewport()->Size;
// Calculate the window size
ImVec2 windowSize = ImVec2(
viewportSize.x * 0.9f,
viewportSize.y * 0.9f
);
// Calculate the centered position
ImVec2 centeredPosition = ImVec2(
(viewportSize.x - windowSize.x) * 0.5f,
(viewportSize.y - windowSize.y) * 0.5f
);
// Set the next window position and size
ImGui::SetNextWindowPos(centeredPosition, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Archives", &_state->_showArchives)) {
ImGui::BeginChild("ChildL", ImVec2(ImGui::GetContentRegionAvail().x * 0.4f, ImGui::GetContentRegionAvail().y), ImGuiChildFlags_None);
ImGui::Button(ICON_MS_FILTER_ALT);
ImGui::SameLine();
_state->_nameFilter.Draw();
ImGui::Separator();
if (_state->_files.children.empty())
populateFileList();
displayTree(&_state->_files);
ImGui::EndChild();
ImGui::SameLine();
{ // Right pane
ImGui::BeginChild("ChildR", ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y), ImGuiChildFlags_Borders);
if (_state->_displayMode == kDisplayQDA) {
displayQDA();
} else if (_state->_displayMode == kDisplayTGA) {
displayTGA();
}
ImGui::EndChild();
}
}
ImGui::End();
}
void showSceneObjects() {
if (!_state->_showSceneObjects)
return;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 250), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Scene Objects", &_state->_showSceneObjects)) {
qdGameScene *scene;
qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher();
if (dp && ((scene = dp->get_active_scene()))) {
if (!scene->object_list().empty()) {
for (auto &it : g_engine->_visible_objects) {
if (ImGui::Selectable((char *)transCyrillic(it->name()), _state->_objectToDisplay == it->name())) {
_state->_objectToDisplay = it->name();
}
}
}
}
}
ImGui::End();
}
void showScenePersonages() {
if (!_state->_showScenePersonages)
return;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 250), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Scene Personages", &_state->_showScenePersonages)) {
qdGameScene *scene;
qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher();
if (dp && ((scene = dp->get_active_scene()))) {
if (!scene->getPersonages()->empty()) {
if (ImGui::BeginTable("Personages", 8, ImGuiTableFlags_Borders)) {
ImGuiTableFlags flags = ImGuiTableColumnFlags_WidthFixed;
ImGui::TableSetupColumn("Name", flags);
ImGui::TableSetupColumn("Flags", flags);
ImGui::TableSetupColumn("Control", flags);
ImGui::TableSetupColumn("Movement", flags);
ImGui::TableSetupColumn("Frame", flags);
ImGui::TableSetupColumn("Time", flags);
ImGui::TableSetupColumn("Anim Flags", flags);
ImGui::TableSetupColumn("Anim Status", flags);
ImGui::TableHeadersRow();
for (auto &it : *scene->getPersonages()) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text((char *)transCyrillic(it->name()));
qdGameObjectState *st = it->get_state(it->cur_state());
ImGui::TableNextColumn();
ImGui::Text("%s", st ? qdGameObjectState::flag2str(st->flags(), true, true).c_str() : "<none>");
ImGui::SetItemTooltip("%s", st ? qdGameObjectState::flag2str(st->flags(), true).c_str() : "<none>");
ImGui::TableNextColumn();
ImGui::Text(qdGameObjectMoving::control2str(it->get_control_types(), true).c_str());
ImGui::TableNextColumn();
ImGui::Text(qdGameObjectMoving::movement2str(it->get_movement_mode(), true).c_str());
qdAnimation *anim = it->get_animation();
ImGui::TableNextColumn();
ImGui::Text("%d / %d", anim->get_cur_frame_number(), anim->num_frames());
ImGui::TableNextColumn();
ImGui::Text("%f / %f", anim->cur_time(), anim->length());
ImGui::TableNextColumn();
ImGui::Text(qdAnimation::flag2str(anim->flags(), true, true).c_str());
ImGui::SetItemTooltip(qdAnimation::flag2str(anim->flags(), true).c_str());
ImGui::TableNextColumn();
ImGui::Text(qdAnimation::status2str(anim->status(), true).c_str());
}
ImGui::EndTable();
}
}
}
}
ImGui::End();
}
void onImGuiInit() {
ImGuiIO &io = ImGui::GetIO();
io.Fonts->AddFontDefault();
static const ImWchar cyrillic_ranges[] = {
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x0400, 0x04FF, // Cyrillic
0
};
io.FontDefault = ImGui::addTTFFontFromArchive("LiberationSans-Regular.ttf", 16.0f, nullptr, cyrillic_ranges);;
ImFontConfig icons_config;
icons_config.MergeMode = true;
icons_config.PixelSnapH = false;
icons_config.OversampleH = 3;
icons_config.OversampleV = 3;
icons_config.GlyphOffset = {0, 4};
static const ImWchar icons_ranges[] = {ICON_MIN_MS, ICON_MAX_MS, 0};
ImGui::addTTFFontFromArchive("MaterialSymbolsSharp.ttf", 16.f, &icons_config, icons_ranges);
_state = new ImGuiState();
}
void onImGuiRender() {
if (!debugChannelSet(-1, kDebugImGui)) {
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse;
return;
}
if (!_state)
return;
if (_state->_qdaIsPlaying && (int)g_system->getMillis() > _state->_qdaNextFrameTimestamp) {
_state->_qdaToDisplayFrame++;
_state->_qdaToDisplayFrame %= _state->_qdaToDisplayFrameCount;
_state->_qdaNextFrameTimestamp = g_system->getMillis() + 50; // 20 fps
}
ImGui::GetIO().ConfigFlags &= ~(ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse);
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("View")) {
ImGui::SeparatorText("Windows");
ImGui::MenuItem("Archives", NULL, &_state->_showArchives);
ImGui::MenuItem("Scene Objects", NULL, &_state->_showSceneObjects);
ImGui::MenuItem("Scene Personages", NULL, &_state->_showScenePersonages);
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
showArchives();
showSceneObjects();
showScenePersonages();
}
void onImGuiCleanup() {
delete _state;
_state = nullptr;
}
} // namespace QDEngine

View File

@@ -0,0 +1,31 @@
/* 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 QDENGINE_DEBUGTOOLS_H
#define QDENGINE_DEBUGTOOLS_H
namespace QDEngine {
void onImGuiInit();
void onImGuiRender();
void onImGuiCleanup();
} // namespace QDEngine
#endif // QDENGINE_DEBUGTOOLS_H

View File

@@ -0,0 +1,74 @@
/* 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 QDENGINE_DT_INTERNAL_H
#define QDENGINE_DT_INTERNAL_H
namespace QDEngine {
typedef struct ImGuiImage {
ImTextureID id;
int width;
int height;
} ImGuiImage;
enum {
kDisplayQDA,
kDisplayTGA,
};
struct FileTree {
Common::Path path;
Common::String name;
Common::Array<FileTree *> children;
int id;
FileTree(Common::Path *p, Common::String n, bool node, int i);
FileTree() { id = 0; }
};
typedef struct ImGuiState {
bool _showArchives = false;
bool _showSceneObjects = false;
bool _showScenePersonages = false;
Common::HashMap<Common::String, ImGuiImage> _frames;
Common::Path _fileToDisplay;
Common::String _objectToDisplay;
int _qdaToDisplayFrame = -1;
int _qdaToDisplayFrameCount = 0;
bool _qdaIsPlaying = false;
int _qdaNextFrameTimestamp = 0;
ImGuiTextFilter _nameFilter;
FileTree _files;
int _displayMode = -1;
} ImGuiState;
extern ImGuiState *_state;
}
#endif // QDENGINE_DT_INTERNAL_H

View File

@@ -0,0 +1,80 @@
/* 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 "common/config-manager.h"
#include "common/file.h"
#include "common/md5.h"
#include "common/str-array.h"
#include "common/util.h"
#include "engines/advancedDetector.h"
#include "qdengine/qdengine.h"
#include "qdengine/detection_tables.h"
static const DebugChannelDef debugFlagList[] = {
{ QDEngine::kDebugGraphics, "graphics", "Graphics debug level" },
{ QDEngine::kDebugImGui, "imgui", "Imgui debug output"},
{ QDEngine::kDebugInput, "input", "Enable user input tracing"},
{ QDEngine::kDebugLoad, "load", "Enable load tracing" },
{ QDEngine::kDebugLog, "log", "See log messages"},
{ QDEngine::kDebugMovement, "movement", "Enable movement tracing"},
{ QDEngine::kDebugSave, "save", "Enable save tracing"},
{ QDEngine::kDebugSound, "sound", "Sound debug level"},
{ QDEngine::kDebugTemp, "temp", "Enable temporary tracing" },
{ QDEngine::kDebugQuant, "quant", "Enable quant tracing"},
{ QDEngine::kDebugMinigames, "minigames", "Enable minigames tracing"},
{ QDEngine::kDebugText, "text", "Enable text tracing"},
{ QDEngine::kDebug16BppMode, "16bpp", "Enable 16bpp mode"},
DEBUG_CHANNEL_END
};
class QDEngineMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
public:
QDEngineMetaEngineDetection() : AdvancedMetaEngineDetection(QDEngine::GAME_DESCRIPTIONS, QDEngine::GAME_NAMES) {
_flags = kADFlagMatchFullPaths;
}
~QDEngineMetaEngineDetection() override {}
const char *getName() const override {
return "qdengine";
}
const char *getEngineName() const override {
return "QD Engine";
}
const char *getOriginalCopyright() const override {
return "QD Engine (C) 2003-8 K-D LAB";
}
const DebugChannelDef *getDebugChannels() const override {
return debugFlagList;
}
};
REGISTER_PLUGIN_STATIC(QDENGINE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, QDEngineMetaEngineDetection);

View File

@@ -0,0 +1,199 @@
/* 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/>.
*
*/
namespace QDEngine {
const PlainGameDescriptor GAME_NAMES[] = {
{ "qdengine", "QDEngine game" },
{ "karliknos", "Little Longnose" }, // Карлик Нос
{ "nupogodi3", "Wait for it! Issue 3. Song for a Hare" }, // Ну, погоди! Выпуск 3. Песня для зайца
{ "pilots3", "Pilot Brothers 3: Back Side of the Earth" }, // Братья Пилоты. Обратная сторона Земли
{ "pilots3d", "Pilot Brothers 3D. The Case of Garden Pests" }, // Братья Пилоты 3D. Дело об Огородных вредителях
{ "pilots3d-2", "Pilot Brothers 3D-2. Kennel Club Secrets" }, // Братья Пилоты 3D-2. Тайны Клуба Собаководов
{ "mng", "Mom don't Worry" }, // Мама не горюй
{ "rybalka", "Features of National Fishing" }, // Особенности национальной рыбалки
{ "maski", "Mask Show" }, // Маски-шоу
{ "3mice1", "Marvellous Mice Adventures: Meeting Sea Rat" }, // Три маленькие белые мышки. Визит Морской крысы
{ "shveik", "The Adventures of the Good Soldier Schweik" }, // Похождения бравого солдата Швейка
{ "klepa", "Klepa: Symbolic Rivets" }, // Клёпа: Символические Заклепки
{ "3mice2", "Marvellous Mice Adventures: Sea Rat's Birthday" }, // Три маленькие белые мышки. День рождения морской крысы
{ "dogncat", "Dog-n-cat: In the Footsteps of Unprecedented Beasts" }, // Агентство "КотоПес": По следам невиданных зверей
{ "dogncat2", "Dog-n-cat: Island of Dr Ratiarty" }, // Агентство "КотоПес": Остров доктора Крысарди
{ 0, 0 }
};
#define SUPPORT_STATUS ADGF_NO_FLAGS
#define GAMEelf(id,extra,md5,size,exefile,exemd5,exesize,lang,flags) { \
id, \
nullptr, \
AD_ENTRY2s("qd_game.qml", md5, size, exefile, exemd5, exesize), \
lang, \
Common::kPlatformWindows, \
(SUPPORT_STATUS | ADGF_DROPPLATFORM | flags), \
GUIO1(GUIO_NONE) \
}
#define GAME(id,md5,size,exefile,exemd5,exesize) GAMEelf(id,nullptr,md5,size,exefile,exemd5,exesize,Common::RU_RUS,0)
#define GAMEd(id,md5,size,exefile,exemd5,exesize) GAMEelf(id,nullptr,md5,size,exefile,exemd5,exesize,Common::RU_RUS,ADGF_DEMO)
#define GAMEl(id,md5,size,exefile,exemd5,exesize,lang) GAMEelf(id,nullptr,md5,size,exefile,exemd5,exesize,lang,0)
#define GAMEe(id,extra,md5,size,exefile,exemd5,exesize) GAMEelf(id,extra,md5,size,exefile,exemd5,exesize,Common::RU_RUS,0)
const ADGameDescription GAME_DESCRIPTIONS[] = {
// Карлик Нос
// 2003/10/03. K D-Lab / Melnitsa
GAME("karliknos", "a3f1b86c07bf72f688e7f2b5f20aa7f9", 3225385,
"qd_game.exe", "fcc99749c0ec55d4b112450755ae97b8", 1808636),
// Nykštukas Nosis
// 2004/04/19 Akelote
GAMEl("karliknos", "89077e9322d92b080406d3807f548fe2", 3225327,
"qd_game.exe", "607fa1a3b2c2b7810a5de49b5e7c1521", 917504, Common::LT_LTU),
// Ну, погоди! Выпуск 3. Песня для зайца
// 2003/12/11. K D-Lab
GAME("nupogodi3", "7394a5d28590680cfeb6a037101a9c81", 1675230,
"qd_game.exe", "d5e942e1d588fbd127c812551c0b67ef", 909312),
// Na, palauk! Zuikio dainos
GAMEl("nupogodi3", "3fbcdd27bf0a3defb6195c92b9b0a95f", 1675036,
"qd_game.exe", "18b4260f3f25ac0f394a8c618203dcba", 1855208, Common::LT_LTU),
// Jen počkej a Píseň pro zajíce
GAMEl("nupogodi3", "c0fab62fe6f3a339e96b1dd4a034e40a", 1674743,
"qd_game.exe", "d5e942e1d588fbd127c812551c0b67ef", 909312, Common::CS_CZE),
// No počkaj! 3: Pieseň pre zajaca
//GAMEl("nupogodi3", "???", 1674743,
// "qd_game.exe", "???", 909312, Common::SK_SVK),
// Братья Пилоты. Обратная сторона Земли
// 2004/06/11. K D-Lab / Pipe Studio
// GOG release is NOT on this engine
GAME("pilots3", "33dfc61046e5af85b570eda24e0afe6d", 14452732,
"bp4.exe", "fd5bcdcc1fc16c78aa51d67e550cc674", 950272),
// Особенности национальной рыбалки
// 2004/09/15. Melnitsa / Lazy Games
GAME("rybalka", "4113d7f0f67cf9563f4c62f999898426", 16892191,
"onr.exe", "30e87b2fa28bab268e0a98e0898ef09c", 745472),
// Братья Пилоты 3D. Дело об Огородных вредителях
// 2004/10/22. K D-Lab
GAME("pilots3d", "c836992c240990f199947e8a362ea867", 5741533,
"qd_game.exe", "34684d88c8be61b60b2b6707e49b2ba0", 733184),
// Братья Пилоты 3D-2. Тайны Клуба Собаководов
// 2005/04/29. K D-Lab
GAMEe("pilots3d-2", "Part I", "7f9eeee513eadbd0f2431bca880df1d1", 4266775,
"qd_game.exe", "708813f2e8b77f62385f558dfc333abe", 753664),
GAMEe("pilots3d-2", "Part II", "dbf676d0d9f4f8d968352918e7ecaffe", 9689557,
"qd_game.exe", "708813f2e8b77f62385f558dfc333abe", 753664),
// Мама не горюй
// 2005/08/05. Melnitsa / Lazy Games
GAME("mng", "9a1b9134f914f22682fbc0604f4eed81", 20704192,
"mama.exe", "233ac221814568e5c278f952e76495ce", 757760),
GAMEd("mng", "da3a6e591d4896ca3176c5866aef278f", 2541094,
"qd_game.exe", "233ac221814568e5c278f952e76495ce", 757760),
// Маски-шоу
// 2005/12/16. Lazy Games
GAME("maski", "9a40b7491cac0dd80657cfe52e28ea74", 23128230,
"maski.exe", "1b7a4076bf1ed15e3eb642caeb337337", 761856),
// Три маленькие белые мышки и пираты северного моря
GAMEd("3mice1", "e6ad21f2f3241116b0f66a1d98f8e3f3", 403092,
"qd_game.exe", "da2dc5265cb7c55bcf1b24cd9deae9d1", 761856),
// Три маленькие белые мышки. Визит Морской крысы
// 2007/03/01. Lazy Games
GAME("3mice1", "63e79178e66c520a9094622ccdcaf9c5", 10006622,
"qd_game.exe", "b8b3545b022f8e0975a8a948c03ad76e", 917504),
// Příběhy myší rodinky I
GAMEl("3mice1", "a6060f3d17ea2e50a03216332e517817", 10022470,
"qd_game.exe", "b8b3545b022f8e0975a8a948c03ad76e", 917504, Common::CS_CZE),
// Były Sobie Myszki Trzy: Na Spotkanie Cioci Myszy
GAMEl("3mice1", "6fe8feb6cf76f4642f6d6cb612b1d446", 10012908,
"qd_game.exe", "b8b3545b022f8e0975a8a948c03ad76e", 917504, Common::PL_POL),
// Похождения бравого солдата Швейка
// 2007/09/07. Lazy Games
GAME("shveik", "3877afbb780996a5608a5b358dd59726", 30233418,
"shveik.exe", "a56cb058b46e47754019652d27d974b3", 962560),
// Клёпа: Символические Заклепки
// 2007/10/19. K-D Logic
GAME("klepa", "a09e1f072942d88c06abccfb820f46a9", 20260975,
"qd_game.exe", "a56cb058b46e47754019652d27d974b3", 962560),
// Три маленькие белые мышки. День рождения морской крысы
// 2007/12/27. Lazy Games
GAME("3mice2", "93d8311ff9c00453f25192743c9e98d9", 8176962,
"qd_game.exe", "ffe20c2dbb131b01fccc1211a41e76e7", 962560),
// Příběhy myší rodinky II
//GAMEl("3mice2", "???", 8176962, Common::CZ_CZE),
GAMEd("3mice2", "dfd98feb2e7d3345a7babdeb3ed3e9a7", 800666, // Demo1
"demo1.exe", "ffe20c2dbb131b01fccc1211a41e76e7", 962560),
// Były Sobie Myszki Trzy: Urodzinowe Śledztwo
GAMEl("3mice2", "9128a0d801e547cb651c5fc7e09bee04", 8182142,
"qd_game.exe", "ffe20c2dbb131b01fccc1211a41e76e7", 962560, Common::PL_POL),
{ // Demo2, original
// Video is in MP4 format which is not supported
"3mice2",
"Original",
AD_ENTRY3s("qd_game.qml", "6af4c6f11cf0994670bedb78efe22267", 1124576, // Demo2
"demo2.exe", "ffe20c2dbb131b01fccc1211a41e76e7", 962560,
"Resource/Video/martha.mpg", "02850c5fc074eba22b368cca0ff57c98", 9810104),
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_UNSTABLE | ADGF_DROPPLATFORM | ADGF_DEMO | GF_BROKEN_VIDEOS,
GUIO1(GUIO_NONE)
},
{ // Demo2, recoded
// Video is recoded with: ffmpeg -i martha.mpg -b:v 6000k -maxrate:v 9000k martha-new.mpeg
// The full game has this video also broken: the video frames get frozen at the last several seconds
"3mice2",
"Reencoded video",
AD_ENTRY3s("qd_game.qml", "6af4c6f11cf0994670bedb78efe22267", 1124576,
"demo2.exe", "ffe20c2dbb131b01fccc1211a41e76e7", 962560,
"Resource/Video/martha.mpg", "4dc93c37c0cdd75c01c58412f68e4874", 32499712),
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_DROPPLATFORM | ADGF_DEMO,
GUIO1(GUIO_NONE)
},
// Агентство "КотоПес": По следам невиданных зверей
// 2008/03/21 KD Vision Games
GAME("dogncat", "db4e0081fdaf575e82910cf7399cef62", 17759363,
"qd_game.exe", "ed659f0fc79e772f1f1ff8107fa94dea", 962560),
// Агентство "КотоПес": Остров доктора Крысарди
// 2008/09/19 KD Vision Games
GAME("dogncat2", "c250f79a8e404b13a588e6a03e3a6d20", 10483617,
"qd_game.exe", "ed659f0fc79e772f1f1ff8107fa94dea", 962560),
AD_TABLE_END_MARKER
};
} // namespace Qdengine

View 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 "common/translation.h"
#include "gui/ThemeEval.h"
#include "qdengine/dialogs.h"
namespace QDEngine {
QdOptionsWidget::QdOptionsWidget(GuiObject* boss, const Common::String& name, const Common::String& domain) : OptionsContainerWidget(boss, name, "QdGameOptionsDialog", domain),
_16bppModeCheckbox(nullptr) {
_16bppModeCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "QdGameOptionsDialog.16bppMode", _("Enable 16 bits per pixel mode"), _("Enable this if backend does not support 32bpp and/or to debug graphics"));
}
QdOptionsWidget::~QdOptionsWidget() {
}
void QdOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const {
layouts.addDialog(layoutName, overlayedLayout)
.addLayout(GUI::ThemeLayout::kLayoutVertical)
.addPadding(0, 0, 0, 0)
.addWidget("16bppMode", "Checkbox")
.closeLayout()
.closeDialog();
}
void QdOptionsWidget::load() {
if (_16bppModeCheckbox)
_16bppModeCheckbox->setState(ConfMan.getBool("16bpp"));
}
bool QdOptionsWidget::save() {
if (_16bppModeCheckbox)
ConfMan.setBool("16bpp", _16bppModeCheckbox->getState());
return true;
}
} // End of namespace QDEngine

View 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 QDENGINE_DIALOGS_H
#define QDENGINE_DIALOGS_H
#include "gui/dialog.h"
#include "gui/widget.h"
namespace QDEngine {
class QdOptionsWidget : public GUI::OptionsContainerWidget {
public:
QdOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain);
~QdOptionsWidget() override;
void load() override;
bool save() override;
private:
void defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const override;
GUI::CheckboxWidget *_16bppModeCheckbox;
};
} // End of namespace QDEngine
#endif

View 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/>.
*
*/
#include "qdengine/dialogs.h"
#include "qdengine/metaengine.h"
#include "qdengine/qdengine.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
const char *QDEngineMetaEngine::getName() const {
return "qdengine";
}
Common::Error QDEngineMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
*engine = new QDEngine::QDEngineEngine(syst, desc);
return Common::kNoError;
}
GUI::OptionsContainerWidget *QDEngineMetaEngine::buildEngineOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const {
return new QDEngine::QdOptionsWidget(boss, name, target);
}
bool QDEngineMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSavesUseExtendedFormat) ||
(f == kSimpleSavesNames) ||
(f == kSupportsListSaves) ||
(f == kSupportsDeleteSave) ||
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSupportsLoadingDuringStartup);
}
void QDEngineMetaEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
QDEngine::qdGameDispatcher *dp = QDEngine::qdGameDispatcher::get_dispatcher();
if (dp)
dp->game_screenshot(thumb);
}
#if PLUGIN_ENABLED_DYNAMIC(QDENGINE)
REGISTER_PLUGIN_DYNAMIC(QDENGINE, PLUGIN_TYPE_ENGINE, QDEngineMetaEngine);
#else
REGISTER_PLUGIN_STATIC(QDENGINE, PLUGIN_TYPE_ENGINE, QDEngineMetaEngine);
#endif

View 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 QDENGINE_METAENGINE_H
#define QDENGINE_METAENGINE_H
#include "engines/advancedDetector.h"
class QDEngineMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
GUI::OptionsContainerWidget *buildEngineOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
/**
* Determine whether the engine supports the specified MetaEngine feature.
*
* Used by e.g. the launcher to determine whether to enable the Load button.
*/
bool hasFeature(MetaEngineFeature f) const override;
virtual void getSavegameThumbnail(Graphics::Surface &thumb) override;
};
#endif // QDENGINE_METAENGINE_H

View File

@@ -0,0 +1,191 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_BABOCHKA_H
#define QDENGINE_MINIGAMES_3MICE2_BABOCHKA_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2BabochkaMiniGame : public qdMiniGameInterface {
public:
qd3mice2BabochkaMiniGame() {}
~qd3mice2BabochkaMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2Babochka::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
for (int i = 1; i <= 25; i++)
_objects[i] = _scene->object_interface(Common::String::format("object@%i#", i).c_str());
for (int i = 1; i <= 25; i++)
_objects[26 + i] = _scene->object_interface(Common::String::format("inv_object@%i#", i).c_str());
_objDone = _scene->object_interface("$done");
_timePassed = 0.0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2Babochka::quant(%f)", dt);
_timePassed += dt;
qdMinigameObjectInterface *obj = _scene->mouse_click_object_interface();
if (obj) {
const char *name = obj->name();
if (strstr(name, "object@") && obj->is_state_active("base") && !_scene->mouse_object_interface()) {
obj->set_state("hide");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "to_inv: num is: %d for name: '%s'", num, name);
_objects[num + 26]->set_state("to_inv");
}
_scene->release_object_interface(obj);
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)) {
obj = _scene->mouse_object_interface();
if (obj) {
const char *name = obj->name();
obj->set_state("del");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "base: num is: %d for name: '%s'", num, name);
_objects[num]->set_state("base");
_scene->release_object_interface(obj);
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)) {
obj = _scene->mouse_object_interface();
if (obj) {
qdMinigameObjectInterface *obj2 = _scene->mouse_hover_object_interface();
if (obj2) {
const char *name = obj->name();
if (strstr(name, "@") && strstr(obj2->name(), "@")) {
int num = getObjNum(name);
debugC(2, kDebugMinigames, "part1: num is: %d for name: '%s'", num, name);
name = obj2->name();
int num2 = getObjNum(name);
debugC(2, kDebugMinigames, "part2: num2 is: %d for name: '%s'", num2, name);
if (num == num2) {
obj->set_state("del");
_objects[num]->set_state("babochka");
}
_scene->release_object_interface(obj);
}
}
}
}
if (_timePassed > 1.0) {
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
_timePassed = 0.0;
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2Babochka::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
for (int i = 1; i <= 25; i++)
if (!_objects[i]->is_state_active("babochka"))
return false;
return true;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_objects[52] = { nullptr };
qdMinigameObjectInterface *_objDone = nullptr;
float _timePassed = 0.0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_BABOCHKA_H

View File

@@ -0,0 +1,208 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_KOVRIK_H
#define QDENGINE_MINIGAMES_3MICE2_KOVRIK_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2KovrikMiniGame : public qdMiniGameInterface {
public:
qd3mice2KovrikMiniGame() {}
~qd3mice2KovrikMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2Kovrik::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
for (int i = 1; i <= 41; i++)
_objects[i] = _scene->object_interface(Common::String::format("object@%i#", i).c_str());
for (int i = 1; i <= 41; i++)
_objects[42 + i] = _scene->object_interface(Common::String::format("inv_object@%i#", i).c_str());
_objDone = _scene->object_interface("$done");
_objSound = _scene->object_interface("$sound");
_timePassed = 0.0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2Kovrik::quant(%f)", dt);
_timePassed += dt;
qdMinigameObjectInterface *obj = _scene->mouse_click_object_interface();
if (obj) {
const char *name = obj->name();
if (strstr(name, "object@") && obj->is_state_active("base") && !_scene->mouse_object_interface()) {
obj->set_state("hide");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "to_inv: num is: %d for name: '%s'", num, name);
_objects[num + 42]->set_state("to_inv");
}
_scene->release_object_interface(obj);
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)) {
obj = _scene->mouse_object_interface();
if (obj) {
const char *name = obj->name();
obj->set_state("del");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "base: num is: %d for name: '%s'", num, name);
_objects[num]->set_state("base");
_scene->release_object_interface(obj);
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)) {
obj = _scene->mouse_object_interface();
if (obj) {
qdMinigameObjectInterface *obj2 = _scene->mouse_hover_object_interface();
if (obj2) {
const char *name = obj->name();
if (strstr(name, "@") && strstr(obj2->name(), "@")) {
int num = getObjNum(name);
debugC(2, kDebugMinigames, "part1: num is: %d for name: '%s'", num, name);
name = obj2->name();
int num2 = getObjNum(name);
debugC(2, kDebugMinigames, "part2: num2 is: %d for name: '%s'", num2, name);
if (num == num2) {
obj->set_state("del");
_objects[num]->set_state("kovrik");
}
if ((num2 == 29 && num == 31) ||
(num2 == 31 && num == 29) ||
(num2 == 26 && (num == 31 || num == 29)) ||
(num2 == 3 && num == 4) ||
(num2 == 22 && num == 21) ||
(num2 == 1 && num == 2) ||
(num2 == 37 && (num == 35 || num == 32 || num == 34 || num == 38))) {
obj->set_state("del");
_objects[num]->set_state("kovrik");
}
_scene->release_object_interface(obj);
}
if (_objSound->is_state_active("\xed\xe5\xf2") // "нет"
|| _objSound->is_state_active("\xed\xe5\xf2\x31")) // "нет1"
_objSound->set_state("\xe4\xe0"); // "да"
}
}
}
if (_timePassed > 1.0) {
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
_timePassed = 0.0;
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2Kovrik::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
for (int i = 1; i <= 41; i++)
if (!_objects[i]->is_state_active("kovrik"))
return false;
return true;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_objects[84] = { nullptr };
qdMinigameObjectInterface *_objDone = nullptr;
qdMinigameObjectInterface *_objSound = nullptr;
float _timePassed = 0.0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_KOVRIK_H

View File

@@ -0,0 +1,286 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_PLATE_H
#define QDENGINE_MINIGAMES_3MICE2_PLATE_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2PlateMiniGame : public qdMiniGameInterface {
public:
qd3mice2PlateMiniGame() {}
~qd3mice2PlateMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2Plate::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
for (int i = 1; i <= 5; i++) {
_figures[i] = _scene->object_interface(Common::String::format("object@%i#", i).c_str());
_figures[i + 5] = _scene->object_interface(Common::String::format("inv_object@%i#", i).c_str());
}
_objDone = _scene->object_interface("$done");
_objZoneTarget = _scene->object_interface("zone_target");
_objZoneFull = _scene->object_interface("zone_full");
_objFading = _scene->object_interface("\xE7\xE0\xF2\xE5\xEC\xED\xE5\xED\xE8\xE5"); // "затемнение"
_objHasStarted = _scene->object_interface("$\xE7\xE0\xEF\xF3\xF1\xEA \xE1\xFB\xEB"); // "$запуск был"
_initialCoords[1] = 54;
_initialCoords[2] = 99;
_initialCoords[3] = 693;
_initialCoords[4] = 673;
_initialCoords[5] = 706;
_initialCoords[7] = 452;
_initialCoords[8] = 98;
_initialCoords[9] = 436;
_initialCoords[10] = 93;
_initialCoords[11] = 254;
mgVect2i pos;
if (_objHasStarted->is_state_active("\xed\xe5\xf2")) { // "нет"
for (int i = 0; i < 5; i++) {
pos.x = _initialCoords[i + 1];
pos.y = _initialCoords[i + 7];
_figures[i + 1]->set_R(_scene->screen2world_coords(pos, 0.0));
}
_zoneDepth = -100;
_objHasStarted->set_state("\xe4\xe0"); // "да"
} else {
float depth = 0.0;
for (int i = 0; i < 5; i++) {
if (_scene->screen_depth(_figures[i + 1]->R()) < depth)
depth = _scene->screen_depth(_figures[i + 1]->R());
}
_zoneDepth = depth - 100;
}
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2Plate::quant(%f)", dt);
qdMinigameObjectInterface *mouseObj = _scene->mouse_object_interface();
qdMinigameObjectInterface *clickObj = _scene->mouse_click_object_interface();
qdMinigameObjectInterface *hoverObj = _scene->mouse_hover_object_interface();
const char *name;
if (clickObj && !mouseObj) {
name = clickObj->name();
if (strstr(name, "object@") && clickObj->is_state_active("base")) {
int num = getObjNum(name);
clickObj->set_state("hide");
debugC(2, kDebugMinigames, "to_inv: num is: %d for name: '%s'", num, name);
_figures[num + 5]->set_state("to_inv");
_objZoneFull->set_state("\xD4\xEE\xED - \xEC\xE0\xF1\xEA\xE0"); // "Фон - маска"
_objZoneFull->set_R(_scene->screen2world_coords(_objZoneFull->screen_R(), _zoneDepth - 500));
_objZoneTarget->set_R(_scene->screen2world_coords(_objZoneTarget->screen_R(), _zoneDepth - 1500));
_objFading->set_R(_scene->screen2world_coords(_objFading->screen_R(), _zoneDepth - 3500));
} else if (!strcmp(name, "zone_target")) {
int minDepth = 32768.0;
int num = -1;
for (int i = 0; i < 5; i++) {
float depth = _scene->screen_depth(_figures[i + 1]->R());
if (depth < minDepth && _figures[i + 1]->is_state_active("plate")) {
minDepth = depth;
num = i + 1;
}
}
debugC(2, kDebugMinigames, "zone_target: num is: %d", num);
if (num > -1) {
_figures[num]->set_state("hide");
_figures[num + 5]->set_state("to_inv");
_objZoneFull->set_state("\xD4\xEE\xED - \xEC\xE0\xF1\xEA\xE0"); // "Фон - маска"
_objZoneFull->set_R(_scene->screen2world_coords(_objZoneFull->screen_R(), _zoneDepth - 1500));
_objZoneTarget->set_R(_scene->screen2world_coords(_objZoneTarget->screen_R(), _zoneDepth - 2500));
}
}
_objFading->set_R(_scene->screen2world_coords(_objFading->screen_R(), _zoneDepth - 3500));
_scene->release_object_interface(clickObj);
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN) && mouseObj) {
name = mouseObj->name();
int num = getObjNum(name);
debugC(2, kDebugMinigames, "base: num is: %d for name: '%s'", num, name);
mouseObj->set_state("del");
_figures[num]->set_state("base");
mgVect2i pos;
pos.x = _initialCoords[num];
pos.y = _initialCoords[num + 6];
_figures[num]->set_R(_scene->screen2world_coords(pos, 0));
_scene->release_object_interface(mouseObj);
_objZoneFull->set_state("no");
_objFading->set_R(_scene->screen2world_coords(_objFading->screen_R(), _zoneDepth - 3500));
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN) && mouseObj && hoverObj) {
name = mouseObj->name();
int num = getObjNum(name);
debugC(2, kDebugMinigames, "plate: num is: %d for name: '%s'", num, name);
if (!strcmp(hoverObj->name(), "zone_target")) {
mouseObj->set_state("del");
_figures[num]->set_state("plate");
_figures[num]->set_R(_scene->screen2world_coords(mgVect2i(400, 300), _zoneDepth));
_zoneDepth -= 500;
} else if (!strcmp(hoverObj->name(), "zone_full")) {
mouseObj->set_state("del");
_figures[num]->set_state("base");
mgVect2i pos;
pos.x = _initialCoords[num];
pos.y = _initialCoords[num + 6];
_figures[num]->set_R(_scene->screen2world_coords(pos, 0));
}
_objFading->set_R(_scene->screen2world_coords(_objFading->screen_R(), _zoneDepth - 3500));
_scene->release_object_interface(mouseObj);
_objZoneFull->set_state("no");
}
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
else
_objDone->set_state("\xed\xe5\xf2"); // "нет"
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2Plate::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
for (int i = 0; i < 5; i++) {
if (!_figures[i + 1]->is_state_active("plate"))
return false;
if (i == 4)
break;
if (_scene->screen_depth(_figures[i + 1]->R()) < _scene->screen_depth(_figures[i + 2]->R()))
return false;
}
return true;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_figures[12] = { nullptr };
qdMinigameObjectInterface *_objDone = nullptr;
qdMinigameObjectInterface *_objZoneTarget = nullptr;
qdMinigameObjectInterface *_objZoneFull = nullptr;
qdMinigameObjectInterface *_objFading = nullptr;
qdMinigameObjectInterface *_objHasStarted = nullptr;
int _initialCoords[12] = { 0 };
int _zoneDepth = 0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_PLATE_H

View File

@@ -0,0 +1,361 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_RASKR_ALL_H
#define QDENGINE_MINIGAMES_3MICE2_RASKR_ALL_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
const int zoneCountInit1[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 64, 89, 90, 91,
92, 93, 94, 96, 97, 98, 99, 129, 130, 132, 134, 135, 136, 138, 139, 140, 141,
142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 157, 158,
159, 160, 161, 162, 163, 164, 166, 167, 170, 172, 173, 174, 178, 179, 180, 182,
184, 185, 186, 187, 190, 192, 196, 197, 198, 199, 204, 205, 211, 212, 213, 214,
216, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 229, 230, 231, 232, 234,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 254, 255, 260, 261, 263,
265, 267, 268, 271, 272, 273, 274, 280, 283, 284, 287, 288, 289, 290, 292, 294,
296, 308, 309, 0
};
const int colorRegions1[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 89, 308, 309, 311, 0,
64, 65, 0,
90, 91, 92, 190, 207, 0,
93, 94, 95, 0,
96, 97, 98, 99, 103, 0,
129, 132, 133, 0,
130, 131, 0,
134, 135, 136, 137, 0,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 0,
153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 0,
166, 167, 194, 0,
170, 171, 0,
172, 173, 174, 175, 0,
178, 179, 180, 182, 184, 185, 186, 187, 229, 230, 231, 232, 233, 0,
192, 282, 0,
196, 208, 0,
197, 198, 199, 200, 0,
204, 205, 206, 0,
211, 212, 213, 214, 215, 0,
216, 217, 218, 219, 220, 221, 222, 223, 224, 0,
225, 226, 227, 228, 0,
234, 235, 0,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 0,
254, 255, 256, 0,
260, 261, 262, 0,
263, 264, 0,
265, 266, 0,
267, 268, 269, 0,
271, 272, 273, 274, 275, 0,
280, 281, 0,
283, 306, 0,
284, 287, 288, 289, 290, 307, 0,
292, 293, 0,
294, 295, 0,
296, 297, 0,
0,
};
const int zoneCountInit2[] = {
1, 2, 3, 4, 5, 6, 8, 16, 17, 18, 37, 46, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 66, 69, 70, 71, 72, 73, 74, 75, 76, 78, 80, 81,
82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 102, 106, 107, 108, 109, 111, 113, 114, 115, 116, 117, 118, 119, 121,
124, 126, 128, 130, 131, 132, 143, 146, 154, 156, 157, 191, 192, 193, 194,
195, 205, 0,
};
int colorRegions2[] = {
1, 2, 3, 4, 5, 55, 56, 57, 58, 59, 60, 93, 94, 95, 96, 97, 98, 99, 100, 101, 134, 0,
6, 7, 0,
8, 9, 0,
16, 17, 18, 19, 0,
37, 38, 0,
46, 47, 0,
48, 49, 50, 51, 52, 53, 54, 102, 103, 0,
61, 68, 0,
66, 67, 0,
69, 70, 71, 72, 73, 74, 75, 76, 81, 152, 0,
78, 79, 0,
80, 85, 86, 87, 88, 89, 90, 91, 92, 141, 0,
82, 83, 84, 0,
106, 107, 108, 109, 110, 0,
111, 112, 0,
113, 114, 115, 116, 117, 118, 119, 120, 0,
121, 122, 0,
124, 125, 0,
126, 127, 0,
128, 129, 0,
130, 131, 132, 133, 0,
143, 144, 0,
146, 147, 0,
154, 155, 0,
156, 159, 0,
157, 158, 0,
191, 192, 193, 194, 195, 196, 0,
205, 206, 0,
0,
};
const int zoneCountInit3[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 189, 190, -1
};
const int colorRegions3[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0,
190, 191, 192, 0,
0,
};
const int zoneCountInit4[] = {
0
};
const int colorRegions4[] = {
0,
0,
};
class qd3mice2RaskrAllMiniGame : public qdMiniGameInterface {
public:
qd3mice2RaskrAllMiniGame(int gameNum) : _gameNum(gameNum) {}
~qd3mice2RaskrAllMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2RaskrAll::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
const int *zoneCountInit = nullptr;
int zoneCountDelta = 0;
if (_gameNum == 1) {
_numZones = 311;
_colorRegions = colorRegions1;
_colorRegionsSize = ARRAYSIZE(colorRegions1);
_neededColors = 50;
zoneCountInit = zoneCountInit1;
zoneCountDelta = 0;
} else if (_gameNum == 2) {
_numZones = 206;
_colorRegions = colorRegions2;
_colorRegionsSize = ARRAYSIZE(colorRegions2);
_neededColors = 50;
zoneCountInit = zoneCountInit2;
zoneCountDelta = 0;
} else if (_gameNum == 3) {
_numZones = 265;
_colorRegions = colorRegions3;
_colorRegionsSize = ARRAYSIZE(colorRegions3);
_neededColors = 70;
zoneCountInit = zoneCountInit3;
zoneCountDelta = 1;
} else if (_gameNum == 4) {
_numZones = 133;
_colorRegions = colorRegions4;
_colorRegionsSize = ARRAYSIZE(colorRegions4);
_neededColors = 50;
zoneCountInit = zoneCountInit4;
zoneCountDelta = 0;
} else {
error("qd3mice2RaskrAllMiniGame::init(): Unsupported gameNumber: %d", _gameNum);
}
for (int i = 1; i <= _numZones; i++) {
_zones[i] = _scene->object_interface(Common::String::format("zone@%i#", i).c_str());
_zoneCount[i] = true;
}
for (int i = 0; zoneCountInit[i] + zoneCountDelta != 0; i++)
_zoneCount[zoneCountInit[i] + zoneCountDelta] = false;
_objColor = _scene->object_interface("$color");
_objColorSel = _scene->object_interface("$color_sel");
_objLoaded = _scene->object_interface("$loaded");
_objDone = _scene->object_interface("$done");
if (_objLoaded->is_state_active("no")) {
for (int i = 1; i <= _numZones; i++)
_zones[i]->set_shadow(0xFEFEFF, 0);
_objColorSel->set_state("!\xEC\xE0\xF1\xEA\xE0"); // "!маска"
_objColor->set_shadow(0xFEFEFE, 0);
_objLoaded->set_state("yes");
}
_timePassed = 0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2RaskrAll::quant(%f)", dt);
_timePassed += dt;
if (_timePassed > 0.5) {
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
_timePassed = 0.0;
}
qdMinigameObjectInterface *mouseObj = _scene->mouse_click_object_interface();
if (!mouseObj)
return true;
const char *name = mouseObj->name();
if (strstr(name, "@color@")) {
_objColor->set_shadow(mouseObj->shadow_color(), mouseObj->shadow_alpha());
Common::String color;
for (int i = 8; name[i] != '#'; i++)
color += name[i];
_objColorSel->set_state(color.c_str());
} else {
if (strstr(name, "zone@")) {
int num = getObjNum(name);
int start = 0;
for (int i = 0; i < _colorRegionsSize; i++) {
if (_colorRegions[i] == 0) {
start = i + 1;
continue;
}
if (_colorRegions[i] == num)
break;
}
debugC(2, kDebugMinigames, "zone: %d", num);
if (start < _colorRegionsSize) {
for (int i = start; _colorRegions[i] != 0; i++)
_zones[_colorRegions[i]]->set_shadow(_objColor->shadow_color(), _objColor->shadow_alpha());
} else {
_zones[num]->set_shadow(_objColor->shadow_color(), _objColor->shadow_alpha());
}
}
}
_scene->release_object_interface(mouseObj);
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2RaskrAll::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
int count = 0;
for (int i = 1; i <= _numZones; i++) {
if (_zones[i]->shadow_color() != 0)
if (_zoneCount[i])
count++;
}
debugC(2, kDebugMinigames, "Solution count: %d zone234: %06x", count, _zones[234]->shadow_color());
return count > _neededColors;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_zones[312] = { nullptr };
qdMinigameObjectInterface *_objColor = nullptr;
qdMinigameObjectInterface *_objColorSel = nullptr;
qdMinigameObjectInterface *_objLoaded = nullptr;
qdMinigameObjectInterface *_objDone = nullptr;
bool _zoneCount[312] = { false };
int _numZones = 0;
float _timePassed = 0;
int _gameNum = 0;
const int *_colorRegions = nullptr;
int _colorRegionsSize = 0;
int _neededColors = 0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_RASKR_ALL_H

View File

@@ -0,0 +1,195 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_SBOR_KARTY_H
#define QDENGINE_MINIGAMES_3MICE2_SBOR_KARTY_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2SborKartyMiniGame : public qdMiniGameInterface {
public:
qd3mice2SborKartyMiniGame() {}
~qd3mice2SborKartyMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2SborKarty::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
for (int i = 1; i <= 10; i++)
_objects[i] = _scene->object_interface(Common::String::format("object@%i#", i).c_str());
for (int i = 1; i <= 10; i++)
_objects[11 + i] = _scene->object_interface(Common::String::format("inv_object@%i#", i).c_str());
_objDone = _scene->object_interface("$done");
_objDrop = _scene->object_interface("$\xf1\xe1\xf0\xee\xf1\xe8\xf2\xfc\x20\xf1\x20\xec\xfb\xf8\xe8"); // "$сбросить с мыши"
_timePassed = 0.0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2SborKarty::quant(%f)", dt);
_timePassed += dt;
qdMinigameObjectInterface *obj = _scene->mouse_click_object_interface();
if (obj) {
const char *name = obj->name();
if (strstr(name, "object@") && obj->is_state_active("base") && !_scene->mouse_object_interface()) {
obj->set_state("hide");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "to_inv: num is: %d for name: '%s'", num, name);
_objects[num + 11]->set_state("to_inv");
}
_scene->release_object_interface(obj);
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN) || !_objDrop->is_state_active("\xed\xe5\xf2")) { // "нет"
obj = _scene->mouse_object_interface();
if (obj) {
const char *name = obj->name();
obj->set_state("del");
int num = getObjNum(name);
debugC(4, kDebugMinigames, "base: num is: %d for name: '%s'", num, name);
_objects[num]->set_state("base");
_objDrop->set_state("\xed\xe5\xf2"); // "нет"
_scene->release_object_interface(obj);
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)) {
obj = _scene->mouse_object_interface();
if (obj) {
qdMinigameObjectInterface *obj2 = _scene->mouse_hover_object_interface();
if (obj2) {
const char *name = obj->name();
if (strstr(name, "@")) {
int num = getObjNum(name);
debugC(4, kDebugMinigames, "part1: num is: %d for name: '%s'", num, name);
name = obj2->name();
int num2 = getObjNum(name);
debugC(4, kDebugMinigames, "part2: num2 is: %d for name: '%s'", num2, name);
if (num == num2) {
obj->set_state("del");
_objects[num]->set_state("karta");
}
_scene->release_object_interface(obj);
}
}
}
}
if (_timePassed > 1.0) {
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
_timePassed = 0.0;
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2SborKarty::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
for (int i = 1; i <= 10; i++)
if (!_objects[i]->is_state_active("kovrik"))
return false;
return true;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_objects[22] = { nullptr };
qdMinigameObjectInterface *_objDone = nullptr;
qdMinigameObjectInterface *_objDrop = nullptr;
float _timePassed = 0.0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_SBOR_KARTY_H

View File

@@ -0,0 +1,401 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_STATES_H
#define QDENGINE_MINIGAMES_3MICE2_STATES_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2StatesMiniGame : public qdMiniGameInterface {
public:
qd3mice2StatesMiniGame() {}
~qd3mice2StatesMiniGame() {}
#define MASK1 "\xec\xe0\xf1\xea\xe0\x31" // "маска1"
#define MASK2 "\xec\xe0\xf1\xea\xe0\x32" // "маска2"
#define MASK3 "\xec\xe0\xf1\xea\xe0\x33" // "маска3"
#define MASK4 "\xec\xe0\xf1\xea\xe0\x34" // "маска4"
#define MAIN "\xee\xf1\xed\xee\xe2\xed\xee\xe9" // "основной"
#define SET1 "\xed\xe0\xe1\xee\xf0\x31" // "набор1"
#define SET2 "\xed\xe0\xe1\xee\xf0\x32" // "набор2"
#define SET3 "\xed\xe0\xe1\xee\xf0\x33" // "набор3
#define SET4 "\xed\xe0\xe1\xee\xf0\x34" // "набор4"
#define SET5 "\xed\xe0\xe1\xee\xf0\x35" // "набор5"
#define SET6 "\xed\xe0\xe1\xee\xf0\x36" // "набор6"
#define SET7 "\xed\xe0\xe1\xee\xf0\x37" // "набор7"
#define SET8 "\xed\xe0\xe1\xee\xf0\x38" // "набор8"
#define BG_MASK "\xd4\xee\xed\x20\x2d\x20\xec\xe0\xf1\xea\xe0" // "Фон - маска"
#define BG_MASK1 "\xd4\xee\xed\x20\x2d\x20\xec\xe0\xf1\xea\xe0\x31" // "Фон - маска1"
#define BG_MASK2 "\xd4\xee\xed\x20\x2d\x20\xec\xe0\xf1\xea\xe0\x32" // "Фон - маска2"
#define BG_FRONT_LEFT "\xf4\xee\xed front \xeb\xe5\xe2\xee" // "фон front лево"
#define BG_FRONT_RIGHT "\xf4\xee\xed front \xef\xf0\xe0\xe2\xee" // "фон front право"
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2States::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_objScene = _scene->object_interface("$\xF1\xF6\xE5\xED\xE0"); // "$сцена"
_objSelectedSet = _scene->object_interface("$select_nabor");
_objects[1] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый открыт"
_objects[2] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый закрыт"
_objects[3] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик правый открыт"
_objects[4] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик левый открыт"
_objects[5] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый закрыт"
_objects[6] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый открыт"
_objects[7] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xEB\xE5\xE2\xEE \xF1\xEA\xE0\xEB\xEA\xE0"); // "накладка front лево скалка"
_objects[8] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xEB\xE5\xE2\xEE \xEF\xE0\xEB\xEE\xF7\xEA\xE8"); // "накладка front лево палочки"
_objects[9] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xE3\xE8\xF0\xE8 \xE2 \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xEE\xEC \xFF\xF9\xE8\xEA\xE5"); // "_МАСКА front гири в центральном ящике"
_objects[10] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[11] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xE3\xE8\xF0\xE8"); // "накладка front гири"
_objects[12] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[13] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[14] = _scene->object_interface(BG_FRONT_RIGHT);
_objects[15] = _scene->object_interface(BG_FRONT_LEFT);
_objects[16] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEF\xF0\xE0\xE2\xEE \xEA front"); // "_МАСКА front право к front"
_objects[17] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEB\xE5\xE2\xEE \xEA front"); // "_МАСКА front лево к front"
_objects[18] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[19] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[20] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[21] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[22] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xE3\xE8\xF0\xE8"); // "накладка front гири"
_objects[23] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[24] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xE3\xE8\xF0\xE8 \xE2 \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xEE\xEC \xFF\xF9\xE8\xEA\xE5"); // "_МАСКА front гири в центральном ящике"
_objects[25] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый закрыт"
_objects[26] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[27] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[28] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[29] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[30] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[31] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEB\xE5\xE2\xEE \xEA front"); // "_МАСКА front лево к front"
_objects[32] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[33] = _scene->object_interface(BG_FRONT_LEFT);
_objects[34] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xE3\xE8\xF0\xE8"); // "накладка front гири"
_objects[35] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[36] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xE3\xE8\xF0\xE8 \xE2 \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xEE\xEC \xFF\xF9\xE8\xEA\xE5"); // "_МАСКА front гири в центральном ящике"
_objects[37] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый закрыт"
_objects[38] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[39] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[40] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[41] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[42] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[43] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEF\xF0\xE0\xE2\xEE \xEA front"); // "_МАСКА front право к front"
_objects[44] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[45] = _scene->object_interface(BG_FRONT_RIGHT);
_objects[46] = _scene->object_interface("\xEA\xEE\xEC\xEE\xE4 \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "комод левый ящик открыт"
_objects[47] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА center левый ящик закрыт"
_objects[48] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEB\xE5\xE2\xEE"); // "_МАСКА center левый ящик открыт лево"
_objects[49] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center левый ящик открыт право"
_objects[50] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xFF\xE9\xF6\xE0"); // "накладка center яйца"
_objects[51] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xE7\xE5\xEB\xE5\xED\xFB\xE9 \xEF\xE0\xEA\xE5\xF2"); // "накладка center зеленый пакет"
_objects[52] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xE0\xF1\xEB\xEE"); // "накладка center масло"
_objects[53] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xEE\xEB\xEE\xEA\xEE"); // "накладка center молоко"
_objects[54] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xE2\xE5\xF1\xFB"); // "накладка center весы"
_objects[55] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xF3\xEA\xE0"); // "накладка center мука"
_objects[56] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEA\xED\xE8\xE3\xE0 \xF1 \xF0\xE5\xF6\xE5\xEF\xF2\xE0\xEC\xE8"); // "накладка center книга с рецептами"
_objects[57] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xE2\xE5\xF1\xFB"); // "_МАСКА center весы"
_objects[58] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEA\xED\xE8\xE3\xE0 \xF1 \xF0\xE5\xF6\xE5\xEF\xF2\xE0\xEC\xE8"); // "_МАСКА center книга с рецептами"
_objects[59] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА center правый ящик закрыт"
_objects[60] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEB\xE5\xE2\xEE"); // "_МАСКА center правый ящик открыт лево"
_objects[61] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center правый ящик открыт право"
_objects[62] = _scene->object_interface("\xEA\xEE\xEC\xEE\xE4 \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "комод правый ящик открыт"
_objects[63] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xEE"); // "_МАСКА center лево"
_objects[64] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center право"
_objects[65] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xF4\xF0\xEE\xED\xF2"); // "_МАСКА center фронт"
_objects[66] = _scene->object_interface("\xF4\xEE\xED center"); // "фон center"
_objects[67] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый закрыт"
_objects[68] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый закрыт"
_objects[69] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый открыт"
_objects[70] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый открыт"
_objects[71] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xEB\xE5\xE2\xEE \xEF\xE0\xEB\xEE\xF7\xEA\xE8"); // "накладка front лево палочки"
_objects[72] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xEB\xE5\xE2\xEE \xF1\xEA\xE0\xEB\xEA\xE0"); // "накладка front лево скалка"
_objects[73] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик правый открыт"
_objects[74] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик левый открыт"
_objects[75] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF1\xEE\xEB\xFC"); // "_МАСКА front соль"
_objects[76] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[77] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[78] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[79] = _scene->object_interface(BG_FRONT_RIGHT);
_objects[80] = _scene->object_interface(BG_FRONT_LEFT);
_objects[81] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEF\xF0\xE0\xE2\xEE \xEA front"); // "_МАСКА front право к front"
_objects[82] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEB\xE5\xE2\xEE \xEA front"); // "_МАСКА front лево к front"
_objects[83] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[84] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[85] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[86] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[87] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEB\xE5\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик левый закрыт"
_objects[88] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[89] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF1\xEE\xEB\xFC"); // "_МАСКА front соль"
_objects[90] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[91] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[92] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[93] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[94] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[95] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEB\xE5\xE2\xEE \xEA front"); // "_МАСКА front лево к front"
_objects[96] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[97] = _scene->object_interface(BG_FRONT_LEFT);
_objects[98] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xEF\xF0\xE0\xE2\xFB\xE9 \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА front ящик правый закрыт"
_objects[99] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xF1\xEE\xEB\xFC"); // "накладка front соль"
_objects[100] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF1\xEE\xEB\xFC"); // "_МАСКА front соль"
_objects[101] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xFF\xF9\xE8\xEA \xF6\xE5\xED\xF2\xF0\xE0\xEB\xFC\xED\xFB\xE9"); // "_МАСКА front ящик центральный"
_objects[102] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 front \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "накладка front ящик открыт"
_objects[103] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА front к front право"
_objects[104] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEA front \xEB\xE5\xE2\xEE"); // "_МАСКА front к front лево"
_objects[105] = _scene->object_interface("\xF4\xEE\xED front"); // "фон front"
_objects[106] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xEF\xF0\xE0\xE2\xEE \xEA front"); // "_МАСКА front право к front"
_objects[107] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 front \xF6\xE5\xED\xF2\xF0"); // "_МАСКА front центр"
_objects[108] = _scene->object_interface(BG_FRONT_RIGHT);
_objects[109] = _scene->object_interface("\xEA\xEE\xEC\xEE\xE4 \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "комод левый ящик открыт"
_objects[110] = _scene->object_interface("\xEA\xEE\xEC\xEE\xE4 \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2"); // "комод правый ящик открыт"
_objects[111] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xE7\xE5\xEB\xE5\xED\xFB\xE9 \xEF\xE0\xEA\xE5\xF2"); // "накладка center зеленый пакет"
_objects[112] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xE0\xF1\xEB\xEE"); // "накладка center масло"
_objects[113] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xEE\xEB\xEE\xEA\xEE"); // "накладка center молоко"
_objects[114] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xEC\xF3\xEA\xE0"); // "накладка center мука"
_objects[115] = _scene->object_interface("\xED\xE0\xEA\xEB\xE0\xE4\xEA\xE0 center \xFF\xE9\xF6\xE0"); // "накладка center яйца"
_objects[116] = _scene->object_interface("\xF4\xEE\xED center"); // "фон center"
_objects[117] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xF4\xF0\xEE\xED\xF2"); // "_МАСКА center фронт"
_objects[118] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center право"
_objects[119] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА center правый ящик закрыт"
_objects[120] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xE7\xE0\xEA\xF0\xFB\xF2"); // "_МАСКА center левый ящик закрыт"
_objects[121] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xEE"); // "_МАСКА center лево"
_objects[122] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEB\xE5\xE2\xEE"); // "_МАСКА center левый ящик открыт лево"
_objects[123] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEB\xE5\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center левый ящик открыт право"
_objects[124] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEB\xE5\xE2\xEE"); // "_МАСКА center правый ящик открыт лево"
_objects[125] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEF\xF0\xE0\xE2\xFB\xE9 \xFF\xF9\xE8\xEA \xEE\xF2\xEA\xF0\xFB\xF2 \xEF\xF0\xE0\xE2\xEE"); // "_МАСКА center правый ящик открыт право"
_objects[126] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xE7\xE5\xEB\xE5\xED\xFB\xE9 \xEF\xE0\xEA\xE5\xF2"); // "_МАСКА center зеленый пакет"
_objects[127] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEC\xE0\xF1\xEB\xEE"); // "_МАСКА center масло"
_objects[128] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEC\xEE\xEB\xEE\xEA\xEE"); // "_МАСКА center молоко"
_objects[129] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xEC\xF3\xEA\xE0"); // "_МАСКА center мука"
_objects[130] = _scene->object_interface("_\xCC\xC0\xD1\xCA\xC0 center \xFF\xE9\xF6\xE0"); // "_МАСКА center яйца"
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2States::quant(%f)", dt);
_engine->set_interface_text(MAIN, "text", "START");
if (!_objSelectedSet->is_state_active("none")) {
if (_objSelectedSet->is_state_active(SET1)) {
_engine->set_interface_text(MAIN, "text", SET1);
_objects[1]->set_state(MASK2);
_objects[2]->set_state(MASK1);
_objects[3]->set_state(MASK3);
_objects[4]->set_state(MASK2);
_objects[5]->set_state(MASK1);
_objects[6]->set_state(MASK2);
_objects[7]->set_state(MASK2);
_objects[8]->set_state(MASK2);
_objects[9]->set_state(MASK2);
_objects[10]->set_state(MASK2);
_objects[11]->set_state(MASK2);
_objects[12]->set_state(MASK1);
_objects[13]->set_state(MASK1);
_objects[14]->set_state(MASK2);
_objects[15]->set_state(MASK2);
_objects[16]->set_state(MASK2);
_objects[17]->set_state(MASK2);
_objects[18]->set_state(MASK1);
_objects[19]->set_state(MASK1);
_objects[20]->set_state(MASK1);
_objects[21]->set_state(MASK1);
} else if (_objSelectedSet->is_state_active(SET2)) {
_engine->set_interface_text(MAIN, "text", SET2);
_objects[22]->set_state(MASK3);
_objects[23]->set_state(MASK3);
_objects[24]->set_state(MASK3);
_objects[25]->set_state(BG_MASK);
_objects[26]->set_state(MASK2);
_objects[27]->set_state(MASK3);
_objects[28]->set_state(MASK2);
_objects[29]->set_state(MASK2);
_objects[30]->set_state(MASK2);
_objects[31]->set_state(BG_MASK);
_objects[32]->set_state(BG_MASK1);
_objects[33]->set_state(BG_FRONT_LEFT);
} else if (_objSelectedSet->is_state_active(SET3)) {
_engine->set_interface_text(MAIN, "text", SET3);
_objects[34]->set_state(MASK4);
_objects[35]->set_state(MASK4);
_objects[36]->set_state(MASK4);
_objects[37]->set_state(BG_MASK);
_objects[38]->set_state(MASK3);
_objects[39]->set_state(MASK4);
_objects[40]->set_state(MASK3);
_objects[41]->set_state(MASK3);
_objects[42]->set_state(MASK3);
_objects[43]->set_state(BG_MASK);
_objects[44]->set_state(BG_MASK2);
_objects[45]->set_state(BG_FRONT_RIGHT);
} else if (_objSelectedSet->is_state_active(SET4)) {
_engine->set_interface_text(MAIN, "text", SET4);
_objects[46]->set_state(MASK2);
_objects[47]->set_state(MASK1);
_objects[48]->set_state(MASK2);
_objects[49]->set_state(MASK2);
_objects[50]->set_state(MASK2);
_objects[51]->set_state(MASK2);
_objects[52]->set_state(MASK2);
_objects[53]->set_state(MASK2);
_objects[54]->set_state(MASK2);
_objects[55]->set_state(MASK2);
_objects[56]->set_state(MASK1);
_objects[57]->set_state(MASK2);
_objects[58]->set_state(MASK2);
_objects[59]->set_state(MASK1);
_objects[60]->set_state(MASK2);
_objects[61]->set_state(MASK2);
_objects[62]->set_state(MASK2);
_objects[63]->set_state(MASK1);
_objects[64]->set_state(MASK1);
_objects[65]->set_state(MASK1);
_objects[66]->set_state(MASK1);
} else if (_objSelectedSet->is_state_active(SET5)) {
_engine->set_interface_text(MAIN, "text", SET5);
_objects[67]->set_state(MASK3);
_objects[68]->set_state(MASK3);
_objects[69]->set_state(MASK3);
_objects[70]->set_state(MASK3);
_objects[71]->set_state(MASK3);
_objects[72]->set_state(MASK3);
_objects[73]->set_state(MASK3);
_objects[74]->set_state(MASK3);
_objects[75]->set_state(MASK2);
_objects[76]->set_state(MASK2);
_objects[77]->set_state(MASK2);
_objects[78]->set_state(MASK1);
_objects[79]->set_state(MASK2);
_objects[80]->set_state(MASK2);
_objects[81]->set_state(MASK2);
_objects[82]->set_state(MASK2);
_objects[83]->set_state(MASK1);
_objects[84]->set_state(MASK1);
_objects[85]->set_state(MASK1);
_objects[86]->set_state(MASK1);
} else if (_objSelectedSet->is_state_active(SET6)) {
_engine->set_interface_text(MAIN, "text", SET6);
_objects[87]->set_state(BG_MASK);
_objects[88]->set_state(MASK3);
_objects[89]->set_state(MASK3);
_objects[90]->set_state(MASK1);
_objects[91]->set_state(MASK3);
_objects[92]->set_state(MASK2);
_objects[93]->set_state(MASK2);
_objects[94]->set_state(MASK2);
_objects[95]->set_state(BG_MASK);
_objects[96]->set_state(BG_MASK1);
_objects[97]->set_state(BG_FRONT_LEFT);
} else if (_objSelectedSet->is_state_active(SET7)) {
_engine->set_interface_text(MAIN, "text", SET7);
_objects[98]->set_state(BG_MASK);
_objects[99]->set_state(MASK4);
_objects[100]->set_state(MASK4);
_objects[101]->set_state(MASK3);
_objects[102]->set_state(MASK4);
_objects[103]->set_state(MASK3);
_objects[104]->set_state(MASK3);
_objects[105]->set_state(MASK3);
_objects[106]->set_state(BG_MASK);
_objects[107]->set_state(BG_MASK2);
_objects[108]->set_state(BG_FRONT_RIGHT);
} else if (_objSelectedSet->is_state_active(SET8)) {
_objects[109]->set_state(MASK2);
_objects[110]->set_state(MASK1);
_objects[111]->set_state(MASK1);
_objects[112]->set_state(MASK1);
_objects[113]->set_state(MASK1);
_objects[114]->set_state(MASK1);
_objects[115]->set_state(MASK1);
_objects[116]->set_state(MASK1);
_objects[117]->set_state(MASK1);
_objects[118]->set_state(MASK1);
_objects[119]->set_state(MASK2);
_objects[120]->set_state(MASK2);
_objects[121]->set_state(MASK1);
_objects[122]->set_state(MASK1);
_objects[123]->set_state(MASK1);
_objects[124]->set_state(MASK1);
_objects[125]->set_state(MASK1);
_objects[126]->set_state(MASK1);
_objects[127]->set_state(MASK1);
_objects[128]->set_state(MASK1);
_objects[129]->set_state(MASK1);
_objects[130]->set_state(MASK1);
}
_objSelectedSet->set_state("none");
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2States::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_objScene = nullptr;
qdMinigameObjectInterface *_objSelectedSet = nullptr;
qdMinigameObjectInterface *_objects[131] = { nullptr };
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_STATES_H

View File

@@ -0,0 +1,314 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_SUDOKU_H
#define QDENGINE_MINIGAMES_3MICE2_SUDOKU_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2SudokuMiniGame : public qdMiniGameInterface {
public:
qd3mice2SudokuMiniGame() {}
~qd3mice2SudokuMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2Sudoku::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_figures[0] = _scene->object_interface("figure@1#");
_figures[1] = _scene->object_interface("figure@2#");
_figures[2] = _scene->object_interface("figure@3#");
_figures[3] = _scene->object_interface("figure@4#");
_figures[4] = _scene->object_interface("figure@5#");
_figures[5] = _scene->object_interface("figure@6#");
_figures[6] = _scene->object_interface("figure@7#");
_figures[7] = _scene->object_interface("figure@8#");
_figures[8] = _scene->object_interface("figure@9#");
_figures[9] = _scene->object_interface("figure@10#");
_figures[10] = _scene->object_interface("figure@11#");
_figures[11] = _scene->object_interface("figure@12#");
_figures[12] = _scene->object_interface("figure@13#");
_figures[13] = _scene->object_interface("figure@1#inv");
_figures[14] = _scene->object_interface("figure@2#inv");
_figures[15] = _scene->object_interface("figure@3#inv");
_figures[16] = _scene->object_interface("figure@4#inv");
_figures[17] = _scene->object_interface("figure@5#inv");
_figures[18] = _scene->object_interface("figure@6#inv");
_figures[19] = _scene->object_interface("figure@7#inv");
_figures[20] = _scene->object_interface("figure@8#inv");
_figures[21] = _scene->object_interface("figure@9#inv");
_figures[22] = _scene->object_interface("figure@10#inv");
_figures[23] = _scene->object_interface("figure@11#inv");
_figures[24] = _scene->object_interface("figure@12#inv");
_figures[25] = _scene->object_interface("figure@13#inv");
_pos[0] = 20;
_pos[1] = 10;
_pos[2] = 26;
_pos[3] = 1;
_pos[4] = 3;
_pos[5] = 17;
_pos[6] = 8;
_pos[7] = 20;
_pos[8] = 6;
_pos[9] = 16;
_pos[10] = 17;
_pos[11] = 14;
_pos[12] = 18;
_objDone = _scene->object_interface("$done");
_objResult = _scene->object_interface("$\xf0\xe5\xe7\xf3\xeb\xfc\xf2\xe0\xf2"); // "$результат"
_objSettled = _scene->object_interface("$\xf0\xe0\xe7\xeb\xee\xe6\xe5\xed\xee"); // "$разложено"
_objReset = _scene->object_interface("$\xee\xe1\xed\xf3\xeb\xe8\xf2\xfc"); // "$обнулить"
_objTarget = _scene->object_interface("target");
_objLoading = _scene->object_interface("$\xe7\xe0\xe3\xf0\xf3\xe7\xea\xe0"); // "$загрузка"
if (_objLoading->is_state_active("no")) {
for (int i = 0; i < 13; i++)
_pieceTargets[i] = -1;
_objLoading->set_state("yes");
return true;
} else {
if (_objLoading->is_state_active("yes")) {
for (int i = 0; i < 13; i++) {
_objTarget->set_state(Common::String::format("%d", i + 1).c_str());
_objTarget->update_screen_R();
_pieceCoords[i] = _objTarget->screen_R();
_pieceTargets[i] = -1;
}
for (int j = 0; j < 13; j++) {
for (int i = 0; i < 13; i++) {
if (_figures[i]->screen_R().x - _pieceCoords[j].x < 2 &&
_figures[i]->screen_R().y - _pieceCoords[j].y < 2)
_pieceTargets[i] = j;
}
}
}
}
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2Sudoku::quant(%f)", dt);
if (_objReset->is_state_active("\xe4\xe0")) { // "да"
for (int i = 0; i < 13; i++) {
_pieceTargets[i] = -1;
_figures[i]->set_state("base");
}
_objReset->set_state("\xed\xe5\xf2"); // "нет"
}
if (checkSolution()) {
_objDone->set_state("\xe4\xe0"); // "да"
_objResult->set_state("\xef\xf0\xe0\xe2\xe8\xeb\xfc\xed\xee"); // "правильно"
} else {
_objDone->set_state("\xed\xe5\xf2"); // "нет"
_objResult->set_state("\xed\xe5\x20\xef\xf0\xe0\xe2\xe8\xeb\xfc\xed\xee"); // "не правильно"
}
if (checkInitPos())
_objSettled->set_state("\xe4\xe0"); // "да"
else
_objSettled->set_state("\xed\xe5\xf2"); // "нет"
qdMinigameObjectInterface *mouseObj = _scene->mouse_object_interface();
qdMinigameObjectInterface *clickObj = _scene->mouse_click_object_interface();
qdMinigameObjectInterface *hoverObj = _scene->mouse_hover_object_interface();
if (mouseObj) {
int num = getObjNum(mouseObj->name());
if (hoverObj) {
int num2 = -1;
if (strstr(hoverObj->name(), "zone@"))
num2 = getObjNum(hoverObj->name());
if (num2 == -1 || posIsSet(num2 - 1))
_figures[num + 12]->set_state("inv");
else
_figures[num + 12]->set_state("inv_active");
} else {
_figures[num + 12]->set_state("inv");
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN) && clickObj && !mouseObj) {
int num = -1;
if (strstr(clickObj->name(), "figure")) {
num = getObjNum(clickObj->name());
debugC(2, kDebugMinigames, "clickObj: zone is: %d for name: '%s'", num, clickObj->name());
if (num > 0) {
_figures[num - 1]->set_state("hide");
_figures[num + 12]->set_state("to_inv");
}
}
resetFigure(num - 1);
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN) &&
mouseObj &&
clickObj &&
strstr(mouseObj->name(), "figure") &&
strstr(mouseObj->name(), "inv") &&
strstr(clickObj->name(), "zone@")) {
int num = getObjNum(clickObj->name());
int num2 =getObjNum(mouseObj->name());
debugC(2, kDebugMinigames, "clickObj: zone is: %d for name: '%s'", num, clickObj->name());
debugC(2, kDebugMinigames, "mouseObj: zone is: %d for name: '%s'", num2, mouseObj->name());
if (num > 0 && num2 > 0 && !posIsSet(num - 1)) {
_objTarget->set_state(Common::String::format("%d", num).c_str());
_objTarget->update_screen_R();
_figures[num2 + 12]->set_state("del");
_figures[num2 - 1]->set_state("target");
mgVect2i pos = _objTarget->screen_R();
pos.y += _pos[num2 - 1];
_figures[num2 - 1]->set_R(_scene->screen2world_coords(pos, 0));
_pieceTargets[num - 1] = num2 - 1;
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN) && mouseObj) {
int num = getObjNum(mouseObj->name());
debugC(2, kDebugMinigames, "mouseObj: zone is: %d for name: '%s'", num, mouseObj->name());
_figures[num - 1]->set_state("base");
_figures[num + 12]->set_state("del");
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2Sudoku::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
for (int i = 0; i < 13; i++)
if (_pieceTargets[i] != i)
return false;
return true;
}
bool checkInitPos() {
for (int i = 0; i < 13; i++)
if (_pieceTargets[i] == -1)
return false;
return true;
}
void resetFigure(int pos) {
for (int i = 0; i < 13; i++)
if (_pieceTargets[i] == pos)
_pieceTargets[i] = -1;
}
bool posIsSet(int pos) {
return _pieceTargets[pos] != -1;
}
int getObjNum(const char *name) {
const char *from = strstr(name, "@");
const char *to = strstr(name, "#");
char tmp[20];
Common::strlcpy(tmp, from + 1, to - from);
return atol(tmp);
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_figures[26] = { nullptr };
int _pos[13] = { 0 };
mgVect2i _pieceCoords[13];
int _pieceTargets[13] = { 0 };
qdMinigameObjectInterface *_objDone = nullptr;
qdMinigameObjectInterface *_objResult = nullptr;
qdMinigameObjectInterface *_objSettled = nullptr;
qdMinigameObjectInterface *_objReset = nullptr;
qdMinigameObjectInterface *_objTarget = nullptr;
qdMinigameObjectInterface *_objLoading = nullptr;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_SUDOKU_H

View File

@@ -0,0 +1,494 @@
/* 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 QDENGINE_MINIGAMES_3MICE2_TESTO_H
#define QDENGINE_MINIGAMES_3MICE2_TESTO_H
#include "common/debug.h"
#include "common/rect.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qd3mice2TestoMiniGame : public qdMiniGameInterface {
public:
qd3mice2TestoMiniGame() {}
~qd3mice2TestoMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "3mice2Testo::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_figures[0] = _scene->object_interface("figure1");
_figures[1] = _scene->object_interface("figure2");
_figures[2] = _scene->object_interface("figure3");
_figures[3] = _scene->object_interface("figure4");
_figures[4] = _scene->object_interface("figure5");
_figures[5] = _scene->object_interface("figure6");
_figures[6] = _scene->object_interface("figure7");
_figures[7] = _scene->object_interface("figure8");
_figures[8] = _scene->object_interface("figure1fake");
_figures[9] = _scene->object_interface("figure2fake");
_figures[10] = _scene->object_interface("figure3fake");
_figures[11] = _scene->object_interface("figure4fake");
_figures[12] = _scene->object_interface("figure5fake");
_figures[13] = _scene->object_interface("figure6fake");
_figures[14] = _scene->object_interface("figure7fake");
_figures[15] = _scene->object_interface("figure8fake");
_figures[16] = _scene->object_interface("figure1inv");
_figures[17] = _scene->object_interface("figure2inv");
_figures[18] = _scene->object_interface("figure3inv");
_figures[19] = _scene->object_interface("figure4inv");
_figures[20] = _scene->object_interface("figure5inv");
_figures[21] = _scene->object_interface("figure6inv");
_figures[22] = _scene->object_interface("figure7inv");
_figures[23] = _scene->object_interface("figure8inv");
_objNoDough = _scene->object_interface("notesto");
_objNoDoughFake = _scene->object_interface("notesto_fake");
_objDone = _scene->object_interface("$done");
_objLoadPassed = _scene->object_interface("$\xE7\xE0\xE3\xF0\xF3\xE7\xEA\xE0 \xE1\xFB\xEB\xE0"); // "$загрузка была"
#if 0
for (int i = 0; i < 1088; i++) {
debugN("{ %3d, %3d }, ", _figureVerts[i].x, _figureVerts[i].y);
if ((i + 1) % 8 == 0)
debugN("// %d\n", i - 7);
}
#endif
_noDoughX = 1000;
_numVerts[0] = 66;
_numVerts[1] = 94;
_numVerts[2] = 136;
_numVerts[3] = 136;
_numVerts[4] = 68;
_numVerts[5] = 68;
_numVerts[6] = 112;
_numVerts[7] = 112;
for (int i = 0; i < 8; i++) {
int v = i;
int maxX = 0;
int minX = 0;
int minY = 0;
int maxY = 0;
for (int j = 0; j < _numVerts[i]; j++) {
if (_figureVerts[v].x < minX)
minX = _figureVerts[v].x;
if (_figureVerts[v].x > maxX)
maxX = _figureVerts[v].x;
if (_figureVerts[v].y < minY)
minY = _figureVerts[v].y;
if (_figureVerts[v].y > maxY)
maxY = _figureVerts[v].y;
v += 8; // Data is arranged in vertical columns
}
_figureBboxes[i].top = maxX;
_figureBboxes[i].left = minX;
_figureBboxes[i].bottom = maxY;
_figureBboxes[i].top = minY;
debugC(2, kDebugMinigames, "bbox for: %d: [%d, %d, %d, %d]", i, _figureBboxes[i].left, _figureBboxes[i].top, _figureBboxes[i].right, _figureBboxes[i].bottom);
}
mgVect2i pos = _objNoDough->screen_R();
pos.x += _noDoughX;
_objNoDoughFake->set_R(_scene->screen2world_coords(pos, -100.0));
_initialCoords[0].x = 75;
_initialCoords[0].y = 80;
_initialCoords[1].x = 695;
_initialCoords[1].y = 100;
_initialCoords[2].x = 82;
_initialCoords[2].y = 234;
_initialCoords[3].x = 738;
_initialCoords[3].y = 468;
_initialCoords[4].x = 84;
_initialCoords[4].y = 392;
_initialCoords[5].x = 302;
_initialCoords[5].y = 465;
_initialCoords[6].x = 687;
_initialCoords[6].y = 293;
_initialCoords[7].x = 611;
_initialCoords[7].y = 472;
if (_objLoadPassed->is_state_active("\xed\xe5\xf2")) { // "нет"
for (int i = 0; i < 8; i++)
_figures[i]->set_R(_scene->screen2world_coords(_initialCoords[i], 0.0));
_objLoadPassed->set_state("\xe4\xe0"); // "да"
return true;
}
return false;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "3mice2Testo::quant(%f)", dt);
if (checkSolution())
_objDone->set_state("\xe4\xe0"); // "да"
else
_objDone->set_state("\xed\xe5\xf2"); // "нет"
for (int i = 0; i < 8; i++) {
mgVect2i pos = _figures[i]->screen_R();
pos.x += _noDoughX;
_figures[i + 8]->set_R(_scene->screen2world_coords(pos, 1000.0));
}
qdMinigameObjectInterface *mouseObj = _scene->mouse_object_interface();
qdMinigameObjectInterface *clickObj = _scene->mouse_click_object_interface();
const char *name = nullptr;
if (mouseObj) {
name = mouseObj->name();
if (strstr(name, "figure") && strstr(name, "inv")) {
int num = atol(name + 6);
if (checkSnapPiece(num - 1))
mouseObj->set_state("inv");
else
mouseObj->set_state("inv_glow");
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN) && !mouseObj) {
int hit = hitTest();
debugC(2, kDebugMinigames, "hit: %d", hit);
if (hit > -1) {
_figures[hit]->set_state("hide");
_figures[hit + 16]->set_state("to_inv");
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN) && mouseObj) {
int num = -1;
if (strstr(name, "figure") && strstr(name, "inv")) {
num = atol(name + 6);
debugC(2, kDebugMinigames, "drop: %d", num);
if (num > 0 && num <= 8 && !checkSnapPiece(num - 1)) {
_figures[num - 1]->set_state("testo");
_figures[num + 15]->set_state("del");
_figures[num - 1]->set_R(_scene->screen2world_coords(_engine->mouse_cursor_position(), 0.0));
}
}
if (clickObj) { // && mouseObj
name = clickObj->name();
if (strstr(name, "notesto") && num > 0 && num <= 8) {
_figures[num - 1]->set_state("base");
_figures[num + 15]->set_state("del");
_figures[num - 1]->set_R(_scene->screen2world_coords(_initialCoords[num - 1], 0.0));
}
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN) && mouseObj) {
name = mouseObj->name();
if (strstr(name, "figure") && strstr(name, "inv")) {
int num = atol(name + 6);
if (num > 0 && num <= 8) {
_figures[num - 1]->set_state("base");
_figures[num + 15]->set_state("del");
_figures[num - 1]->set_R(_scene->screen2world_coords(_initialCoords[num - 1], 0.0));
}
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "3mice2Testo::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
bool checkSolution() {
return _figures[1]->is_state_active("testo")
&& _figures[3]->is_state_active("testo")
&& _figures[4]->is_state_active("testo")
&& _figures[5]->is_state_active("testo")
&& _figures[6]->is_state_active("testo");
}
int hitTest() {
mgVect2i pos = _engine->mouse_cursor_position();
pos.x += _noDoughX;
for (int i = 0; i < 8; i++) {
if (_figures[i + 8]->hit_test(pos))
return i;
}
return -1;
}
bool checkSnapPiece(int num) {
mgVect2i pos = _engine->mouse_cursor_position();
pos.x += _noDoughX;
int v = num;
for (int i = 0; i < _numVerts[num]; i++) {
mgVect2i npos = _figureVerts[v];
npos.x += pos.x;
npos.y += pos.y;
for (int j = 0; j < 8; j++) {
if (j != num) {
if (_figures[8 + j]->hit_test(npos))
return true;
if (_objNoDoughFake->hit_test(npos))
return true;
}
}
v += 8;
}
for (int i = 0; i < 8; i++) {
if (i != num) {
if (_figureBboxes[i].right + _figures[i]->screen_R().x < pos.x + _figureBboxes[num].right &&
_figureBboxes[i].left + _figures[i]->screen_R().x > pos.x + _figureBboxes[num].left &&
_figureBboxes[i].top + _figures[i]->screen_R().y < pos.y + _figureBboxes[num].top &&
_figureBboxes[i].bottom + _figures[i]->screen_R().y > pos.y + _figureBboxes[num].bottom)
return true;
}
}
return false;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_figures[24] = { nullptr };
int _numVerts[8] = { 0 };
qdMinigameObjectInterface *_objNoDough = nullptr;
qdMinigameObjectInterface *_objNoDoughFake = nullptr;
qdMinigameObjectInterface *_objLoadPassed = nullptr;
qdMinigameObjectInterface *_objDone = nullptr;
mgVect2i _initialCoords[8];
int _noDoughX = 0;
Common::Rect _figureBboxes[8];
const mgVect2i _figureVerts[1088] = {
{ -66, 0 }, { -86, 0 }, { -73, 0 }, { -54, 0 }, { -65, 0 }, { -22, 0 }, { -83, 0 }, { -62, 0 }, // 0
{ -66, -10 }, { -86, -11 }, { -68, -3 }, { -50, -2 }, { -65, -10 }, { -22, -3 }, { -83, -6 }, { -62, -5 }, // 8
{ -65, -20 }, { -85, -20 }, { -63, -6 }, { -47, -4 }, { -65, -17 }, { -22, -6 }, { -80, -9 }, { -60, -7 }, // 16
{ -65, -30 }, { -85, -30 }, { -58, -11 }, { -43, -8 }, { -62, -27 }, { -21, -9 }, { -77, -12 }, { -58, -9 }, // 24
{ -65, -40 }, { -85, -41 }, { -53, -14 }, { -39, -10 }, { -58, -34 }, { -20, -12 }, { -74, -15 }, { -56, -11 }, // 32
{ -64, -50 }, { -84, -50 }, { -50, -16 }, { -37, -12 }, { -53, -41 }, { -18, -14 }, { -71, -20 }, { -53, -15 }, // 40
{ -63, -60 }, { -84, -57 }, { -50, -17 }, { -37, -13 }, { -48, -45 }, { -17, -15 }, { -70, -23 }, { -53, -17 }, // 48
{ -62, -63 }, { -84, -63 }, { -53, -22 }, { -39, -16 }, { -43, -50 }, { -15, -17 }, { -71, -27 }, { -53, -20 }, // 56
{ -59, -64 }, { -83, -74 }, { -53, -26 }, { -39, -19 }, { -38, -53 }, { -13, -18 }, { -72, -31 }, { -54, -23 }, // 64
{ -49, -65 }, { -82, -80 }, { -57, -35 }, { -42, -26 }, { -33, -56 }, { -11, -19 }, { -73, -36 }, { -55, -27 }, // 72
{ -39, -65 }, { -81, -81 }, { -61, -41 }, { -45, -30 }, { -28, -58 }, { -10, -20 }, { -71, -40 }, { -53, -30 }, // 80
{ -29, -65 }, { -80, -82 }, { -61, -44 }, { -45, -33 }, { -23, -60 }, { -8, -21 }, { -69, -44 }, { -52, -33 }, // 88
{ -19, -65 }, { -77, -82 }, { -56, -44 }, { -41, -33 }, { -18, -61 }, { -6, -21 }, { -68, -46 }, { -51, -35 }, // 96
{ -9, -65 }, { -74, -83 }, { -51, -44 }, { -38, -33 }, { -13, -63 }, { -4, -22 }, { -64, -47 }, { -48, -35 }, // 104
{ 1, -65 }, { -57, -84 }, { -45, -42 }, { -33, -31 }, { -8, -63 }, { -3, -22 }, { -59, -47 }, { -44, -35 }, // 112
{ 11, -65 }, { -47, -84 }, { -40, -41 }, { -30, -30 }, { -3, -63 }, { -1, -22 }, { -57, -48 }, { -43, -36 }, // 120
{ 21, -65 }, { -37, -85 }, { -34, -40 }, { -25, -30 }, { 2, -63 }, { 1, -22 }, { -53, -52 }, { -40, -39 }, // 128
{ 31, -65 }, { -30, -86 }, { -33, -40 }, { -24, -30 }, { 7, -63 }, { 2, -22 }, { -52, -55 }, { -39, -41 }, // 136
{ 39, -65 }, { -20, -86 }, { -33, -45 }, { -24, -33 }, { 12, -63 }, { 4, -22 }, { -52, -61 }, { -39, -46 }, // 144
{ 47, -64 }, { -10, -86 }, { -33, -50 }, { -24, -37 }, { 17, -62 }, { 6, -21 }, { -49, -67 }, { -37, -50 }, // 152
{ 52, -64 }, { 0, -86 }, { -33, -55 }, { -24, -41 }, { 22, -60 }, { 8, -21 }, { -45, -71 }, { -34, -53 }, // 160
{ 57, -63 }, { 10, -86 }, { -33, -60 }, { -24, -44 }, { 27, -58 }, { 9, -20 }, { -40, -74 }, { -30, -56 }, // 168
{ 61, -63 }, { 20, -86 }, { -34, -61 }, { -25, -45 }, { 32, -56 }, { 11, -19 }, { -35, -76 }, { -26, -57 }, // 176
{ 64, -62 }, { 30, -86 }, { -34, -68 }, { -25, -50 }, { 37, -53 }, { 13, -18 }, { -30, -75 }, { -23, -56 }, // 184
{ 65, -61 }, { 41, -86 }, { -30, -68 }, { -22, -50 }, { 42, -50 }, { 14, -17 }, { -25, -72 }, { -19, -54 }, // 192
{ 65, -60 }, { 51, -85 }, { -29, -67 }, { -21, -50 }, { 47, -45 }, { 16, -15 }, { -20, -71 }, { -15, -53 }, // 200
{ 65, -50 }, { 59, -84 }, { -24, -66 }, { -18, -49 }, { 53, -39 }, { 18, -13 }, { -15, -72 }, { -11, -54 }, // 208
{ 65, -40 }, { 74, -83 }, { -20, -64 }, { -15, -47 }, { 57, -34 }, { 20, -12 }, { -10, -77 }, { -8, -58 }, // 216
{ 65, -30 }, { 79, -82 }, { -15, -61 }, { -11, -45 }, { 60, -29 }, { 21, -10 }, { -5, -80 }, { -4, -60 }, // 224
{ 65, -20 }, { 83, -81 }, { -10, -58 }, { -7, -43 }, { 63, -22 }, { 22, -8 }, { 0, -80 }, { 0, -60 }, // 232
{ 65, -10 }, { 84, -80 }, { -6, -56 }, { -4, -41 }, { 65, -15 }, { 22, -5 }, { 5, -80 }, { 4, -60 }, // 240
{ 65, 0 }, { 85, -79 }, { 0, -65 }, { 0, -48 }, { 65, -10 }, { 22, -3 }, { 10, -76 }, { 8, -57 }, // 248
{ 65, 6 }, { 86, -78 }, { 5, -72 }, { 4, -53 }, { 65, -5 }, { 22, -2 }, { 15, -71 }, { 11, -53 }, // 256
{ 64, 7 }, { 87, -75 }, { 9, -76 }, { 7, -56 }, { 65, 0 }, { 22, 0 }, { 20, -70 }, { 15, -53 }, // 264
{ 64, 17 }, { 87, -68 }, { 12, -76 }, { 9, -56 }, { 65, 5 }, { 22, 2 }, { 25, -71 }, { 19, -53 }, // 272
{ 64, 20 }, { 87, -58 }, { 15, -69 }, { 11, -51 }, { 65, 10 }, { 22, 3 }, { 30, -72 }, { 23, -54 }, // 280
{ 63, 22 }, { 86, -58 }, { 18, -60 }, { 13, -44 }, { 63, 15 }, { 22, 5 }, { 35, -71 }, { 26, -53 }, // 288
{ 63, 32 }, { 86, -48 }, { 19, -53 }, { 14, -39 }, { 61, 20 }, { 21, 7 }, { 40, -68 }, { 30, -51 }, // 296
{ 63, 42 }, { 86, -38 }, { 20, -52 }, { 15, -38 }, { 59, 25 }, { 20, 9 }, { 43, -64 }, { 32, -48 }, // 304
{ 63, 44 }, { 86, -28 }, { 25, -53 }, { 18, -39 }, { 56, 30 }, { 19, 10 }, { 44, -60 }, { 33, -45 }, // 312
{ 62, 45 }, { 86, -18 }, { 30, -54 }, { 22, -40 }, { 53, 35 }, { 18, 12 }, { 46, -54 }, { 35, -41 }, // 320
{ 62, 55 }, { 86, -10 }, { 35, -55 }, { 26, -41 }, { 49, 40 }, { 17, 14 }, { 50, -51 }, { 38, -38 }, // 328
{ 62, 61 }, { 85, -10 }, { 40, -57 }, { 30, -42 }, { 44, 45 }, { 15, 15 }, { 55, -49 }, { 41, -37 }, // 336
{ 61, 62 }, { 85, 9 }, { 43, -58 }, { 32, -43 }, { 37, 50 }, { 13, 17 }, { 59, -50 }, { 44, -38 }, // 344
{ 61, 63 }, { 84, 9 }, { 45, -57 }, { 33, -42 }, { 33, 53 }, { 11, 18 }, { 65, -48 }, { 49, -36 }, // 352
{ 60, 64 }, { 84, 26 }, { 45, -52 }, { 33, -38 }, { 28, 56 }, { 10, 19 }, { 70, -43 }, { 53, -32 }, // 360
{ 50, 64 }, { 83, 26 }, { 43, -46 }, { 32, -34 }, { 21, 59 }, { 7, 20 }, { 71, -41 }, { 53, -31 }, // 368
{ 40, 65 }, { 83, 42 }, { 41, -37 }, { 30, -27 }, { 16, 61 }, { 6, 21 }, { 71, -36 }, { 53, -27 }, // 376
{ 30, 65 }, { 82, 42 }, { 39, -32 }, { 29, -24 }, { 10, 63 }, { 3, 22 }, { 69, -32 }, { 52, -24 }, // 384
{ 20, 65 }, { 82, 50 }, { 40, -31 }, { 30, -23 }, { 5, 63 }, { 2, 22 }, { 68, -27 }, { 51, -20 }, // 392
{ 10, 65 }, { 83, 50 }, { 45, -30 }, { 33, -22 }, { 0, 63 }, { 0, 22 }, { 71, -22 }, { 53, -17 }, // 400
{ 0, 65 }, { 83, 55 }, { 50, -30 }, { 37, -22 }, { -5, 63 }, { -2, 22 }, { 76, -18 }, { 57, -14 }, // 408
{ -10, 65 }, { 82, 55 }, { 55, -31 }, { 41, -23 }, { -10, 63 }, { -3, 22 }, { 80, -15 }, { 60, -11 }, // 416
{ -20, 65 }, { 82, 68 }, { 60, -31 }, { 44, -23 }, { -15, 63 }, { -5, 22 }, { 84, -10 }, { 63, -8 }, // 424
{ -30, 65 }, { 81, 68 }, { 67, -31 }, { 50, -23 }, { -20, 61 }, { -7, 21 }, { 84, -5 }, { 63, -4 }, // 432
{ -40, 65 }, { 81, 81 }, { 67, -29 }, { 50, -21 }, { -25, 59 }, { -9, 20 }, { 84, -2 }, { 63, -2 }, // 440
{ -45, 64 }, { 80, 81 }, { 64, -25 }, { 47, -18 }, { -30, 57 }, { -10, 20 }, { 82, 0 }, { 62, 0 }, // 448
{ -50, 63 }, { 80, 83 }, { 61, -20 }, { 45, -15 }, { -35, 54 }, { -12, 19 }, { 78, 3 }, { 59, 2 }, // 456
{ -60, 63 }, { 79, 83 }, { 57, -16 }, { 42, -12 }, { -40, 51 }, { -14, 18 }, { 75, 7 }, { 56, 5 }, // 464
{ -66, 63 }, { 79, 84 }, { 54, -12 }, { 40, -9 }, { -45, 46 }, { -15, 16 }, { 73, 10 }, { 55, 8 }, // 472
{ -66, 53 }, { 71, 84 }, { 52, -9 }, { 38, -7 }, { -49, 42 }, { -17, 14 }, { 73, 14 }, { 55, 11 }, // 480
{ -66, 43 }, { 71, 85 }, { 55, -6 }, { 41, -4 }, { -53, 37 }, { -18, 13 }, { 77, 20 }, { 58, 15 }, // 488
{ -66, 33 }, { 61, 85 }, { 60, -3 }, { 44, -2 }, { -57, 32 }, { -20, 11 }, { 79, 24 }, { 59, 18 }, // 496
{ -66, 23 }, { 53, 85 }, { 65, 0 }, { 48, 0 }, { -60, 26 }, { -21, 9 }, { 78, 29 }, { 59, 22 }, // 504
{ -66, 13 }, { 49, 85 }, { 69, 3 }, { 51, 2 }, { -63, 19 }, { -22, 7 }, { 75, 32 }, { 56, 24 }, // 512
{ -67, 9 }, { 49, 86 }, { 72, 5 }, { 53, 4 }, { -64, 16 }, { -22, 6 }, { 73, 34 }, { 55, 26 }, // 520
{ 0, 0 }, { 39, 86 }, { 72, 6 }, { 53, 4 }, { -65, 11 }, { -22, 4 }, { 73, 34 }, { 55, 26 }, // 528
{ 0, 0 }, { 29, 86 }, { 67, 9 }, { 50, 7 }, { -65, 5 }, { -22, 2 }, { 68, 34 }, { 51, 26 }, // 536
{ 0, 0 }, { 19, 86 }, { 62, 11 }, { 46, 8 }, { 0, 0 }, { 0, 0 }, { 63, 35 }, { 47, 26 }, // 544
{ 0, 0 }, { 9, 86 }, { 57, 13 }, { 42, 10 }, { 0, 0 }, { 0, 0 }, { 58, 35 }, { 44, 26 }, // 552
{ 0, 0 }, { 0, 86 }, { 52, 16 }, { 38, 12 }, { 0, 0 }, { 0, 0 }, { 56, 38 }, { 42, 29 }, // 560
{ 0, 0 }, { -3, 86 }, { 50, 18 }, { 37, 13 }, { 0, 0 }, { 0, 0 }, { 55, 41 }, { 41, 31 }, // 568
{ 0, 0 }, { -3, 85 }, { 52, 23 }, { 38, 17 }, { 0, 0 }, { 0, 0 }, { 55, 46 }, { 41, 35 }, // 576
{ 0, 0 }, { -13, 85 }, { 54, 28 }, { 40, 21 }, { 0, 0 }, { 0, 0 }, { 50, 52 }, { 38, 39 }, // 584
{ 0, 0 }, { -23, 85 }, { 56, 35 }, { 41, 26 }, { 0, 0 }, { 0, 0 }, { 45, 57 }, { 34, 43 }, // 592
{ 0, 0 }, { -33, 85 }, { 57, 38 }, { 42, 28 }, { 0, 0 }, { 0, 0 }, { 39, 60 }, { 29, 45 }, // 600
{ 0, 0 }, { -43, 85 }, { 57, 42 }, { 42, 31 }, { 0, 0 }, { 0, 0 }, { 33, 59 }, { 25, 44 }, // 608
{ 0, 0 }, { -50, 85 }, { 54, 42 }, { 40, 31 }, { 0, 0 }, { 0, 0 }, { 27, 65 }, { 20, 49 }, // 616
{ 0, 0 }, { -57, 85 }, { 49, 42 }, { 36, 31 }, { 0, 0 }, { 0, 0 }, { 26, 69 }, { 20, 52 }, // 624
{ 0, 0 }, { -57, 84 }, { 45, 41 }, { 33, 30 }, { 0, 0 }, { 0, 0 }, { 25, 74 }, { 19, 56 }, // 632
{ 0, 0 }, { -62, 84 }, { 40, 41 }, { 30, 30 }, { 0, 0 }, { 0, 0 }, { 22, 76 }, { 17, 57 }, // 640
{ 0, 0 }, { -62, 83 }, { 35, 41 }, { 26, 30 }, { 0, 0 }, { 0, 0 }, { 17, 77 }, { 13, 58 }, // 648
{ 0, 0 }, { -72, 83 }, { 30, 41 }, { 22, 30 }, { 0, 0 }, { 0, 0 }, { 12, 76 }, { 9, 57 }, // 656
{ 0, 0 }, { -83, 83 }, { 28, 41 }, { 21, 30 }, { 0, 0 }, { 0, 0 }, { 7, 74 }, { 5, 56 }, // 664
{ 0, 0 }, { -84, 82 }, { 27, 41 }, { 20, 30 }, { 0, 0 }, { 0, 0 }, { 3, 70 }, { 2, 53 }, // 672
{ 0, 0 }, { -84, 71 }, { 27, 45 }, { 20, 33 }, { 0, 0 }, { 0, 0 }, { 0, 68 }, { 0, 51 }, // 680
{ 0, 0 }, { -84, 61 }, { 27, 50 }, { 20, 37 }, { 0, 0 }, { 0, 0 }, { -5, 71 }, { -4, 53 }, // 688
{ 0, 0 }, { -85, 61 }, { 27, 55 }, { 20, 41 }, { 0, 0 }, { 0, 0 }, { -10, 76 }, { -8, 57 }, // 696
{ 0, 0 }, { -85, 51 }, { 27, 60 }, { 20, 44 }, { 0, 0 }, { 0, 0 }, { -16, 78 }, { -12, 59 }, // 704
{ 0, 0 }, { -85, 41 }, { 27, 65 }, { 20, 48 }, { 0, 0 }, { 0, 0 }, { -22, 77 }, { -17, 58 }, // 712
{ 0, 0 }, { -85, 31 }, { 25, 66 }, { 18, 49 }, { 0, 0 }, { 0, 0 }, { -28, 73 }, { -21, 55 }, // 720
{ 0, 0 }, { -85, 21 }, { 20, 63 }, { 15, 47 }, { 0, 0 }, { 0, 0 }, { -33, 64 }, { -25, 48 }, // 728
{ 0, 0 }, { -85, 12 }, { 15, 59 }, { 11, 44 }, { 0, 0 }, { 0, 0 }, { -40, 64 }, { -30, 48 }, // 736
{ 0, 0 }, { -86, 1 }, { 10, 57 }, { 7, 42 }, { 0, 0 }, { 0, 0 }, { -45, 66 }, { -34, 50 }, // 744
{ 0, 0 }, { 0, 0 }, { 5, 54 }, { 4, 40 }, { 0, 0 }, { 0, 0 }, { -50, 66 }, { -38, 50 }, // 752
{ 0, 0 }, { 0, 0 }, { 2, 60 }, { 1, 44 }, { 0, 0 }, { 0, 0 }, { -55, 64 }, { -41, 48 }, // 760
{ 0, 0 }, { 0, 0 }, { -1, 65 }, { -1, 48 }, { 0, 0 }, { 0, 0 }, { -59, 60 }, { -44, 45 }, // 768
{ 0, 0 }, { 0, 0 }, { -4, 71 }, { -3, 53 }, { 0, 0 }, { 0, 0 }, { -60, 56 }, { -45, 42 }, // 776
{ 0, 0 }, { 0, 0 }, { -6, 73 }, { -4, 54 }, { 0, 0 }, { 0, 0 }, { -60, 51 }, { -45, 38 }, // 784
{ 0, 0 }, { 0, 0 }, { -9, 73 }, { -7, 54 }, { 0, 0 }, { 0, 0 }, { -60, 47 }, { -45, 35 }, // 792
{ 0, 0 }, { 0, 0 }, { -11, 71 }, { -8, 53 }, { 0, 0 }, { 0, 0 }, { -64, 41 }, { -48, 31 }, // 800
{ 0, 0 }, { 0, 0 }, { -13, 65 }, { -10, 48 }, { 0, 0 }, { 0, 0 }, { -69, 39 }, { -52, 29 }, // 808
{ 0, 0 }, { 0, 0 }, { -15, 60 }, { -11, 44 }, { 0, 0 }, { 0, 0 }, { -74, 38 }, { -56, 29 }, // 816
{ 0, 0 }, { 0, 0 }, { -17, 56 }, { -13, 41 }, { 0, 0 }, { 0, 0 }, { -78, 35 }, { -59, 26 }, // 824
{ 0, 0 }, { 0, 0 }, { -19, 51 }, { -14, 38 }, { 0, 0 }, { 0, 0 }, { -79, 33 }, { -59, 25 }, // 832
{ 0, 0 }, { 0, 0 }, { -22, 53 }, { -16, 39 }, { 0, 0 }, { 0, 0 }, { -80, 30 }, { -60, 23 }, // 840
{ 0, 0 }, { 0, 0 }, { -27, 57 }, { -20, 42 }, { 0, 0 }, { 0, 0 }, { -77, 25 }, { -58, 19 }, // 848
{ 0, 0 }, { 0, 0 }, { -32, 60 }, { -24, 44 }, { 0, 0 }, { 0, 0 }, { -74, 19 }, { -56, 14 }, // 856
{ 0, 0 }, { 0, 0 }, { -38, 63 }, { -28, 47 }, { 0, 0 }, { 0, 0 }, { -73, 14 }, { -55, 11 }, // 864
{ 0, 0 }, { 0, 0 }, { -39, 62 }, { -29, 46 }, { 0, 0 }, { 0, 0 }, { -76, 9 }, { -57, 7 }, // 872
{ 0, 0 }, { 0, 0 }, { -41, 62 }, { -30, 46 }, { 0, 0 }, { 0, 0 }, { -80, 7 }, { -60, 5 }, // 880
{ 0, 0 }, { 0, 0 }, { -41, 57 }, { -30, 42 }, { 0, 0 }, { 0, 0 }, { -82, 4 }, { -62, 3 }, // 888
{ 0, 0 }, { 0, 0 }, { -41, 52 }, { -30, 38 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 896
{ 0, 0 }, { 0, 0 }, { -42, 48 }, { -31, 36 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 904
{ 0, 0 }, { 0, 0 }, { -42, 43 }, { -31, 32 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 912
{ 0, 0 }, { 0, 0 }, { -39, 39 }, { -29, 29 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 920
{ 0, 0 }, { 0, 0 }, { -43, 38 }, { -32, 28 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 928
{ 0, 0 }, { 0, 0 }, { -49, 38 }, { -36, 28 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 936
{ 0, 0 }, { 0, 0 }, { -54, 37 }, { -40, 27 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 944
{ 0, 0 }, { 0, 0 }, { -59, 36 }, { -44, 27 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 952
{ 0, 0 }, { 0, 0 }, { -62, 34 }, { -46, 25 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 960
{ 0, 0 }, { 0, 0 }, { -60, 29 }, { -44, 21 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 968
{ 0, 0 }, { 0, 0 }, { -58, 26 }, { -43, 19 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 976
{ 0, 0 }, { 0, 0 }, { -55, 21 }, { -41, 16 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 984
{ 0, 0 }, { 0, 0 }, { -52, 17 }, { -38, 13 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 992
{ 0, 0 }, { 0, 0 }, { -51, 15 }, { -38, 11 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1000
{ 0, 0 }, { 0, 0 }, { -54, 13 }, { -40, 10 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1008
{ 0, 0 }, { 0, 0 }, { -57, 10 }, { -42, 7 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1016
{ 0, 0 }, { 0, 0 }, { -60, 9 }, { -44, 7 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1024
{ 0, 0 }, { 0, 0 }, { -65, 6 }, { -48, 4 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1032
{ 0, 0 }, { 0, 0 }, { -68, 4 }, { -50, 3 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1040
{ 0, 0 }, { 0, 0 }, { -71, 3 }, { -53, 2 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1048
{ 0, 0 }, { 0, 0 }, { -73, 2 }, { -54, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1056
{ 0, 0 }, { 0, 0 }, { -74, 1 }, { -55, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1064
{ 0, 0 }, { 0, 0 }, { -75, 0 }, { -55, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1072
{ 0, 0 }, { 0, 0 }, { -75, -1 }, { -55, -1 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // 1080
};
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_3MICE2_TESTO_H

View File

@@ -0,0 +1,94 @@
/* 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 "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/EffectManager.h"
#include "qdengine/minigames/adv/qdMath.h"
namespace QDEngine {
EffectManager::EffectManager(HoldData<EffectManagerData> &data, MinigameManager *runtime) {
_runtime = runtime;
const char *effectName = _runtime->parameter("effect_name", "effect");
if (_runtime->testObject(effectName)) {
_effect = _runtime->getObject(effectName);
_data.crd = _effect->R();
_effect->set_screen_scale(mgVect2f(0.01f, 0.01f), mgVect2f(10000.f, 10000.f));
_runtime->hide(_effect);
}
data.process(_data);
_effectTime = clamp(_runtime->getParameter("effect_time", 3.f), 0.5f, 10.f);
_phaseTime = clamp(_runtime->getParameter("effect_phase_time", _effectTime / 20.f), 0.03f, 1.f);
_phaseSpeed = clamp(_runtime->getParameter("effect_phase_speed", 1.5f), 1.05f, 10.f);
_current = EFFECT_COUNT;
_effectTimer = 0;
_phaseTimer = 0;
}
EffectManager::~EffectManager() {
_runtime->release(_effect);
}
void EffectManager::quant(float dt) {
if (_current == EFFECT_COUNT)
return;
if (_runtime->getTime() > _effectTimer) {
stop(_current);
return;
}
if (_runtime->getTime() > _phaseTimer) {
_phaseTimer = _runtime->getTime() + _phaseTime;
mgVect2f scale = _effect->screen_scale();
mgVect2f speed = scale;
scale *= _phaseSpeed;
speed = scale - speed;
speed /= _phaseTime;
_effect->set_screen_scale(scale, speed);
}
}
void EffectManager::start(EffectType id) {
if (_current != EFFECT_COUNT || !_effect)
return;
_effectTimer = _runtime->getTime() + _effectTime;
_current = id;
_phaseTimer = _runtime->getTime();
_effect->set_screen_scale(mgVect2f(0.02f, 0.02f), mgVect2f(10000.f, 10000.f));
_effect->set_R(_data.crd);
}
void EffectManager::stop(EffectType id) {
if (_current == EFFECT_COUNT)
return;
_runtime->hide(_effect);
_effect->set_screen_scale(mgVect2f(0.01f, 0.01f), mgVect2f(10000.f, 10000.f));
_current = EFFECT_COUNT;
}
} // namespace QDEngine

View 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 QDENGINE_MINIGAMES_ADV_EFFECT_MANAGER_H
#define QDENGINE_MINIGAMES_ADV_EFFECT_MANAGER_H
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/HoldData.h"
namespace QDEngine {
enum EffectType {
EFFECT_1,
EFFECT_COUNT
};
class EffectManager {
public:
EffectManager(HoldData<EffectManagerData> &data, MinigameManager *runtime);
~EffectManager();
void quant(float dt);
void start(EffectType id);
void stop(EffectType id);
private:
EffectType _current;
EffectManagerData _data;
float _phaseTime;
float _effectTime;
float _phaseSpeed;
float _effectTimer;
float _phaseTimer;
QDObject _effect;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_EFFECT_MANAGER_H

View File

@@ -0,0 +1,151 @@
/* 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/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/EventManager.h"
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/TextManager.h"
namespace QDEngine {
EventManager::EventPreset::EventPreset() {
score = 0;
fontID = -1;
escapeID = -1;
triggerEventID = -1;
}
EventManager::EventManager(MinigameManager *runtime) {
_runtime = runtime;
_score = 0;
char str_cache[256];
for (int idx = 0;; ++idx) {
snprintf(str_cache, 127, "register_trigger_%d", idx);
if (const char *descr = _runtime->parameter(str_cache, false))
_triggerEvents.push_back(_runtime->getObject(descr));
else
break;
}
debugC(2, kDebugMinigames, "EventManager(): registered %d trigger objects", _triggerEvents.size());
_eventPresets.resize(SYSTEM_EVENTS_SIZE);
for (int idx = 0; idx < SYSTEM_EVENTS_SIZE; ++idx) {
snprintf(str_cache, 127, "system_event_%d", idx);
if (const char * descr = _runtime->parameter(str_cache, false)) {
EventPreset preset;
int read = sscanf(descr, "%d %d", &preset.score, &preset.triggerEventID);
if (read != 2)
warning("EventManager(): Incorrect description string: %s", str_cache);
if (read == 2) {
if (preset.triggerEventID >= (int)_triggerEvents.size())
error("EventManager(): Reference to an unregistered trigger in %s", str_cache);
if (preset.triggerEventID < (int)_triggerEvents.size())
_eventPresets[idx] = preset;
}
}
}
for (int idx = 0;; ++idx) {
snprintf(str_cache, 127, "register_event_%d", idx);
if (const char * descr = _runtime->parameter(str_cache, false)) {
EventPreset preset;
int read = sscanf(descr, "%d %d %d %d", &preset.score, &preset.fontID, &preset.escapeID, &preset.triggerEventID);
if (read != 4)
warning("EventManager(): Incorrect event description string: %d", idx);
if (preset.triggerEventID >= (int)_triggerEvents.size())
error("EventManager(): Reference to an unregistered trigger in %s", str_cache);
if (read == 4 && preset.triggerEventID < (int)_triggerEvents.size())
_eventPresets.push_back(preset);
else
_eventPresets.push_back(EventPreset());
} else
break;
}
debugC(2, kDebugMinigames, "EventManager(): registered %d events", _eventPresets.size());
if (const char * data = _runtime->parameter("allow_negative", false)) {
int tmp;
sscanf(data, "%d", &tmp);
_enableNegative = tmp;
} else
_enableNegative = false;
}
void EventManager::sysEvent(int eventID) {
assert(eventID >= 0);
debugC(6, kDebugMinigames, "EventManager() System event: %d", eventID);
assert(eventID < SYSTEM_EVENTS_SIZE);
mgVect2i pos = _runtime->screenSize() / 2;
event(eventID - SYSTEM_EVENTS_SIZE, mgVect2f(pos.x, pos.y), 1);
}
void EventManager::event(int eventID, const mgVect2f& pos, int factor) {
debugC(6, kDebugMinigames, "EventManager() Event: %d, pos=(%5.1f, %5.1f), fartor=%d", eventID, pos.x, pos.y, factor);
eventID += SYSTEM_EVENTS_SIZE;
if (eventID >= (int)_eventPresets.size())
return;
const EventPreset& pr = _eventPresets[eventID];
if (pr.triggerEventID >= 0) {
assert(pr.triggerEventID < (int)_triggerEvents.size());
_triggerEvents[pr.triggerEventID]->set_state("on");
}
if (pr.score) {
int diff = addScore(pr.score);
if (pr.fontID >= 0 && pr.escapeID >= 0 && diff != 0)
_runtime->textManager().showNumber(diff, pos, pr.fontID, pr.escapeID);
}
}
int EventManager::addScore(int sc) {
int diff = _score;
_score += sc;
if (_score < 0 && !_enableNegative)
_score = 0;
diff = _score - diff;
if (diff)
_runtime->textManager().updateScore(_score);
return diff;
}
} // namespace QDEngine

View 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/>.
*
*/
#ifndef QDENGINE_MINIGAMES_ADV_EVENT_MANAGER_H
#define QDENGINE_MINIGAMES_ADV_EVENT_MANAGER_H
namespace QDEngine {
class EventManager {
public:
EventManager(MinigameManager *runtime);
void sysEvent(int eventID);
void event(int eventID, const mgVect2f& pos, int factor);
int score() const {
return _score;
}
int addScore(int sc);
private:
int _score;
bool _enableNegative;
struct EventPreset {
EventPreset();
int score;
int fontID;
int escapeID;
int triggerEventID;
};
typedef Std::vector<EventPreset> EventPresets;
EventPresets _eventPresets;
QDObjects _triggerEvents;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_EVENT_MANAGER_H

View 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/>.
*
*/
#include "common/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
qdMiniGameInterface *create_adv_minigame(const char *name, MinigameConsCallback callback) {
debugC(3, kDebugMinigames, "open_game_interface: %s, runtime%s", name, g_runtime ? "!=0" : "==0");
if (!g_runtime)
return g_runtime = new MinigameManager(callback);
return new MinigameManager(callback);
}
bool close_adv_minigame(qdMiniGameInterface *game) {
debugC(3, kDebugMinigames, "close_game_interface, runtime%s%s", g_runtime == game ? "==game" : "!=game", g_runtime ? "!=0" : "==0");
delete game;
if (game == g_runtime)
g_runtime = 0;
return true;
}
} // namespace QDEngine

View 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/>.
*
*/
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/FlyObject.h"
#include "qdengine/minigames/adv/qdMath.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
FlyObjectBase::FlyObjectBase(const mgVect2f& _c, const mgVect2f& _t, float _s)
: current(_c)
, target(_t)
, speed(_s) {
}
bool FlyObjectBase::quant(float dt) {
mgVect2f dir = target;
dir -= current;
float step = speed * dt;
if (abs(dir) < step) {
current = target;
return false;
}
norm(dir);
dir *= step;
current += dir;
return true;
}
bool FlyQDObject::quant(float dt, QDObject& obj, MinigameManager *runtime) {
bool ret = FlyObjectBase::quant(dt);
obj->set_R(runtime->game2world(current, depth));
return ret;
}
} // namespace QDEngine

View 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 QDENGINE_MINIGAMES_ADV_FLYOBJECT_H
#define QDENGINE_MINIGAMES_ADV_FLYOBJECT_H
namespace QDEngine {
struct FlyObjectBase {
FlyObjectBase(const mgVect2f& _c = mgVect2f(), const mgVect2f& _t = mgVect2f(), float _s = 1.f);
bool quant(float dt);
mgVect2f current;
mgVect2f target;
float speed;
};
struct FlyQDObject : public FlyObjectBase {
FlyQDObject(float dp = 0.f) : depth(dp), data(-1) {}
FlyQDObject(const FlyObjectBase& crd, float dp, int dat) : FlyObjectBase(crd), depth(dp), data(dat) {}
bool operator== (int dat) const {
return data == dat;
}
bool quant(float dt, QDObject& obj, MinigameManager *runtime);
float depth;
int data;
};
typedef Std::vector<FlyQDObject> FlyQDObjects;
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_FLYOBJECT_H

View 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 QDENGINE_MINIGAMES_ADV_HOLD_DATA_H
#define QDENGINE_MINIGAMES_ADV_HOLD_DATA_H
namespace QDEngine {
template <class T>
class HoldData {
T _emptyData;
T &_data;
bool _empty;
public:
HoldData() : _data(_emptyData), _empty(true) {}
HoldData(T* data, bool empty)
: _data(data ? * data : _emptyData) {
_empty = data ? empty : true;
}
void process(T& current) {
if (_empty) {
_data = current;
_empty = false;
} else
current = _data;
}
const T &get() const {
assert(!_empty);
return _data;
}
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_HOLD_DATA_H

View 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 QDENGINE_MINIGAMES_ADV_MINIGAME_INTERFACE_H
#define QDENGINE_MINIGAMES_ADV_MINIGAME_INTERFACE_H
namespace QDEngine {
class MinigameInterface {
public:
enum StateType {
NOT_INITED,
RUNNING,
GAME_WIN,
GAME_LOST
};
MinigameInterface() : _state(NOT_INITED) {}
virtual ~MinigameInterface() {}
virtual void quant(float dt) = 0;
void setState(StateType state) {
_state = state;
}
StateType state() const {
return _state;
}
private:
StateType _state;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_MINIGAME_INTERFACE_H

View File

@@ -0,0 +1,113 @@
/* 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 "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/ObjectContainer.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
ObjectContainer::ObjectContainer() {
_current = 0;
}
void ObjectContainer::release(MinigameManager *runtime) {
for (auto &it : _objects)
runtime->release(it);
_objects.clear();
_current = 0;
}
void ObjectContainer::pushObject(QDObject& obj) {
assert(Common::find(_objects.begin(), _objects.end(), obj) == _objects.end());
_objects.push_back(obj);
}
const char *ObjectContainer::name() const {
#ifdef _DEBUG
return _name.c_str();
#else
return "";
#endif
}
bool ObjectContainer::load(const char* base_name, MinigameManager *runtime, bool hide) {
if (!runtime->testObject(base_name)) {
warning("ObjectContainer::load(): Object '%s' not found", transCyrillic(base_name));
return false;
}
#ifdef _DEBUG
_name = base_name;
#endif
QDObject obj = runtime->getObject(base_name);
_coord = runtime->world2game(obj);
pushObject(obj);
if (hide)
runtime->hide(obj);
char name[128];
name[127] = 0;
for (int dubl = 0; ; ++dubl) {
snprintf(name, 127, "%s%04d", base_name, dubl);
if (runtime->testObject(name)) {
obj = runtime->getObject(name);
pushObject(obj);
if (hide)
runtime->hide(obj);
} else
break;
}
return true;
}
void ObjectContainer::hideAll(MinigameManager *runtime) {
for (auto &it : _objects)
runtime->hide(it);
}
QDObject ObjectContainer::getObject() {
if (_current < (int)_objects.size())
return _objects[_current++];
return _objects[0]; // bad, but better than crashing
}
void ObjectContainer::releaseObject(QDObject& obj, MinigameManager *runtime) {
QDObjects::iterator it = Common::find(_objects.begin(), _objects.end(), obj);
if (it != _objects.end()) {
if ((int)Common::distance(_objects.begin(), it) >= _current)
error("ObjectContainer::releaseObject(): Object released more than once in to the pool: %s", transCyrillic(name()));
runtime->hide(obj);
if (_current > 0)
SWAP(*it, _objects[--_current]);
obj = 0;
}
}
} // namespace QDEngine

View 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 QDENGINE_MINIGAMES_ADV_OBJECT_CONTAINER_H
#define QDENGINE_MINIGAMES_ADV_OBJECT_CONTAINER_H
namespace QDEngine {
class ObjectContainer {
QDObjects _objects;
int _current;
mgVect3f _coord;
#ifdef _DEBUG
Common::String _name;
#endif
const char *name() const;
void pushObject(QDObject& obj);
public:
ObjectContainer();
void release(MinigameManager *runtime);
bool load(const char *_name, MinigameManager *runtime, bool hide = true);
void hideAll(MinigameManager *runtime);
const mgVect3f &coord() const {
return _coord;
}
QDObject getObject();
void releaseObject(QDObject& obj, MinigameManager *runtime);
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_OBJECT_CONTAINER_H

View File

@@ -0,0 +1,98 @@
/* 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 "qdengine/minigames/adv/Range.h"
namespace QDEngine {
void Rangef::set(float min, float max) {
_min = min;
_max = max;
}
Rangef Rangef::intersection(const Rangef& range) {
float begin;
float end;
if (maximum() < range.minimum() || minimum() > range.maximum())
return Rangef(0.f, 0.f);
if (include(range.minimum()))
begin = range.minimum();
else
begin = minimum();
if (include(range.maximum()))
end = range.maximum();
else
end = maximum();
return Rangef(begin, end);
}
float Rangef::clip(float &value) const {
if (include(value))
return value;
else {
if (value < minimum())
return minimum();
else
return maximum();
}
}
// --------------------- Rangei
void Rangei::set(int min, int max) {
_min = min;
_max = max;
}
Rangei Rangei::intersection(const Rangei& range) {
int begin;
int end;
if (maximum() < range.minimum() || minimum() > range.maximum())
return Rangei(0, 0);
if (include(range.minimum()))
begin = range.minimum();
else
begin = minimum();
if (include(range.maximum()))
end = range.maximum();
else
end = maximum();
return Rangei(begin, end);
}
int Rangei::clip(int &value) {
if (include(value))
return value;
else {
if (value < minimum())
return minimum();
else
return maximum();
}
}
} // namespace QDEngine

View File

@@ -0,0 +1,141 @@
/* 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 QDENGINE_MINIGAMES_ADV_RANGE_H
#define QDENGINE_MINIGAMES_ADV_RANGE_H
namespace QDEngine {
class Rangef {
public:
Rangef(float min = 0.f, float max = 0.f)
: _min(min)
, _max(max)
{}
float minimum() const {
return _min;
}
void setMinimum(float min) {
_min = min;
}
float maximum() const {
return _max;
}
void setMaximum(float max) {
_max = max;
}
void set(float min, float max);
float length() const {
return _max - _min;
}
float center() const {
return (_max + _min) / 2.f;
}
/// Корректен ли интервал (нет - в случае когда minimum > maximum);
bool is_valid() const {
return _min <= _max;
}
/// Включает ли отрезок (закрытый интервал) точку \c _value.
bool include(float value) const {
return (_min <= value) && (_max >= value);
}
/// Включает ли интервал в себя \c _range.
bool include(const Rangef& range) const {
return _min <= range._min && _max >= range._max;
}
/// Возвращает пересечение интервала *this и \c _range.
Rangef intersection(const Rangef& range);
/// Возвращает \c _value в пределах интервала [minimum, maximum].
float clip(float &value) const;
private:
float _min;
float _max;
};
// --------------------- Rangei
class Rangei {
public:
Rangei(int min = 0.f, int max = 0.f)
: _min(min)
, _max(max)
{}
int minimum() const {
return _min;
}
void setMinimum(int min) {
_min = min;
}
int maximum() const {
return _max;
}
void setMaximum(int max) {
_max = max;
}
void set(int min, int max);
int length() const {
return _max - _min;
}
int center() const {
return (_max + _min) / 2;
}
/// Корректен ли интервал (нет - в случае когда minimum > maximum);
bool is_valid() const {
return _min <= _max;
}
/// Включает ли отрезок (закрытый интервал) точку \c _value.
bool include(int value) const {
return (_min <= value) && (_max >= value);
}
/// Включает ли интервал в себя \c _range.
bool include(const Rangei& range) const {
return _min <= range._min && _max >= range._max;
}
/// Возвращает пересечение интервала *this и \c _range.
Rangei intersection(const Rangei& range);
/// Возвращает \c _value в пределах интервала [minimum, maximum].
int clip(int &value);
private:
int _min;
int _max;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_RANGE_H

View File

@@ -0,0 +1,364 @@
/* 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 QDENGINE_MINIGAMES_ADV_RECT_H
#define QDENGINE_MINIGAMES_ADV_RECT_H
#include "qdengine/xmath.h"
#include "qdengine/minigames/adv/Range.h"
namespace QDEngine {
/*
* FIXME: Подразумевается, что left < right и top < bottom, добавить
* стратегию для кустомизации этого понятия?
*/
/// Абстрактый прямоугольник.
/**
* @param ScalarType - скалярный тип
* @param VectType - векторный тип
*/
template<typename scalar_type, class vect_type>
struct Rect {
typedef vect_type VectType;
typedef scalar_type ScalarType;
typedef Rect<ScalarType, VectType> RectType;
typedef Rangef RangeType;
// конструкторы
Rect() :
_left(ScalarType(0)),
_top(ScalarType(0)),
_width(ScalarType(0)),
_height(ScalarType(0)) {}
/// Создаёт Rect размера \a _size, левый-верхний угол остаётся в точке (0, 0).
Rect(const VectType& size) :
_top(ScalarType(0)),
_left(ScalarType(0)),
_width(size.x),
_height(size.y) {}
Rect(ScalarType left, ScalarType top, ScalarType width, ScalarType height) :
_left(left),
_top(top),
_width(width),
_height(height) {}
Rect(const VectType& _topleft, const VectType& size) :
_left(_topleft.x),
_top(_topleft.y),
_width(size.x),
_height(size.y) {}
void set(ScalarType left, ScalarType top, ScalarType width, ScalarType height) {
_left = left;
_top = top;
_width = width;
_height = height;
}
inline ScalarType left() const {
return _left;
}
inline ScalarType top() const {
return _top;
}
inline ScalarType width() const {
return _width;
}
inline ScalarType height() const {
return _height;
}
VectType _lefttop() const {
return VectType(_left, _top);
}
VectType right_top() const {
return VectType(_left + _width, _top);
}
VectType _leftbottom() const {
return VectType(_left, _top + _height);
}
VectType right_bottom() const {
return VectType(_left + _width, _top + _height);
}
// аксессоры (вычисляющие):
inline ScalarType right() const {
return _left + _width;
}
inline ScalarType bottom() const {
return _top + _height;
}
/*
* FIXME: для float и double деление на 2 лучше заменить на умножение на 0.5,
* для целых типов лучше исползовать сдвиг.
*/
/// Возвращает координаты цетра прямоугольника.
inline VectType center() const {
return VectType(_left + _width / ScalarType(2),
_top + _height / ScalarType(2));
}
/// Возвращает размер прямоугольника.
inline VectType size() const {
return VectType(_width, _height);
}
// сеттеры:
inline void left(ScalarType left) {
_left = left;
}
inline void top(ScalarType top) {
_top = top;
}
inline void width(ScalarType width) {
_width = width;
}
inline void height(ScalarType height) {
_height = height;
}
// сеттеры (вычисляющие):
inline void right(ScalarType right) {
_left = right - _width;
}
inline void bottom(ScalarType bottom) {
_top = bottom - _height;
}
/// Переносит центр прямоугольника в точку \a _center не изменяя его размер.
inline void center(const VectType& center) {
_left = center.x - _width / ScalarType(2);
_top = center.y - _height / ScalarType(2);
}
/*
* FIXME: размер должен менятся относительно левого-верхнего угла (как у
* сеттеров width и height) или относительно центра? Добавить
* класс-стратегию для этих целей? Фунцию с другим именем (напр
* scale (), которая принимает центр, относительно которого происходит
* скэлинг)?
*/
/// Устанавливает новые размеры, сохраняя левый-верхний угол в преждней точке.
inline void size(const VectType& size) {
_width = size.x;
_height = size.y;
}
// утилиты:
/// Проверяет не находится ли точка \a _point внутри прямоугольника
inline bool point_inside(const VectType& point) const {
if (point.x >= left() && point.y >= top() &&
point.x <= right() && point.y <= bottom())
return true;
else
return false;
}
/// Проверяет не находится ли прямоугольник \a _rect внутри прямоугольника
inline bool rect_inside(const RectType& rect) const {
if (rect.left() >= left() && rect.top() >= top() &&
rect.bottom() <= bottom() && rect.right() <= right())
return true;
else
return false;
}
inline bool rect_overlap(const RectType& rect) const {
if (left() > rect.right() || right() < rect.left()
|| top() > rect.bottom() || bottom() < rect.top())
return false;
return true;
}
/// Производит скэлинг.
/**
* Возвращает копию прямоугольника, над которой произведён скэлинг
* относительно точки \a _origin.
*/
inline RectType scaled(const VectType& scale, const VectType& origin) const {
return (*this - origin) * scale + origin;
}
/// Исправляет отрицательную ширину/высоту
inline void validate() {
if (width() < ScalarType(0)) {
left(left() + width());
width(-width());
}
if (height() < ScalarType(0)) {
top(top() + height());
height(-height());
}
}
inline RectType intersection(const RectType& rect) const {
RangeType xRange = RangeType(left(), right()).intersection(RangeType(rect.left(), rect.right()));
RangeType yRange = RangeType(top(), bottom()).intersection(RangeType(rect.top(), rect.bottom()));
return RectType(xRange.minimum(), yRange.minimum(), xRange.length(), yRange.length());
}
// Операторы
RectType operator+(const VectType& point) const {
return RectType(left() + point.x, top() + point.y,
width(), height());
}
RectType operator-(const VectType& point) const {
return RectType(left() - point.x, top() - point.y,
width(), height());
}
RectType operator*(const VectType& point) const {
return RectType(left() * point.x, top() * point.y,
width() * point.x, height() * point.y);
}
RectType operator*(const RectType& rhs) const {
VectType leftTop(left() + width() * rhs.left(), top() + height() * rhs.top());
VectType size(this->size() * rhs.size());
return RectType(leftTop, size);
}
RectType operator/(const RectType& rhs) const {
VectType leftTop((left() - rhs.left()) / rhs.width(), (top() - rhs.top()) / rhs.height());
VectType size(width() / rhs.width(), height() / rhs.height());
return RectType(leftTop, size);
}
RectType operator/(const VectType& point) const {
return RectType(left() / point.x, top() / point.y,
width() / point.x, height() / point.y);
}
bool operator==(const RectType& rect) const {
return (_left == rect._left && _top == rect._top &&
_width == rect._width && _height == rect._height);
}
bool eq(const RectType& rect, ScalarType eps = FLT_COMPARE_TOLERANCE) const {
return (abs(_left - rect._left) < eps && abs(_top - rect._top) < eps &&
abs(_width - rect._width) < eps && abs(_height - rect._height) < eps);
}
bool operator!=(const RectType& rect) const {
return (_left != rect._left || _top != rect._top ||
_width != rect._width || _height != rect._height);
}
protected:
ScalarType _left;
ScalarType _top;
ScalarType _width;
ScalarType _height;
#if 0
public:
// SideKick на этом обламывается:
template<class ST, class VT>
operator ::Rect<ST, VT>() const {
return ::Rect<ST, VT>(static_cast<ST>(left()),
static_cast<ST>(top()),
static_cast<ST>(width()),
static_cast<ST>(height()));
}
#endif
bool clipLine(VectType& pos0, VectType& pos1) const;
};
template<typename ScalarType, class VectType>
bool Rect<ScalarType, VectType>::clipLine(VectType& pos0, VectType& pos1) const {
VectType p0(pos0), p1(pos1);
bool b0 = point_inside(p0);
bool b1 = point_inside(p1);
if (b0 && b1) // вся линия внутри clip
return true;
else {
float tc;
float t[4] = {-1.0f, -1.0f, -1.0f, -1.0f};
int find = 0;
ScalarType dx = p1.x - p0.x;
ScalarType dy = p1.y - p0.y;
ScalarType crd;
if (abs(dy) > 0) {
tc = (float)(top() - p0.y) / dy;
if (tc >= 0.0f && tc <= 1.0f) {
crd = p0.x + tc * dx;
if (crd >= left() && crd <= right())
t[find++] = tc;
}
tc = (float)(bottom() - p0.y) / dy;
if (tc >= 0.0f && tc <= 1.0f) {
crd = p0.x + tc * dx;
if (crd >= left() && crd <= right())
t[find++] = tc;
}
}
if (abs(dx) > 0) {
tc = (float)(left() - p0.x) / dx;
if (tc >= 0.0f && tc <= 1.0f) {
crd = p0.y + tc * dy;
if (crd >= top() && crd <= bottom())
t[find++] = tc;
}
tc = (float)(right() - p0.x) / dx;
if (tc >= 0.0f && tc <= 1.0f) {
crd = p0.y + tc * dy;
if (crd >= top() && crd <= bottom())
t[find++] = tc;
}
}
if (b0) { //внутри только точка p0
pos1.set(p0.x + t[0]*dx, p0.y + t[0]*dy);
pos0.set(p0.x, p0.y);
} else if (b1) { //внутри только точка p1
pos0.set(p0.x + t[0]*dx, p0.y + t[0]*dy);
pos1.set(p1.x, p1.y);
} else if (find) { //обе точки снаружи, но часть отрезка внутри
if (t[0] < t[1]) {
pos0.set(p0.x + t[0]*dx, p0.y + t[0]*dy);
pos1.set(p0.x + t[1]*dx, p0.y + t[1]*dy);
} else {
pos1.set(p0.x + t[0]*dx, p0.y + t[0]*dy);
pos0.set(p0.x + t[1]*dx, p0.y + t[1]*dy);
}
} else
return false;
}
return true;
}
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_RECT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,318 @@
/* 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 QDENGINE_MINIGAMES_ADV_RUNTIME_H
#define QDENGINE_MINIGAMES_ADV_RUNTIME_H
#include "common/hashmap.h"
#include "qdengine/minigames/adv/common.h"
namespace Common {
class SeekableReadStream;
class SeekableWriteStream;
}
namespace QDEngine {
class qdEngineInterface;
class qdMinigameSceneInterface;
class MinigameInterface;
class TextManager;
class TimeManager;
class EventManager;
class EffectManager;
struct TimeManagerData {
mgVect3f crd;
};
struct EffectManagerData {
mgVect3f crd;
};
struct MinigameData {
MinigameData();
int _sequenceIndex;
int _lastScore;
int _lastTime;
int _bestTime;
int _bestScore;
void write(Common::WriteStream &out) const;
void read(Common::ReadStream &out);
};
struct GameInfo {
GameInfo();
void persist(Common::SeekableReadStream &in);
void write(Common::WriteStream &out) const;
void read(Common::ReadStream &in);
void free();
static int version() {
return 9;
}
bool empty() const {
return _empty && _game._sequenceIndex < 0;
}
MinigameData _game;
bool _empty;
TimeManagerData _timeManagerData;
EffectManagerData _effectManagerData;
uint _dataSize;
void *_gameData;
};
typedef MinigameInterface *(*MinigameConsCallback)(MinigameManager *runtime);
qdMiniGameInterface *create_adv_minigame(const char *name, MinigameConsCallback callback);
bool close_adv_minigame(qdMiniGameInterface *game);
class MinigameManager : public qdMiniGameInterface {
friend class TempValue;
public:
MinigameManager(MinigameConsCallback callback);
~MinigameManager();
// begin MiniGame virtual interface
bool init(const qdEngineInterface *engine_interface);
bool quant(float dt);
bool finit();
bool new_game(const qdEngineInterface *engine);
int save_game(const qdEngineInterface *engine, const qdMinigameSceneInterface *scene, char *buffer, int buffer_size);
int load_game(const qdEngineInterface *engine, const qdMinigameSceneInterface *scene, const char *buffer, int buffer_size);
// finish MiniGame virtual interface
// при необходимости заменяет на неизмененные предыдущим прохождением данные
bool processGameData(Common::SeekableReadStream &data);
mgVect2f mousePosition() const {
return _mousePos;
}
bool mouseLeftPressed() const;
bool mouseRightPressed() const;
bool keyPressed(int vKey, bool once = false) const;
mgVect2i screenSize() const {
return _screenSize;
}
float getTime() const {
return _gameTime;
}
GameInfo *getCurrentGameInfo() const { return _currentGameInfo; };
const MinigameData *getScore(int level, int game) const;
bool debugMode() const {
return _debugMode;
}
TextManager &textManager() const {
return *_textManager;
}
void signal(SystemEvent id);
void event(int eventID, const mgVect2f& pos, int factor = 1);
void event(int eventID, const mgVect2i& pos, int factor = 1) {
event(eventID, mgVect2f(pos.x, pos.y), factor);
}
// указывает вариант показа информации о победе (поворот собранной картинки и т.д.)
void setCompleteHelpVariant(int idx);
// указывает номер подсказки для показа, -1 - спрятать подсказку
void setGameHelpVariant(int idx);
// Возвращает параметр из прикрепленного к игре ini файла
const char *parameter(const char *name, bool required = true) const;
const char *parameter(const char *name, const char *def) const;
// Пересчитывает из экранных координат UI игры в 3D координаты R() объекта на мире
mgVect3f game2world(const mgVect3i &coord) const;
mgVect3f game2world(const mgVect3f &coord) const;
mgVect3f game2world(const mgVect2i &coord, int depth = 0) const;
mgVect3f game2world(const mgVect2f &coord, int depth = 0) const;
// Пересчитывает из мировых координат R() в 2D UI координаты и глубину
mgVect2f world2game(const mgVect3f& pos) const;
mgVect3f world2game(qdMinigameObjectInterface *obj) const;
// размер объекта
mgVect2f getSize(qdMinigameObjectInterface *obj) const;
// Меняет глубину объекта, не меняя его 2D положения на экране
void setDepth(qdMinigameObjectInterface *obj, int depth) const;
// Получает глубину объекта, чем меньше, тем ближе к игроку
float getDepth(qdMinigameObjectInterface *obj) const;
// Получает глубину точки, чем меньше, тем ближе к игроку
float getDepth(const mgVect3f& pos) const;
// получает интерфейс к динамическому игровому объекту по имени
QDObject getObject(const char *name) const;
// проверяет существование динамического объекта в сцене
bool testObject(const char *name) const;
// освобождает интерфейс
void release(QDObject& obj);
// задать текст для контрола
void setText(const char *name, const char *text) const;
void setText(const char *name, int toText, const char *format = "%d") const;
// спрятать объект за пределами экрана
void hide(qdMinigameObjectInterface *obj) const;
// случайное значение в диапазоне [min, max]
float rnd(float min, float max) const;
int rnd(int min, int max) const;
// случайный диапазон, из набора вероятностей
int rnd(const Std::vector<float> &prob) const;
// файл со списком игр по уровням
const char *gameListFileName() const {
return "resource/minigames.lst";
}
int getParameter(const char* name, const int& defValue);
bool getParameter(const char* name, int& out, bool obligatory);
float getParameter(const char* name, const float &defValue);
bool getParameter(const char* name, float &out, bool obligatory);
mgVect2f getParameter(const char* name, const mgVect2f& defValue);
bool getParameter(const char* name, mgVect2f& out, bool obligatory);
mgVect2i getParameter(const char* name, const mgVect2i& defValue);
bool getParameter(const char* name, mgVect2i& out, bool obligatory);
private:
MinigameInterface *_game;
// Вывод текста с помощью объектов
TextManager *_textManager;
// Подсчет и визуализация времени
TimeManager *_timeManager;
// Обработка событий игры
EventManager *_eventManager;
// выводимые эффекты
EffectManager *_effectManager;
// Время в секундах с момента стара игры
float _gameTime;
// кеш проверенных на нажатие клавиш, для отслеживания непосредственно нажатия
mutable bool _lastKeyChecked[256];
// Размер играна
mgVect2i _screenSize;
// текущее положение мыши
mgVect2f _mousePos;
// подстройка мыши
mgVect2f _mouseAdjast;
// объект для передачи сигнала об окончании игры в триггеры
qdMinigameObjectInterface *_state_flag;
// объект для получения сигнала о постановке на паузу
qdMinigameObjectInterface *_pause_flag;
// справка по победе
QDObject _complete_help;
QDObject _complete_help_miniature;
// текущее состояние для включения справки
Common::String _complete_help_state_name;
// справка по игре
QDObject _game_help;
QDObject _game_help_trigger;
bool _game_help_enabled;
// текущее состояние для включения справки
Common::String _game_help_state_name;
// интерфейс к движку
const qdEngineInterface *_engine;
// интерфейс к текущей сцене
qdMinigameSceneInterface *_scene;
// игра запущена для отладки
bool _debugMode;
// rnd seed
int _seed;
// кнопки мыши инвертированы
bool _invertMouseButtons;
// имя файла и информацией о минииграх
Common::String _state_container_name;
// количество пройденных игр на каждом уровне
typedef Common::HashMap<int, int> Counters;
Counters _completeCounters;
struct GameInfoIndex {
GameInfoIndex(int idx, int level) : _gameNum(idx), _gameLevel(level) {}
int _gameNum;
int _gameLevel;
void write(Common::WriteStream &out) const;
void read(Common::ReadStream &in);
bool operator< (const GameInfoIndex& rs) const {
return _gameLevel == rs._gameLevel ? _gameNum < rs._gameNum : _gameLevel < rs._gameLevel;
}
};
struct GameInfoIndex_Hash {
uint operator()(const GameInfoIndex& x) const {
return (x._gameNum << 16) + x._gameLevel;
}
};
struct GameInfoIndex_EqualTo {
uint operator()(const GameInfoIndex& x, const GameInfoIndex& y) const {
return x._gameNum == y._gameNum && x._gameLevel == y._gameLevel;
}
};
// информация о пройденных играх
typedef Common::HashMap<GameInfoIndex, GameInfo, GameInfoIndex_Hash, GameInfoIndex_EqualTo> GameInfoMap;
GameInfoMap _gameInfos;
// Информация о текущей игре, при выходе запишется
GameInfoIndex _currentGameIndex;
GameInfo *_currentGameInfo;
// проверить что все необходимые игры пройдены
bool testAllGamesWin();
// Непосредственно создает и инициализирует игру
bool createGame();
// обработка победы
void gameWin();
// обработка поражения
void gameLose();
// чтение данных об играх
bool loadState(bool current = true);
// сохранение данных в файл
void saveState(bool force = false);
// Полуить объект-счетчик
QDCounter getCounter(const char *name);
// Освободить счетчик
void release(QDCounter& counter);
MinigameConsCallback _callback = nullptr;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_RUNTIME_H

View File

@@ -0,0 +1,381 @@
/* 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/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/TextManager.h"
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/qdMath.h"
namespace QDEngine {
TextManager::TextManager(MinigameManager *runtime) {
char str_cache[256];
_runtime = runtime;
for (int idx = 0;; ++idx) {
snprintf(str_cache, 127, "register_font_%d", idx);
if (const char *descr = _runtime->parameter(str_cache, false)) {
sscanf(descr, "%255s", str_cache);
Font digit;
if (!digit.pool.load(str_cache, _runtime))
break;
debugCN(2, kDebugMinigames, "TextManager(): %d character set \"%s\" loaded, ", idx, str_cache);
snprintf(str_cache, 127, "font_size_%d", idx);
if ((descr = _runtime->parameter(str_cache, false))) {
int read = sscanf(descr, "%f %f", &digit.size.x, &digit.size.y);
if (read != 2)
warning("TextManager(): incorrect font size definition in [%s]", str_cache);
} else {
QDObject obj = digit.pool.getObject();
obj.setState("0");
digit.size = _runtime->getSize(obj);
digit.pool.releaseObject(obj, _runtime);
}
debugC(2, kDebugMinigames, "set size to (%5.1f, %5.1f)\n", digit.size.x, digit.size.y);
_fonts.push_back(digit);
} else
break;
}
for (int idx = 0;; ++idx) {
snprintf(str_cache, 127, "register_particle_escape_%d", idx);
if (const char *descr = _runtime->parameter(str_cache, false)) {
Escape escape;
int read = sscanf(descr, "%d (%f><%f, %f><%f) (%f><%f, %f><%f) %f '%15s",
&escape.depth,
&escape.vel_min.x, &escape.vel_max.x, &escape.vel_min.y, &escape.vel_max.y,
&escape.accel_min.x, &escape.accel_max.x, &escape.accel_min.y, &escape.accel_max.y,
&escape.aliveTime, escape.format);
if (read != 11) {
warning("TextManager(): incorrect particle definition in [%s]", str_cache);
break;
}
_escapes.push_back(escape);
} else
break;
}
debugCN(2, kDebugMinigames, "TextManager(): registered %d particle escapes", _escapes.size());
if (getStaticPreset(_show_scores, "show_scores"))
_show_scores.textID = createStaticText(_show_scores.pos, _show_scores.font, _show_scores.align);
else
_show_scores.textID = -1;
if (getStaticPreset(_show_time, "show_time"))
_show_time.textID = createStaticText(_show_time.pos, _show_time.font, _show_time.align);
else
_show_time.textID = -1;
_targetScore = 0;
_currentScore = 0;
_scoreUpdateTimer = 0.f;
_scoreUpdateTime = _runtime->getParameter("score_update_time", 0.1f);
}
bool TextManager::getStaticPreset(StaticTextPreset& preset, const char *name) const {
if (const char *descr = _runtime->parameter(name, false)) {
int align = 0;
char str[64];
str[63] = 0;
int read = sscanf(descr, "%d %d |%63s", &align, &preset.font, str);
if (read != 3) {
warning("TextManager::getStaticPreset(): Incorrect text format description in %s", transCyrillic(name));
return false;
}
char *pos_obj = strchr(str, '|');
if (!pos_obj) {
warning("TextManager::getStaticPreset(): Incorrect text format description (2) in %s", transCyrillic(name));
return false;
}
*pos_obj = 0;
++pos_obj;
strncpy(preset.format, str, 15);
switch (align) {
case 0:
preset.align = ALIGN_RIGHT;
break;
case 1:
preset.align = ALIGN_LEFT;
break;
default:
preset.align = ALIGN_CENTER;
break;
}
if (QDObject obj = _runtime->getObject(pos_obj)) {
preset.pos = _runtime->world2game(obj);
_runtime->release(obj);
} else
return false;
} else
return false;
return true;
}
TextManager::~TextManager() {
for (auto &mit : _flowMsgs)
mit.release();
for (auto &sit : _staticMsgs)
sit.release();
for (auto &dit : _fonts)
dit.pool.release(_runtime);
}
int TextManager::createStaticText(const mgVect3f& pos, int fontID, TextAlign align) {
assert(fontID >= 0 && fontID < (int)_fonts.size());
StaticMessage msg(_runtime, &_fonts[fontID]);
msg._align = align;
msg._depth = pos.z;
msg._pos = mgVect2f(pos.x, pos.y);
_staticMsgs.push_back(msg);
return (int)_staticMsgs.size() - 1;
}
void TextManager::updateStaticText(int textID, const char *txt) {
assert(textID >= 0 && textID < (int)_staticMsgs.size());
_staticMsgs[textID].setText(txt);
}
void TextManager::showText(const char *txt, const mgVect2f& pos, int fontID, int escapeID) {
assert(fontID >= 0 && fontID < (int)_fonts.size());
assert(escapeID >= 0 && escapeID < (int)_escapes.size());
Escape& es = _escapes[escapeID];
Message msg(_runtime, &_fonts[fontID]);
msg.setText(txt);
if (msg.empty())
return;
msg._time = es.aliveTime > 0 ? es.aliveTime : 1.e6f;
msg._depth = es.depth;
msg._pos = pos;
msg._vel.x = _runtime->rnd(es.vel_min.x, es.vel_max.x);
msg._vel.y = _runtime->rnd(es.vel_min.y, es.vel_max.y);
msg._accel.x = _runtime->rnd(es.accel_min.x, es.accel_max.x);
msg._accel.y = _runtime->rnd(es.accel_min.y, es.accel_max.y);
_flowMsgs.push_back(msg);
}
void TextManager::showNumber(int num, const mgVect2f& pos, int fontID, int escapeID) {
assert(fontID >= 0 && fontID < (int)_fonts.size());
assert(escapeID >= 0 && escapeID < (int)_escapes.size());
char buf[16];
buf[15] = 0;
snprintf(buf, 15, _escapes[escapeID].format, num);
showText(buf, pos, fontID, escapeID);
}
TextManager::Escape::Escape() {
depth = 0;
aliveTime = -1;
format[15] = 0;
}
TextManager::StaticTextPreset::StaticTextPreset() {
font = -1;
align = ALIGN_CENTER;
format[15] = 0;
textID = 0;
}
TextManager::StaticMessage::StaticMessage(MinigameManager *runtime, Font *font, TextAlign align) {
_font = font;
_align = align;
_depth = 0.f;
_runtime = runtime;
}
void TextManager::StaticMessage::release() {
for (auto &it : _objects)
_font->pool.releaseObject(it, _runtime);
_objects.clear();
}
void TextManager::StaticMessage::setText(const char *str) {
assert(_font);
if (!str) {
release();
return;
}
int len = (int)strlen(str);
if ((int)_objects.size() < len)
_objects.resize(len);
else
while ((int)_objects.size() > len) {
if (_objects.back())
_font->pool.releaseObject(_objects.back(), _runtime);
_objects.pop_back();
}
for (int idx = 0; idx < len; ++idx) {
if (validSymbol(str[idx])) {
if (!_objects[idx])
_objects[idx] = _font->pool.getObject();
} else if (_objects[idx])
_font->pool.releaseObject(_objects[idx], _runtime);
}
char name[2];
name[1] = 0;
for (int idx = 0; idx < len; ++idx) {
if (_objects[idx]) {
name[0] = str[idx];
_objects[idx].setState(name);
}
}
update();
}
void TextManager::StaticMessage::update() {
if (_objects.empty())
return;
float width = _font->size.x * (_objects.size() - 1);
float x = _pos.x;
float y = _pos.y;
switch (_align) {
case ALIGN_RIGHT:
x -= width;
break;
case ALIGN_CENTER:
x -= width / 2.f;
break;
default:
break;
}
if (y < -_font->size.y || y > _runtime->screenSize().y + _font->size.y
|| x < -2 * width || x > _runtime->screenSize().x + 2 * width) {
release();
return;
}
for (auto &it : _objects) {
if (it)
it->set_R(_runtime->game2world(mgVect2f(x, y), _depth));
x += _font->size.x;
}
}
TextManager::Message::Message(MinigameManager *runtime, Font *font)
: StaticMessage(runtime, font) {
_time = 0.f;
}
void TextManager::Message::release() {
StaticMessage::release();
_time = 0.f;
}
void TextManager::Message::quant(float dt) {
if (empty())
return;
_time -= dt;
if (_time < 0.f) {
release();
return;
}
_vel += _accel * dt;
_pos += _vel * dt;
update();
}
void TextManager::quant(float dt) {
Messages::iterator it = _flowMsgs.begin();
while (it != _flowMsgs.end()) {
it->quant(dt);
if (it->empty())
it = _flowMsgs.erase(it);
else
++it;
}
if (_show_scores.textID >= 0) {
if (_scoreUpdateTimer >= 0.f && _scoreUpdateTimer <= _runtime->getTime()) {
int sgn = _targetScore - _currentScore < 0 ? -1 : 1;
int mod = abs(_currentScore - _targetScore);
_currentScore += sgn * (mod / 10 + 1);
char buf[16];
buf[15] = 0;
snprintf(buf, 15, _show_scores.format, _currentScore);
updateStaticText(_show_scores.textID, buf);
_scoreUpdateTimer = _currentScore != _targetScore ? _runtime->getTime() + _scoreUpdateTime : -1.f;
}
}
}
void TextManager::updateScore(int score) {
_targetScore = score;
if (_scoreUpdateTimer < 0.f)
_scoreUpdateTimer = _runtime->getTime();
}
void TextManager::updateTime(int seconds) {
if (_show_time.textID >= 0) {
char buf[16];
buf[15] = 0;
int h = seconds / 3600;
seconds -= 3600 * h;
int minutes = seconds / 60;
seconds -= 60 * minutes;
snprintf(buf, 15, _show_time.format, h, minutes, seconds);
updateStaticText(_show_time.textID, buf);
}
}
} // namespace QDEngine

View File

@@ -0,0 +1,137 @@
/* 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 QDENGINE_MINIGAMES_ADV_TEXT_MANAGER_H
#define QDENGINE_MINIGAMES_ADV_TEXT_MANAGER_H
#include "qdengine/minigames/adv/ObjectContainer.h"
namespace QDEngine {
enum TextAlign {
ALIGN_LEFT,
ALIGN_RIGHT,
ALIGN_CENTER
};
class TextManager {
public:
TextManager(MinigameManager *runtime);
~TextManager();
int createStaticText(const mgVect3f& screen_pos, int fontID, TextAlign align);
void updateStaticText(int textID, const char *txt);
void showText(const char *txt, const mgVect2f& pos, int fontID, int escapeID);
void showNumber(int num, const mgVect2f& pos, int fontID, int escapeID);
void quant(float dt);
void updateScore(int score);
void updateTime(int seconds);
private:
struct Font {
mgVect2f size;
ObjectContainer pool;
};
typedef Std::vector<Font> Fonts;
struct Escape {
Escape();
int depth;
float aliveTime;
mgVect2f vel_min;
mgVect2f vel_max;
mgVect2f accel_min;
mgVect2f accel_max;
char format[16];
};
typedef Std::vector<Escape> Escapes;
struct StaticTextPreset {
StaticTextPreset();
mgVect3f pos;
int font;
TextAlign align;
char format[16];
int textID;
};
bool getStaticPreset(StaticTextPreset& preset, const char *name) const;
struct StaticMessage {
StaticMessage(MinigameManager *runtime, Font *font = 0, TextAlign _align = ALIGN_CENTER);
void release();
bool empty() const {
return _objects.empty();
}
void setText(const char *str);
int _depth;
mgVect2f _pos;
TextAlign _align;
protected:
void update();
bool validSymbol(unsigned char ch) const {
return ch > ' ' && ch != '_';
}
private:
Font *_font;
QDObjects _objects;
MinigameManager *_runtime;
};
typedef Std::vector<StaticMessage> StaticMessages;
struct Message : public StaticMessage {
Message(MinigameManager *runtime, Font *font = 0);
void release();
void quant(float dt);
float _time;
mgVect2f _vel;
mgVect2f _accel;
};
typedef Std::vector<Message> Messages;
Fonts _fonts;
Escapes _escapes;
StaticTextPreset _show_scores;
StaticTextPreset _show_time;
StaticMessages _staticMsgs;
Messages _flowMsgs;
int _targetScore;
int _currentScore;
float _scoreUpdateTime;
float _scoreUpdateTimer;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_TEXT_MANAGER_H

View 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/>.
*
*/
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
const char *QDObject::getName() const {
#ifdef _DEBUG
return _name.c_str();
#else
return "";
#endif
}
bool QDObject::hit(const mgVect2f& point) const {
return _obj->hit_test(mgVect2i(round(point.x), round(point.y)));
}
float QDObject::depth(MinigameManager *runtime) const {
return runtime->getDepth(_obj);
}
void QDObject::setState(const char* name) {
if (!_obj->is_state_active(name))
_obj->set_state(name);
}
} // namespace QDEngine

View File

@@ -0,0 +1,92 @@
/* 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 QDENGINE_MINIGAMES_ADV_COMMON_H
#define QDENGINE_MINIGAMES_ADV_COMMON_H
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class MinigameManager;
typedef mgVect3<int> mgVect3i;
class QDObject {
qdMinigameObjectInterface *_obj;
#ifdef _DEBUG
Common::String _name;
#endif
public:
QDObject(qdMinigameObjectInterface* obj = 0, const char* name = "") : _obj(obj) {
#ifdef _DEBUG
_name = name;
#endif
}
const char *getName() const; // DEBUG ONLY
bool hit(const mgVect2f& point) const;
float depth(MinigameManager *runtime) const;
void setState(const char* name);
bool operator==(const QDObject& obj) const {
return _obj == obj._obj;
}
bool operator==(const qdMinigameObjectInterface* obj) const {
return _obj == obj;
}
operator qdMinigameObjectInterface* () const {
return _obj;
}
qdMinigameObjectInterface* operator->() const {
return _obj;
}
};
typedef qdMinigameCounterInterface *QDCounter;
typedef Std::vector<QDObject> QDObjects;
typedef Std::vector<int> Indexes;
typedef Std::vector<mgVect3f> Coords;
class MinigameManager;
extern MinigameManager *g_runtime;
enum SystemEvent {
EVENT_TIME_1_SECOND_TICK,
EVENT_TIME_10_SECOND_TICK,
EVENT_TIME_60_SECOND_TICK,
EVENT_TIME_10_SECOND_LEFT,
EVENT_TIME_LESS_10_SECOND_LEFT_SECOND_TICK,
EVENT_TIME_OUT,
EVENT_GAME_LOSE,
EVENT_GAME_WIN,
SYSTEM_EVENTS_SIZE
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_COMMON_H

View File

@@ -0,0 +1,216 @@
/* 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/debug.h"
#include "common/file.h"
#include "common/system.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/m_karaoke.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
MinigameInterface *createMinigameKaraoke(MinigameManager *runtime) {
return new Karaoke(runtime);
}
Karaoke::Node::Node() {
type = Karaoke::CLEAR;
time = 0.f;
}
Karaoke::Karaoke(MinigameManager *runtime) {
_runtime = runtime;
_controlName = _runtime->parameter("control_name", true);
if (!_controlName || !*_controlName)
return;
_colorReaded = _runtime->parameter("color_first", true);
if (!_colorReaded || !*_colorReaded)
return;
struct Parse {
Common::File &file;
Nodes &nodes;
float currentTime;
char buf[1024];
const char *begin;
const char *cur;
void putLine(bool putEmpty = false) {
if (cur > begin && *begin) {
Node node;
node.type = STRING;
node.time = currentTime;
node.text = Common::String(begin, cur);
nodes.push_back(node);
} else if (putEmpty) {
Node node;
node.type = STRING;
node.time = currentTime;
nodes.push_back(node);
}
begin = cur = buf;
}
char read() {
if (!file.read((void *)cur, 1)) {
putLine();
return 0;
}
return *cur++;
}
Parse(Common::File& _file, Nodes& _nodes) : file(_file), nodes(_nodes) {
currentTime = 0.f;
begin = cur = buf;
bool prevNumber = false;
while (!file.eos()) {
switch (read()) {
case 0:
return;
case '/': {
if (read() == '/') {
--cur;
break;
}
cur -= 2;
putLine(prevNumber);
prevNumber = true;
file.seek(-1, SEEK_CUR);
float tm = 0;
char c;
do {
c = read();
} while ((c >= '0' && c <= '9') || c == '.');
cur = buf;
tm = strtod(cur, nullptr);
if (tm <= 0.f) {
currentTime = 0.f;
nodes.push_back(Node());
} else
currentTime = tm;
file.seek(-1, SEEK_CUR);
continue;
}
case '>':
if (prevNumber)
--cur;
}
prevNumber = false;
}
putLine();
}
};
const char *fileName = _runtime->parameter("text_file", true);
if (!fileName)
return;
Common::File file;
Common::Path path((const char *)transCyrillic(fileName), '\\');
if (!file.open(path)) {
// Try with punyencoded path
if (!file.open(path.punycodeEncode())) {
assert(!(Common::String() + "Не удалось открыть файл \"" + fileName + "\"").c_str());
return;
}
}
Parse(file, _nodes);
debugC(2, kDebugMinigames, "read %d tags", _nodes.size());
_startScreenTag = 0;
_currentTag = 0;
_startTime = 0.001f * g_system->getMillis();
_startTagTime = 0.f;
setState(MinigameInterface::RUNNING);
}
void Karaoke::quant(float dt) {
float curTime = 0.001f * g_system->getMillis() - _startTime;
if (curTime < 0.f)
curTime = 0.f;
Node& node = _nodes[_currentTag];
if (node.type == CLEAR) {
++_currentTag;
if ((uint)_currentTag == _nodes.size())
setState(MinigameInterface::GAME_WIN);
_startScreenTag = _currentTag;
return;
}
Common::String outText;
outText += _colorReaded;
int idx = _startScreenTag;
while (idx < _currentTag) {
assert((uint)idx < _nodes.size());
assert(_nodes[idx].type == STRING);
outText += _nodes[idx].text.c_str();
++idx;
}
float phase = (curTime - _startTagTime) / node.time;
assert(phase >= 0.f);
if (phase >= 1.f) {
outText += node.text + "&>";
++_currentTag;
_startTagTime += node.time;
if ((uint)_currentTag == _nodes.size())
setState(MinigameInterface::GAME_WIN);
} else {
int part = phase * node.text.size();
outText += Common::String(node.text.begin(), node.text.begin() + part) + "&>";
outText += Common::String(node.text.begin() + part, node.text.end()).c_str();
}
++idx;
while ((uint)idx < _nodes.size()) {
if (_nodes[idx].type == CLEAR)
break;
outText += _nodes[idx].text.c_str();
++idx;
}
if (_runtime->mouseRightPressed())
debugC(2, kDebugMinigames, "%s", outText.c_str());
_runtime->setText(_controlName, outText.c_str());
}
} // namespace QDEngine

View File

@@ -0,0 +1,66 @@
/* 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 QDENGINE_MINIGAMES_ADV_M_KARAOKE_H
#define QDENGINE_MINIGAMES_ADV_M_KARAOKE_H
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/MinigameInterface.h"
namespace QDEngine {
MinigameInterface *createMinigameKaraoke(MinigameManager *runtime);
class Karaoke : public MinigameInterface {
public:
Karaoke(MinigameManager *runtime);
void quant(float dt);
enum TagType {
STRING,
CLEAR
};
private:
const char *_controlName = nullptr;
const char *_colorReaded = nullptr;
struct Node {
Node();
TagType type;
float time;
Common::String text;
};
typedef Std::vector<Node> Nodes;
Nodes _nodes;
float _startTime = 0.f;
int _startScreenTag = 0;
int _currentTag = 0;
float _startTagTime = 0.f;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_M_KARAOKE_H

View File

@@ -0,0 +1,476 @@
/* 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/debug.h"
#include "common/memstream.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/m_puzzle.h"
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/Rect.h"
#include "qdengine/minigames/adv/qdMath.h"
#include "qdengine/system/input/keyboard_input.h"
namespace QDEngine {
typedef Rect<float, mgVect2f> Rectf;
MinigameInterface *createMinigamePuzzle(MinigameManager *runtime) {
return new Puzzle(runtime);
}
enum {
EVENT_GET,
EVENT_PUT,
EVENT_SWAP,
EVENT_ROTATE_IN_FIELD,
EVENT_RETURN,
EVENT_PUT_RIGHT,
EVENT_CLICK_RIGHT,
EVENT_CLICK,
EVENT_ROTATE_IN_STACK,
EVENT_FIELD_ROTATE
};
const char *Puzzle::getStateName(int angle, bool selected, bool small) const {
static const char *small_pref = "inv_";
static const char *selected_suf = "_sel";
static char buf[32];
buf[31] = 0;
assert(angle >= 0 && angle < _angles);
angle = (angle + _globalAngle) % _angles;
snprintf(buf, 31, "%s%02d%s", !_singleSize && small ? small_pref : "", angle + 1, selected ? selected_suf : "");
return buf;
}
Puzzle::Puzzle(MinigameManager *runtime) {
_runtime = runtime;
if (!_runtime->getParameter("game_size", _gameSize, true))
return;
assert(_gameSize > 0 && _gameSize < 100);
_field.resize(_gameSize, -1);
_globalAngle = 0;
_singleSize = _runtime->getParameter("small_objects", false);
_angles = _runtime->getParameter("angles", 4);
assert(_angles > 0 && _angles < 10);
if (!(_stackBottom = _runtime->getObject(_runtime->parameter("inventory_bottom"))))
return;
if (!_runtime->getParameter("inventory_size", _stackSize, true))
return;
if (_runtime->getParameter("rotate_period", _rotateTimePeriod, false)) {
assert(sqr(sqrt((float)_gameSize)) == _gameSize);
if (sqr(sqrt((float)_gameSize)) != _gameSize)
return;
} else
_rotateTimePeriod = 86400; // сутки
_nextRotateTime = _runtime->getTime() + _rotateTimePeriod;
_flySpeed = _runtime->getParameter("inventory_drop_speed", 240.f);
assert(_flySpeed > 0.f);
_returnSpeed = _runtime->getParameter("inventory_return_speed", -1.f);
const char *name_begin = _runtime->parameter("obj_name_begin", "obj_");
char buf[128];
buf[127] = 0;
Common::MemoryReadWriteStream gameData(DisposeAfterUse::YES);
for (int idx = 0; idx < _gameSize; ++idx) {
snprintf(buf, 127, "%s%02d", name_begin, idx + 1);
Node node;
node.obj = _runtime->getObject(buf);
if (_runtime->debugMode()) {
node.pos = _nodes.size();
node.angle = 0;
_field[node.pos] = node.pos;
} else
node.angle = _runtime->rnd(0, _angles - 1);
node.obj.setState(getStateName(node.angle, false, true));
node.obj->R().write(gameData);
_nodes.push_back(node);
}
if (!_runtime->processGameData(gameData))
return;
GameInfo *gameInfo = _runtime->getCurrentGameInfo();
if (gameInfo) {
Common::MemoryReadStream data((byte *)gameInfo->_gameData, gameInfo->_dataSize);
for (int idx = 0; idx < _gameSize; ++idx) {
mgVect3f crd;
crd.read(data);
_nodes[idx].obj->set_R(crd);
_positions.push_back(crd);
}
} else {
for (int idx = 0; idx < _gameSize; ++idx) {
mgVect3f crd;
crd.read(gameData);
_nodes[idx].obj->set_R(crd);
_positions.push_back(crd);
}
}
if (_runtime->debugMode())
_nodes[0].angle = _angles - 1;
_size = _runtime->getSize(_nodes[0].obj);
debugC(2, kDebugMinigames, "size = (%6.2f,%6.2f)", _size.x, _size.y);
_depth = _nodes[0].obj.depth(runtime);
_stackPlaceSize = _runtime->getParameter("inventory_place_size", _size * 1.2f);
assert(_stackPlaceSize.x > 0.f && _stackPlaceSize.x < 500.f && _stackPlaceSize.y > 0.f && _stackPlaceSize.y < 500.f);
debugC(2, kDebugMinigames, "stackPlaceSize = (%5.1f, %5.1f)", _stackPlaceSize.x, _stackPlaceSize.y);
_prevPlace = -1;
_pickedItem = -1;
_mouseObjPose = stidx(_stackSize + 1);
_inField = _runtime->debugMode() ? _nodes.size() : 0;
_nextObjTime = _runtime->getTime();
setState(MinigameInterface::RUNNING);
}
Puzzle::~Puzzle() {
for (auto &it : _nodes)
_runtime->release(it.obj);
_runtime->release(_stackBottom);
}
void Puzzle::rotate(int item) {
assert(item >= 0 && item < (int)_nodes.size());
_nodes[item].angle = (_nodes[item].angle + 1) % _angles;
}
int Puzzle::stidx(int idx) const {
return -idx - 2;
}
bool Puzzle::testPlace(int item) const {
assert(item >= 0 && item < (int)_nodes.size());
return _nodes[item].pos == item && _nodes[item].angle == 0;
}
bool Puzzle::isFlying(int idx) const {
for (auto &it : _flyObjs)
if (it.data == idx)
return true;
return false;
}
bool Puzzle::isOnMouse(const Node& node) const {
if (node.pos == _mouseObjPose) {
return true;
}
return false;
}
void Puzzle::put(int where, int what, float flowSpeed) {
assert(where < (int)_field.size());
assert(what >= 0 && what < (int)_nodes.size());
Node& node = _nodes[what];
int start = node.pos;
if (flowSpeed > 0.f || isFlying(what)) {
FlyQDObject* flyObj = 0;
FlyQDObjects::iterator fit;
for (fit = _flyObjs.begin(); fit != _flyObjs.end(); fit++) {
if (fit->data == what)
break;
}
if (fit != _flyObjs.end()) // Этот фрагмент уже летит, просто поменять точку назначения
flyObj = fit;
else { // Добавляем новый летящий фрагмент
_flyObjs.push_back(FlyQDObject());
flyObj = &_flyObjs.back();
flyObj->data = what;
mgVect3f from = isOnMouse(node) ? node.obj->R() : start < -1 ? stackPosition(stidx(start)) : position(start);
flyObj->current = _runtime->world2game(from);
node.obj->set_R(from);
flyObj->speed = flowSpeed;
}
mgVect3f to = where < -1 ? stackPosition(stidx(where)) : position(where);
flyObj->target = _runtime->world2game(to);
flyObj->depth = _runtime->getDepth(to);
}
if (where >= 0)
_field[where] = what;
node.pos = where;
}
void Puzzle::putOnStack(int what, float speed) {
put(stidx((int)_stack.size()), what, speed);
_stack.push_back(what);
}
void Puzzle::returnToStack() {
assert(_pickedItem != -1);
_runtime->event(EVENT_RETURN, _runtime->mousePosition());
if (_prevPlace >= 0)
put(_prevPlace, _pickedItem);
else
putOnStack(_pickedItem, _returnSpeed);
_prevPlace = -1;
_pickedItem = -1;
_runtime->event(EVENT_CLICK, _runtime->mousePosition());
}
void Puzzle::quant(float dt) {
if (_pickedItem == -1)
_runtime->setGameHelpVariant(0);
else
_runtime->setGameHelpVariant(1);
if (_runtime->getTime() > _nextRotateTime) {
_runtime->event(EVENT_FIELD_ROTATE, mgVect2f(400, 300));
_nextRotateTime = _runtime->getTime() + _rotateTimePeriod;
_globalAngle = (_globalAngle + 1) % _angles;
_runtime->setCompleteHelpVariant(_globalAngle);
}
FlyQDObjects::iterator fit = _flyObjs.begin();
while (fit != _flyObjs.end())
if (!isOnMouse(_nodes[fit->data]) && fit->quant(dt, _nodes[fit->data].obj, _runtime))
++fit;
else
fit = _flyObjs.erase(fit);
if (_inField < (int)_nodes.size() && _runtime->getTime() > _nextObjTime &&
((int)_stack.size() < _stackSize - 1 || ((int)_stack.size() < _stackSize && _pickedItem == -1))) { // нужно добавить в инвентори фишку
// ищем случайный не выставленный фрагмент
int freeIdx = round(_runtime->rnd(0.f, _nodes.size() - 1));
Nodes::iterator it = _nodes.begin();
for (;;) {
if (++it == _nodes.end())
it = _nodes.begin();
if (it->isFree())
if (!freeIdx--)
break;
}
int idx = Common::distance(_nodes.begin(), it);
++_inField;
_nextObjTime = _runtime->getTime() + _stackPlaceSize.y / _flySpeed;
it->pos = stidx(_stackSize);
it->obj.setState(getStateName(it->angle, false, true));
putOnStack(idx, _flySpeed);
}
mgVect2f mouse = _runtime->mousePosition();
int hovPlace = -1; // Номер места которое сейчас под мышкой
for (int idx = 0; idx < (int)_stack.size(); ++idx)
if (_nodes[_stack[idx]].obj.hit(mouse)) {
hovPlace = stidx(idx);
break;
}
if (hovPlace == -1) {
float radius = 0.5f * _size.x;
for (int idx = 0; idx < _gameSize; ++idx)
if (dist(_runtime->world2game(position(idx)), mouse) < radius) {
hovPlace = idx;
break;
}
}
if (hovPlace == -1) {
mgVect2i st = _stackBottom->screen_R();
st.y -= _stackPlaceSize.y * _stackSize - 0.5f * _stackPlaceSize.x;
Rectf stackPos(st.x - 0.5f * _stackPlaceSize.x, st.y, _stackPlaceSize.x, _stackPlaceSize.y * _stackSize);
if (stackPos.point_inside(mouse))
hovPlace = stidx(_stackSize);
}
if (_runtime->mouseLeftPressed()) {
if (hovPlace >= 0) { // клик по полю
Indexes::value_type& hovItem = _field[hovPlace];
if (hovItem == -1) // клик по пустой ячейке
if (_pickedItem == -1) // на мыши ничего нет
_runtime->event(EVENT_CLICK, mouse);
else { // кладем фрагмент с мыши
put(hovPlace, _pickedItem);
if (testPlace(_pickedItem)) // положили на свое свое место
_runtime->event(EVENT_PUT_RIGHT, mouse);
else // просто положили
_runtime->event(EVENT_PUT, mouse);
_pickedItem = -1;
_prevPlace = -1;
} else { // клик по непустой ячейке
if (testPlace(hovPlace)) // клик по правильно уложенной фишке
_runtime->event(EVENT_CLICK_RIGHT, mouse);
else if (_pickedItem != -1) { // поменять с тем что на мыше
bool swap = true;
if (_prevPlace >= 0)
put(_prevPlace, hovItem);
else
putOnStack(hovItem, _returnSpeed);
if (testPlace(hovItem)) { // оказалась при обмене на своем месте
_runtime->event(EVENT_PUT_RIGHT, _runtime->world2game(position(_prevPlace)));
swap = false;
}
put(hovPlace, _pickedItem);
if (testPlace(_pickedItem)) { // положили на свое свое место
_runtime->event(EVENT_PUT_RIGHT, mouse);
swap = false;
}
if (swap) // просто обменяли
_runtime->event(EVENT_SWAP, mouse);
_pickedItem = -1;
_prevPlace = -1;
} else { // взять фрагмент на мышь
_runtime->event(EVENT_GET, mouse);
_prevPlace = hovPlace;
_pickedItem = hovItem;
_nodes[_pickedItem].pos = _mouseObjPose;
hovItem = -1;
}
}
} else if (hovPlace < -1) { // клик по стеку
int hovStack = stidx(hovPlace);
if (_pickedItem == -1) // на мыши ничего нет
if (hovStack < (int)_stack.size()) { // взять фрагмент из стека на мышь
_runtime->event(EVENT_GET, mouse);
Indexes::iterator it = _stack.begin() + hovStack;
assert(*it >= 0);
_prevPlace = -1;
_pickedItem = *it;
_nodes[_pickedItem].pos = _mouseObjPose;
_stack.erase(it);
for (int idx = hovStack; idx < (int)_stack.size(); ++idx)
put(stidx(idx), _stack[idx], _flySpeed);
} else // пустой клик в области стека
_runtime->event(EVENT_CLICK, mouse);
else // вернуть фишку на место
returnToStack();
} else // пустой клик мимо игрового поля
_runtime->event(EVENT_CLICK, mouse);
} else if (_runtime->mouseRightPressed()) {
if (_pickedItem == -1) {
if (hovPlace >= 0) { // клик по полю
if (testPlace(hovPlace)) // клик по правильно уложенной фишке
_runtime->event(EVENT_CLICK_RIGHT, mouse);
else {
Indexes::value_type& hovItem = _field[hovPlace];
if (hovItem >= 0) {
rotate(hovItem);
if (testPlace(hovItem)) // повернули на правильный угол
_runtime->event(EVENT_PUT_RIGHT, mouse);
else // просто положили
_runtime->event(EVENT_ROTATE_IN_FIELD, mouse);
} else // попытка прокрутить пустое место
_runtime->event(EVENT_CLICK, mouse);
}
} else if (hovPlace < -1) { // клик по стеку
int hovStack = stidx(hovPlace);
if (hovStack < (int)_stack.size()) { // покрутить внутри стека
_runtime->event(EVENT_ROTATE_IN_STACK, mouse);
rotate(_stack[hovStack]);
} else // попытка прокрутить пустое место
_runtime->event(EVENT_CLICK, mouse);
} else // пустой клик мимо игрового поля
_runtime->event(EVENT_CLICK, mouse);
} else // вернуть фишку на место
returnToStack();
}
bool iWin = true;
for (int idx = 0; idx < (int)_nodes.size(); ++idx) {
Node& node = _nodes[idx];
if (node.pos != -1) {
if (node.pos >= 0) {
if (isFlying(idx))
node.obj.setState(getStateName(node.angle, false, false));
else {
node.obj.setState(getStateName(node.angle, node.pos == hovPlace && !testPlace(idx), false));
node.obj->set_R(position(node.pos));
}
} else if (idx == _pickedItem) {
node.obj.setState(getStateName(node.angle, hovPlace >= 0 && !testPlace(hovPlace), false));
node.obj->set_R(_runtime->game2world(mouse, _stackBottom.depth(_runtime) - 200));
} else {
node.obj.setState(getStateName(node.angle, node.pos == hovPlace && _pickedItem == -1, true));
if (!isFlying(idx))
node.obj->set_R(stackPosition(stidx(node.pos)));
}
iWin = iWin && testPlace(idx);
} else {
_runtime->hide(node.obj);
iWin = false;
}
}
if (iWin)
setState(GAME_WIN);
}
const mgVect3f &Puzzle::position(int num) const {
assert(num >= 0 && num < (int)_positions.size());
// Если глобальный поворот ненулевой, пересчитываем индекс
if (_globalAngle > 0) {
int size = sqrt((float)_gameSize);
int y = num / size;
int x = num - y * size;
--size;
for (int angle = 0; angle < _globalAngle; ++angle) {
int tmp = x;
x = size - y;
y = tmp;
}
num = y * (size + 1) + x;
}
assert(num >= 0 && num < (int)_positions.size());
return _positions[num];
}
mgVect3f Puzzle::stackPosition(int num) const {
mgVect3f bottom = _runtime->world2game(_stackBottom);
bottom.y -= _stackPlaceSize.y * num;
return _runtime->game2world(bottom);
}
} // namespace QDEngine

View File

@@ -0,0 +1,121 @@
/* 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 QDENGINE_MINIGAMES_ADV_M_PUZZLE_H
#define QDENGINE_MINIGAMES_ADV_M_PUZZLE_H
#include "qdengine/minigames/adv/MinigameInterface.h"
#include "qdengine/minigames/adv/FlyObject.h"
namespace QDEngine {
MinigameInterface *createMinigamePuzzle(MinigameManager *runtime);
class Puzzle : public MinigameInterface {
struct Node {
QDObject obj;
int angle;
int pos;
bool inStack() const {
return pos < -1;
}
bool isFree() const {
return pos == -1;
}
Node() : angle(1), pos(-1) {}
};
typedef Std::vector<Node> Nodes;
public:
Puzzle(MinigameManager *runtime);
~Puzzle();
void quant(float dt);
private:
int _gameSize = 0;
int _angles = 0;
int _globalAngle = 0;
float _rotateTimePeriod = 0.f;
float _nextRotateTime = 0.f;
bool _singleSize = false;
mgVect2f _size;
float _depth = 0.f;
Nodes _nodes;
/// Номер места с которого взяли фрагмент
int _prevPlace = -1;
/// Индекс фрагмента на мыши
int _pickedItem = -1;
int _inField = 0; // количество фрагментов на поле
float _nextObjTime = 0.f;
int _mouseObjPose = -1; // индекс положения фрагмента на мыши в стеке
QDObject _stackBottom;
int _stackSize = 0;
mgVect2f _stackPlaceSize;
Indexes _stack;
Indexes _field;
FlyQDObjects _flyObjs;
/// скорость падения новых в стек
float _flySpeed = 0.f;
/// скорость возврата в стек
float _returnSpeed = -1.f;
Coords _positions;
const char *getStateName(int angle, bool selected, bool small) const;
/// повернуть фишку
void rotate(int hovItem);
/// проверить нахождение фишки на своем месте
bool testPlace(int idx) const;
/// фишка на мыши?
bool isOnMouse(const Node& node) const;
/// проверить фишку на предмет самостоятельного управления позиционированием
bool isFlying(int idx) const;
/// конверсия между номером в стеке и индексом положения
int stidx(int idx) const;
/// положить what в ячейку where
void put(int where, int what, float flowSpeed = -1.f);
/// положить на вершину инвентори
void putOnStack(int what, float speed);
/// вернуть с мыши в инвентори
void returnToStack();
/// мировые координаты слота на поле
const mgVect3f &position(int num) const;
/// положение N-ой фишки в инвентори
mgVect3f stackPosition(int N) const;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_M_PUZZLE_H

View File

@@ -0,0 +1,245 @@
/* 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/debug.h"
#include "common/file.h"
#include "common/memstream.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/m_scores.h"
namespace QDEngine {
MinigameInterface *createMinigameScores(MinigameManager *runtime) {
return new Scores(runtime);
}
Scores::Scores(MinigameManager *runtime) {
_runtime = runtime;
const char *fileName = _runtime->parameter("minigame_list");
if (!fileName || !*fileName)
return;
if (!scumm_stricmp(fileName, _runtime->gameListFileName())) {
error("[minigame_list] must refer to \"%s\"", transCyrillic(_runtime->gameListFileName()));
}
const char *gameButtonName = _runtime->parameter("game_miniature_button");
if (!gameButtonName || !*gameButtonName)
return;
Common::MemoryReadWriteStream gameData(DisposeAfterUse::YES);
char name[128];
name[127] = 0;
for (int num = 1; ; ++num) {
snprintf(name, 127, "%s%02d", gameButtonName, num);
if (_runtime->testObject(name)) {
QDObject obj = _runtime->getObject(name);
obj->R().write(gameData);
_games.push_back(_runtime->getObject(name));
} else
break;
}
if (_games.empty()) {
error("Game images not found '%s'", transCyrillic(gameButtonName));
}
if (!_runtime->processGameData(gameData))
return;
_positions.resize(_games.size());
GameInfo *gameInfo = _runtime->getCurrentGameInfo();
if (gameInfo) {
Common::MemoryReadStream buf((byte *)gameInfo->_gameData, gameInfo->_dataSize);
for (auto &it : _positions)
it.read(buf);
} else {
for (auto &it : _positions)
it.read(gameData);
}
Common::File file;
if (!file.open(Common::Path(_runtime->gameListFileName()))) {
error("Failed to open games list file '%s'", transCyrillic(fileName));
}
char read_buf[512];
while (!file.eos()) {
file.readLine(read_buf, 512);
Common::MemoryReadStream buf((const byte *)&read_buf[0], strlen(read_buf));
int level = buf.readByte() - '0';
byte ch = buf.readByte();
if (ch != ':') {
error("Wrong file format");
}
Level lvl(level);
debugCN(2, kDebugMinigames, "%d: ", level);
while (buf.pos() < buf.size()) {
ch = buf.readByte();
if (Common::isDigit(ch)) {
int game = ch - '0';
lvl.games.push_back(game);
debugCN(2, kDebugMinigames, "%d, ", game);
if (const MinigameData *data = _runtime->getScore(level, game)) {
if (data->_sequenceIndex != -1)
lvl.data.push_back(GameData(game, *data));
}
}
}
if (lvl.games.size() > _games.size()) {
error("Not enough game images");
}
Common::sort(lvl.data.begin(), lvl.data.end());
levels_.push_back(lvl);
debugC(2, kDebugMinigames, "%s", "");
}
if (levels_.empty())
return;
Common::sort(levels_.begin(), levels_.end());
_level = 0;
_preLevel = -1;
if (!(_bestScore = _runtime->parameter("best_score")))
return;
if (!(_bestTime = _runtime->parameter("best_time")))
return;
if (!(_lastScore = _runtime->parameter("last_score")))
return;
if (!(_lastTime = _runtime->parameter("last_time")))
return;
if (!(_timeFormat = _runtime->parameter("time_format")))
return;
if (!(_currentLevel = _runtime->parameter("current_level")))
return;
if (!(_prev = _runtime->getObject(_runtime->parameter("prev_button"))))
return;
if (!(_next = _runtime->getObject(_runtime->parameter("next_button"))))
return;
if (!(_gameBorder = _runtime->getObject(_runtime->parameter("game_border"))))
return;
_outMaxLevel = _runtime->getObject(_runtime->parameter("for_game_level"));
if (_outMaxLevel) {
uint level = 0;
for (; level < levels_.size(); ++level)
if (levels_[level].data.size() < levels_[level].games.size())
break;
if (level < levels_.size())
_outMaxLevel.setState(Common::String::format("%d", levels_[level].level).c_str());
else
_outMaxLevel.setState("all");
}
setState(MinigameInterface::RUNNING);
}
Scores::~Scores() {
_runtime->release(_prev);
_runtime->release(_next);
for (auto &it : _games)
_runtime->release(it);
}
void Scores::quant(float dt) {
assert(_level >= 0 && _level < (int)levels_.size());
const Level& lvl = levels_[_level];
char timeBuf[32];
if (_level != _preLevel) {
_preLevel = _level;
_runtime->setText(_currentLevel, lvl.level);
for (int idx = 0; idx < (int)_games.size(); ++idx)
_runtime->hide(_games[idx]);
for (int idx = 0; idx < (int)_games.size(); ++idx) {
if (idx < (int)lvl.data.size()) {
const GameData& data = lvl.data[idx];
int gameId = data.num;
int gameNum;
for (gameNum = 0; gameNum < (int)lvl.games.size(); ++gameNum)
if (gameId == lvl.games[gameNum])
break;
assert(gameNum < (int)lvl.games.size());
assert(gameNum < (int)_games.size());
_games[gameNum].setState(Common::String::format("%d", _level).c_str());
_games[gameNum]->set_R(_positions[idx]);
_runtime->setText(getName(_bestScore, idx), data.info._bestScore);
if (!_timeFormat || !*_timeFormat)
snprintf(timeBuf, 31, "%d", data.info._bestTime);
else
snprintf(timeBuf, 31, _timeFormat, data.info._bestTime / 60, data.info._bestTime % 60);
_runtime->setText(getName(_bestTime, idx), timeBuf);
_runtime->setText(getName(_lastScore, idx), data.info._lastScore);
if (!_timeFormat || !*_timeFormat)
snprintf(timeBuf, 31, "%d", data.info._lastTime);
else
snprintf(timeBuf, 31, _timeFormat, data.info._lastTime / 60, data.info._lastTime % 60);
_runtime->setText(getName(_lastTime, idx), timeBuf);
} else {
_runtime->setText(getName(_bestScore, idx), "");
_runtime->setText(getName(_bestTime, idx), "");
_runtime->setText(getName(_lastScore, idx), "");
_runtime->setText(getName(_lastTime, idx), "");
}
}
}
_runtime->hide(_gameBorder);
for (int idx = 0; idx < (int)_games.size(); ++idx) {
if (_games[idx].hit(_runtime->mousePosition())) {
_gameBorder->set_R(_runtime->game2world(_runtime->world2game(_games[idx])));
break;
}
}
if (_runtime->mouseLeftPressed()) {
if (_level < (int)levels_.size() - 1 && lvl.data.size() == lvl.games.size() && _next.hit(_runtime->mousePosition()))
++_level;
else if (_level > 0 && _prev.hit(_runtime->mousePosition()))
--_level;
}
}
const char *Scores::getName(const char *begin, int idx) const {
static char buf[32];
buf[31] = 0;
snprintf(buf, 31, "%s%02d", begin, idx + 1);
return buf;
}
} // namespace QDEngine

View File

@@ -0,0 +1,88 @@
/* 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 QDENGINE_MINIGAMES_ADV_M_SCORES_H
#define QDENGINE_MINIGAMES_ADV_M_SCORES_H
#include "qdengine/minigames/adv/MinigameInterface.h"
#include "qdengine/minigames/adv/RunTime.h"
namespace QDEngine {
MinigameInterface *createMinigameScores(MinigameManager *runtime);
class Scores : public MinigameInterface {
public:
Scores(MinigameManager *runtime);
~Scores();
void quant(float dt);
private:
struct GameData {
GameData(int gameNum, const MinigameData& inf) : num(gameNum), info(inf) {}
int num;
MinigameData info;
bool operator< (const GameData& rsh) const {
return info._sequenceIndex < rsh.info._sequenceIndex;
}
};
typedef Std::vector<GameData> GameDatas;
struct Level {
Level(int lvl = 0) : level(lvl) {}
int level;
Indexes games;
GameDatas data;
bool operator< (const Level& rsh) const {
return level < rsh.level;
}
};
typedef Std::vector<Level> Levels;
Levels levels_;
const char *_currentLevel = nullptr;
const char *_bestScore = nullptr;
const char *_bestTime = nullptr;
const char *_lastScore = nullptr;
const char *_lastTime = nullptr;
const char *_timeFormat = nullptr;
QDObject _prev;
QDObject _next;
QDObject _gameBorder;
QDObject _outMaxLevel;
QDObjects _games;
int _preLevel = -1;
int _level = -1;
Coords _positions;
const char *getName(const char *begin, int idx) const;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_M_SCORES_H

View File

@@ -0,0 +1,301 @@
/* 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/debug.h"
#include "common/memstream.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/m_swap.h"
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/Rect.h"
namespace QDEngine {
typedef Rect<float, mgVect2f> Rectf;
MinigameInterface *createMinigameSwap(MinigameManager *runtime) {
return new Swap(runtime);
}
enum {
EVENT_GET,
EVENT_SWAP,
EVENT_ROTATE,
EVENT_RETURN,
EVENT_PUT_RIGHT,
EVENT_GET_RIGHT,
EVENT_CLICK,
EVENT_AUTO_ROTATE
};
const char *Swap::getStateName(int angle, bool selected) const {
static const char *selected_suf = "_sel";
static char buf[32];
buf[31] = 0;
assert(angle >= 0 && angle < _angles);
snprintf(buf, 31, "%02d%s", angle + 1, selected ? selected_suf : "");
return buf;
}
Swap::Swap(MinigameManager *runtime) {
_runtime = runtime;
if (!_runtime->getParameter("game_size", _gameSize, true) || _gameSize < 2)
return;
if ((_angles = _runtime->getParameter("angles", 4)) < 1)
return;
if ((_rotateTimePeriod = _runtime->getParameter("rotate_period", 86400.f)) < 10.f)
return;
_nextRotateTime = _runtime->getTime() + _rotateTimePeriod;
const char *name_begin = _runtime->parameter("obj_name_begin", "obj_");
Common::MemoryReadWriteStream gameData(DisposeAfterUse::YES);
for (int idx = 0; idx < _gameSize; ++idx) {
Common::String buf = Common::String::format("%s%02d", name_begin, idx + 1);
Node node(idx);
node.obj = _runtime->getObject(buf.c_str());
node.angle = 0;
node.obj.setState(getStateName(node.angle, false));
_nodes.push_back(node);
node.obj->R().write(gameData);
}
if (!_runtime->processGameData(gameData))
return;
_positions.resize(_gameSize);
GameInfo *gameInfo = _runtime->getCurrentGameInfo();
if (gameInfo) {
Common::MemoryReadStream buf((byte *)gameInfo->_gameData, gameInfo->_dataSize);
for (auto &it : _positions)
it.read(buf);
} else {
for (auto &it : _positions)
it.read(gameData);
}
_size = _runtime->getParameter("element_size", _runtime->getSize(_nodes[0].obj));
assert(_size.x > 0.f && _size.y > 0.f && _size.x < 500.f && _size.y < 500.f);
debugC(2, kDebugMinigames, "element_size = (%6.2f,%6.2f)", _size.x, _size.y);
_pickedItem = -1;
_last1 = _last2 = -1;
if (_runtime->debugMode()) {
_last1 = 0;
_last2 = 1;
rotate(_last1, _last2, false);
} else
for (int cnt = 0; cnt < 50; ++cnt) {
rotate(_runtime->rnd(0, _gameSize - 1), _runtime->rnd(0, _gameSize - 1), true, true);
swap(_runtime->rnd(0, _gameSize - 1), _runtime->rnd(0, _gameSize - 1), true);
}
setState(MinigameInterface::RUNNING);
}
Swap::~Swap() {
for (auto &it : _nodes)
_runtime->release(it.obj);
}
void Swap::quant(float dt) {
if (_pickedItem >= 0)
_runtime->setGameHelpVariant(1);
else if (_last1 >= 0)
_runtime->setGameHelpVariant(2);
else
_runtime->setGameHelpVariant(0);
if (_runtime->getTime() > _nextRotateTime) {
int item1 = _runtime->rnd(0, _gameSize - 1);
int item2 = _runtime->rnd(0, _gameSize - 1);
if (item1 != _last1 && item1 != _last2 && item1 != _pickedItem && item2 != _last1 && item2 != _last2 && item2 != _pickedItem) {
_nextRotateTime = _runtime->getTime() + _rotateTimePeriod;
rotate(item1, item2, false, true);
_runtime->event(EVENT_AUTO_ROTATE, mgVect2f(400, 300));
return;
}
}
mgVect2f mouse = _runtime->mousePosition();
int hovPlace = -1; // Номер места которое сейчас под мышкой
if (_pickedItem == -1) {
for (auto &it : _nodes)
if (it.obj.hit(mouse)) {
hovPlace = Common::distance(_nodes.begin(), &it);
break;
}
}
if (hovPlace == -1)
for (int idx = 0; idx < _gameSize; ++idx) {
Rectf rect(_size * 0.9f);
rect.center(_runtime->world2game(position(idx)));
if (rect.point_inside(mouse)) {
hovPlace = idx;
break;
}
}
if (_runtime->mouseLeftPressed()) {
if (hovPlace >= 0) { // клик по полю
if (_pickedItem == -1) { // мышь пустая, берем
deactivate();
_runtime->event(EVENT_GET, mouse);
_pickedItem = hovPlace;
} else if (_pickedItem == hovPlace) { // вернуть на место
_runtime->event(EVENT_RETURN, mouse);
put(_pickedItem, false);
_pickedItem = -1;
} else { // поменять местами
_last1 = _pickedItem;
_last2 = hovPlace;
swap(_last1, _last2, false);
_pickedItem = -1;
}
} else { // пустой клик мимо игрового поля
deactivate();
_runtime->event(EVENT_CLICK, mouse);
}
} else if (_runtime->mouseRightPressed()) {
if (_pickedItem >= 0) // если на мыши фрагмент ничего не делаем
_runtime->event(EVENT_CLICK, mouse);
else if (hovPlace == _last1 || hovPlace == _last2) // клик по выделенным
rotate(_last1, _last2, false);
else // пустой клик мимо активного места
_runtime->event(EVENT_CLICK, mouse);
}
if (_pickedItem >= 0)
_nodes[_pickedItem].obj->set_R(_runtime->game2world(mouse, -5000));
int idx = 0;
for (; idx < _gameSize; ++idx)
if (!testPlace(idx))
break;
if (idx == (int)_nodes.size()) {
deactivate();
setState(MinigameInterface::GAME_WIN);
}
}
const mgVect3f &Swap::position(int num) const {
assert(num >= 0 && num < (int)_positions.size());
return _positions[num];
}
void Swap::put(int item, bool hl) {
assert(item >= 0 && item < (int)_nodes.size());
_nodes[item].obj->set_R(position(item));
_nodes[item].obj.setState(getStateName(_nodes[item].angle, hl));
}
void Swap::deactivate() {
if (_last1 >= 0) {
assert(_last2 >= 0);
put(_last1, false);
put(_last2, false);
}
_last1 = -1;
_last2 = -1;
}
bool Swap::testPlace(int item) const {
assert(item >= 0 && item < (int)_nodes.size());
return _nodes[item].home == item && _nodes[item].angle == 0;
}
void Swap::swap(int item1, int item2, bool silent) {
assert(item1 >= 0 && item1 < (int)_nodes.size());
assert(item2 >= 0 && item2 < (int)_nodes.size());
bool res = false;
if (!silent) {
if (testPlace(item1)) { // сняли со своего места
_runtime->event(EVENT_GET_RIGHT, _runtime->world2game(position(item1)));
res = true;
}
if (testPlace(item2)) { // сняли со своего места
_runtime->event(EVENT_GET_RIGHT, _runtime->world2game(position(item2)));
res = true;
}
}
SWAP(_nodes[item1], _nodes[item2]);
put(item1, !silent);
put(item2, !silent);
if (!silent) {
if (testPlace(item1)) { // оказалась при обмене на своем месте
_runtime->event(EVENT_PUT_RIGHT, _runtime->world2game(position(item1)));
res = true;
}
if (testPlace(item2)) { // положили на свое свое место
_runtime->event(EVENT_PUT_RIGHT, _runtime->world2game(position(item2)));
res = true;
}
if (!res) // просто обменяли
_runtime->event(EVENT_SWAP, _runtime->mousePosition());
}
}
void Swap::rotate(int item1, int item2, bool silent, bool avto) {
assert(item1 >= 0 && item1 < (int)_nodes.size());
assert(item2 >= 0 && item2 < (int)_nodes.size());
if (!silent) {
if (testPlace(item1)) // сняли со своего места
_runtime->event(EVENT_GET_RIGHT, _runtime->world2game(position(item1)));
if (testPlace(item2)) // сняли со своего места
_runtime->event(EVENT_GET_RIGHT, _runtime->world2game(position(item2)));
}
_nodes[item1].angle = (_nodes[item1].angle + 1) % _angles;
_nodes[item2].angle = (_nodes[item2].angle + 1) % _angles;
put(item1, !avto);
put(item2, !avto);
if (!silent) {
if (testPlace(item1)) // оказалась при обмене на своем месте
_runtime->event(EVENT_PUT_RIGHT, _runtime->world2game(position(item1)));
if (testPlace(item2)) // положили на свое свое место
_runtime->event(EVENT_PUT_RIGHT, _runtime->world2game(position(item2)));
_runtime->event(EVENT_ROTATE, _runtime->mousePosition());
}
}
} // namespace QDEngine

View File

@@ -0,0 +1,81 @@
/* 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 QDENGINE_MINIGAMES_ADV_M_SWAP_H
#define QDENGINE_MINIGAMES_ADV_M_SWAP_H
#include "qdengine/minigames/adv/MinigameInterface.h"
namespace QDEngine {
MinigameInterface *createMinigameSwap(MinigameManager *runtime);
class Swap : public MinigameInterface {
public:
Swap(MinigameManager *runtime);
~Swap();
void quant(float dt);
private:
int _gameSize = 0;
int _angles = 0;
float _rotateTimePeriod = 0.5f; // время поворота фишки
float _nextRotateTime = 0.f; // время следующего поворота
mgVect2f _size;
struct Node {
Node(int idx = -1) : home(idx), angle(0) {}
QDObject obj;
int angle;
int home;
};
typedef Std::vector<Node> Nodes;
Nodes _nodes;
// Индекс фрагмента на мыши
int _pickedItem = -1;
// активные фрагменты после обмена
int _last1 = 0, _last2 = 0;
Coords _positions;
const char *getStateName(int angle, bool selected) const;
// поменять местами, если было снятие или укладка на/с правильного места, то true
void swap(int item1, int item2, bool silent);
// повернуть фишку
void rotate(int item1, int item2, bool silent, bool avto = false);
// погасить выделенные
void deactivate();
// проверить нахождение фишки на своем месте
bool testPlace(int idx) const;
// поставить объект на свое место и включить нужное состояние
void put(int idx, bool hl);
// мировые координаты слота на поле
const mgVect3f &position(int num) const;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_M_SWAP_H

View File

@@ -0,0 +1,639 @@
/* 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/debug.h"
#include "common/memstream.h"
#include "qdengine/qdengine.h"
#include "qdengine/minigames/adv/m_triangles.h"
#include "qdengine/minigames/adv/RunTime.h"
#include "qdengine/minigames/adv/EventManager.h"
#include "qdengine/minigames/adv/qdMath.h"
namespace QDEngine {
MinigameInterface *createMinigameTriangle(MinigameManager *runtime) {
return new MinigameTriangle(runtime);
}
enum {
EVENT_TURN,
EVENT_GET_RIGHT,
EVENT_PUT_RIGHT
};
MinigameTriangle::Node::Node(int number, int rot) {
_number = number;
_rotation = rot;
_isBack = false;
_highlight = false;
_animated = false;
_flip = 0;
}
void MinigameTriangle::Node::release(MinigameManager *runtime) {
for (auto &it : _face)
runtime->release(it);
}
bool MinigameTriangle::Node::hit(const mgVect2f &pos) const {
return obj().hit(pos);
}
MinigameTriangle::MinigameTriangle(MinigameManager *runtime) {
_runtime = runtime;
int type = 0;
if (!_runtime->getParameter("game_type", type, true))
return;
switch (type) {
case 1:
_gameType = RECTANGLE;
break;
case 2:
_gameType = HEXAGON;
break;
default:
_gameType = TRIANGLE;
}
_fieldLines = _fieldWidth = 0;
if (!_runtime->getParameter("size", _fieldLines, true))
return;
if (_fieldLines < 2)
return;
if (_gameType == RECTANGLE) {
if (!_runtime->getParameter("width", _fieldWidth, true))
return;
if (_fieldWidth < 2)
return;
}
switch (_gameType) {
case TRIANGLE:
_fieldSize = sqr(_fieldLines);
break;
case RECTANGLE:
_fieldSize = _fieldLines * _fieldWidth;
break;
case HEXAGON:
assert(_fieldLines % 2 == 0);
if (_fieldLines % 2 != 0)
return;
_fieldSize = 3 * sqr(_fieldLines) / 2;
break;
}
if (!_runtime->getParameter("animation_time", _animationTime, true))
return;
_quickReselect = _runtime->getParameter("quick_reselect", false);
const char *faceNameBegin = _runtime->parameter("object_name_begin", "obj_");
const char *backNameBegin = _runtime->parameter("backg_name_begin", "element__back");
const char *selectNameBegin = _runtime->parameter("select_name_begin", "element_select_");
char name[64];
name[63] = 0;
for (int num = 0; num < _fieldSize; ++num) {
_nodes.push_back(Node(num, 0));
Node &node = _nodes.back();
for (int angle = 1; angle <= 3; ++angle) {
snprintf(name, 63, "%s%02d_%1d", faceNameBegin, num + 1, angle);
debugC(5, kDebugMinigames, "Loading face object: %s", name);
QDObject obj = _runtime->getObject(name);
node._face.push_back(obj);
_positions.push_back(obj->R());
}
}
Common::MemoryReadWriteStream gameData(DisposeAfterUse::YES);
for (auto &it : _positions)
it.write(gameData);
if (!_runtime->processGameData(gameData))
return;
GameInfo *gameInfo = _runtime->getCurrentGameInfo();
if (gameInfo) {
Common::MemoryReadStream buf((byte *)gameInfo->_gameData, gameInfo->_dataSize);
for (auto &it : _positions)
it.read(buf);
} else {
for (auto &it : _positions)
it.read(gameData);
}
for (int num = 1; num <= 2; ++num) {
for (int angle = 1; angle <= 3; ++angle) {
snprintf(name, 63, "%s%1d_%1d", backNameBegin, num, angle);
debugC(5, kDebugMinigames, "Loading back object: %s", name);
if (!_backSides[(num - 1) * 3 + angle - 1].load(name, _runtime))
return;
}
snprintf(name, 63, "%s%1d", selectNameBegin, num);
debugC(5, kDebugMinigames, "Loading select object: %s", name);
if (!_selectBorders[num - 1].load(name, _runtime))
return;
}
_selectDepth = _nodes[0]._face[0].depth(_runtime) - 1000;
_selected = -1;
_hovered = -1;
_animationState = NO_ANIMATION;
_animatedNodes[0] = _animatedNodes[1] = -1;
_animationTimer = 0.f;
if (!_runtime->debugMode())
for (int i = 0; i < 150; ++i) {
int pos1 = _runtime->rnd(0, _nodes.size() - 1);
for (int j = 0; j < 20; ++j) {
int pos2 = _runtime->rnd(pos1 - 10, pos1 + 10);
if (compatible(pos1, pos2)) {
swapNodes(pos1, pos2, true);
break;
}
}
}
for (int idx = 0; idx < _fieldSize; ++idx)
updateNode(_nodes[idx], idx);
setState(RUNNING);
}
MinigameTriangle::~MinigameTriangle() {
for (auto &it : _nodes)
it.release(_runtime);
for (int idx = 0; idx < 2; ++idx)
_selectBorders[idx].release(_runtime);
for (int idx = 0; idx < 6; ++idx)
_backSides[idx].release(_runtime);
}
void MinigameTriangle::Node::debugInfo() const {
debugC(5, kDebugMinigames, "name:\"%s\" state:\"%s\" number:%d rotation:%d flip:%d isBack:%d highlight:%d animated:%d", obj().getName(), obj()->current_state_name(), _number, _rotation, _flip, _isBack, _highlight, _animated);
}
const Common::String MinigameTriangle::Node::getFaceStateName(int angle, bool selected, bool animated, bool instantaneous) {
assert(!selected || !animated); // анимированные выделенными быть не могут
static const char *angleNames[3] = {"0", "120", "240"};
assert(angle >= 0 && angle < ARRAYSIZE(angleNames));
Common::String out;
out = Common::String::format("%s%s%s", (animated ? "02_" : "01_"), angleNames[angle], (selected || instantaneous ? "_sel" : ""));
return out;
}
const char *MinigameTriangle::Node::getBackStateName(bool selected, bool animated, bool instantaneous) {
assert(!selected || !animated); // анимированные выделенными быть не могут
if (animated)
return selected || instantaneous ? "02_sel" : "02";
else
return selected || instantaneous ? "01_sel" : "01";
}
const char *MinigameTriangle::Node::getBorderStateName(bool selected) {
return selected ? "01" : "02";
}
void MinigameTriangle::releaseNodeBack(Node &node) {
if (node._back) {
node._back.setState(Node::getBackStateName(false, false, false));
for (int type = 0; type < 6; ++type)
_backSides[type].releaseObject(node._back, _runtime);
}
}
void MinigameTriangle::updateNode(Node &node, int position, int flip, bool quick) {
for (auto &fit : node._face)
_runtime->hide(fit);
node._flip = flip;
if (node._isBack) {
if (!node._back)
node._back = _backSides[orientation(position) * 3 + flip].getObject();
node._back->set_R(slotCoord(position, flip));
node._back->update_screen_R();
node._back.setState(Node::getBackStateName(node._highlight, node._animated, quick));
} else {
releaseNodeBack(node);
QDObject &face = node._face[flip];
face->set_R(slotCoord(position, flip));
face->update_screen_R();
face.setState(Node::getFaceStateName(node._rotation, node._highlight, node._animated, quick).c_str());
}
}
void MinigameTriangle::highlight(int idx, bool hl) {
if (idx >= 0) {
assert(idx < (int)_nodes.size());
_nodes[idx]._highlight = hl;
updateNode(_nodes[idx], idx);
}
}
void MinigameTriangle::beginSwapNodes(int pos1, int pos2) {
assert(compatible(pos1, pos2));
if (pos1 > pos2)
SWAP(pos1, pos2);
_animationState = FIRST_PHASE;
_animationTimer = _animationTime;
_animatedNodes[0] = pos1;
_animatedNodes[1] = pos2;
Node &node1 = _nodes[pos1];
Node &node2 = _nodes[pos2];
node1._animated = true;
node2._animated = true;
releaseNodeBack(node1);
releaseNodeBack(node2);
updateNode(node1, pos1, destination(pos1, pos2));
updateNode(node2, pos2, destination(pos1, pos2));
debugC(5, kDebugMinigames, ">>>>>>>>>>>>>>>>>>>>>>>>>>> change %d <> %d, 1st phase <<<<<<<<<<<<<<<<<<<<<<<<<<<<", pos1, pos2);
_nodes[pos1].debugInfo();
_nodes[pos2].debugInfo();
}
void MinigameTriangle::endSwapNodes(int pos1, int pos2) {
Node &node1 = _nodes[pos1];
Node &node2 = _nodes[pos2];
bool counted = false;
if (node1._number == pos1) { // поставили на свое место
assert(!node1._isBack);
counted = true;
_runtime->event(EVENT_PUT_RIGHT, node1.obj()->screen_R());
}
if (node2._number == pos1) { // сняли со своего места
assert(node2._isBack);
counted = true;
_runtime->event(EVENT_GET_RIGHT, node1.obj()->screen_R());
}
if (node2._number == pos2) { // поставили на свое место
assert(!node2._isBack);
counted = true;
_runtime->event(EVENT_PUT_RIGHT, node2.obj()->screen_R());
}
if (node1._number == pos2) { // сняли со своего места
assert(node1._isBack);
counted = true;
_runtime->event(EVENT_GET_RIGHT, node2.obj()->screen_R());
}
if (!counted) { // просто сделали ход
mgVect2i pos = node1.obj()->screen_R();
pos += node2.obj()->screen_R();
pos /= 2;
_runtime->event(EVENT_TURN, pos);
}
bool isWin = true;
int position = 0;
for (auto &it : _nodes) {
if (it._number != position++) {
isWin = false;
break;
}
}
if (isWin) {
setState(GAME_WIN);
return;
}
}
bool MinigameTriangle::animate(float dt) {
if (_animationState == NO_ANIMATION)
return false;
_animationTimer -= dt;
if (_animationTimer > 0)
return true;
Node &node1 = _nodes[_animatedNodes[0]];
Node &node2 = _nodes[_animatedNodes[1]];
switch (_animationState) {
case FIRST_PHASE: {
node1._rotation = getRotate(_animatedNodes[0], _animatedNodes[1]);
node2._rotation = getRotate(_animatedNodes[1], _animatedNodes[0]);
node1._isBack = !node1._isBack;
node2._isBack = !node2._isBack;
releaseNodeBack(node1);
releaseNodeBack(node2);
for (auto &it : node1._face)
it.setState(Node::getFaceStateName(0, false, false, false).c_str());
for (auto &it : node2._face)
it.setState(Node::getFaceStateName(0, false, false, false).c_str());
updateNode(node1, _animatedNodes[1], destination(_animatedNodes[0], _animatedNodes[1]), true);
updateNode(node2, _animatedNodes[0], destination(_animatedNodes[1], _animatedNodes[0]), true);
_animationTimer = 0.f;
_animationState = SECOND_PHASE;
debugC(5, kDebugMinigames, ">>>>>>>>>>>>>>>>>>>>>>>>>>> change %d <> %d, 2nd phase 1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<", _animatedNodes[0], _animatedNodes[1]);
node1.debugInfo();
node2.debugInfo();
return true;
}
case SECOND_PHASE:
node1._animated = false;
node2._animated = false;
updateNode(node1, _animatedNodes[1], destination(_animatedNodes[0], _animatedNodes[1]));
updateNode(node2, _animatedNodes[0], destination(_animatedNodes[1], _animatedNodes[0]));
SWAP(node1, node2);
_animationTimer = _animationTime;
_animationState = FIRD_PHASE;
debugC(5, kDebugMinigames, ">>>>>>>>>>>>>>>>>>>>>>>>>>> change %d <> %d, 2nd phase 2 <<<<<<<<<<<<<<<<<<<<<<<<<<<<", _animatedNodes[0], _animatedNodes[1]);
node2.debugInfo();
node1.debugInfo();
return true;
case FIRD_PHASE:
_animationTimer = 0.f;
_animationState = NO_ANIMATION;
releaseNodeBack(node1);
releaseNodeBack(node2);
updateNode(node1, _animatedNodes[0]);
updateNode(node2, _animatedNodes[1]);
endSwapNodes(_animatedNodes[0], _animatedNodes[1]);
debugC(5, kDebugMinigames, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ change %d <> %d, finished ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", _animatedNodes[0], _animatedNodes[1]);
_animatedNodes[0] = -1;
_animatedNodes[1] = -1;
return true;
default:
break;
}
return false;
}
void MinigameTriangle::swapNodes(int pos1, int pos2, bool silentQuick) {
if (silentQuick) {
Node &node1 = _nodes[pos1];
Node &node2 = _nodes[pos2];
node1._rotation = getRotate(pos1, pos2);
node2._rotation = getRotate(pos2, pos1);
node1._isBack = !node1._isBack;
node2._isBack = !node2._isBack;
releaseNodeBack(node1);
releaseNodeBack(node2);
SWAP(node1, node2);
updateNode(node1, pos1, 0, true);
updateNode(node2, pos2, 0, true);
} else
beginSwapNodes(pos1, pos2);
}
void MinigameTriangle::quant(float dt) {
if (_selected >= 0)
_runtime->setGameHelpVariant(0);
else
_runtime->setGameHelpVariant(1);
if (animate(dt))
return;
int mousePos = -1;
for (int idx = 0; idx < _fieldSize; ++idx)
if (_nodes[idx].hit(_runtime->mousePosition())) {
mousePos = idx;
break;
}
int startAnimation = -1;
int lastSelected = _selected;
if (_runtime->mouseLeftPressed()) {
if (mousePos < 0) // кликнули мимо - снимаем выделение
_selected = -1;
else if (_selected < 0) // ничего выделено небыло, просто выделяем
_selected = mousePos;
else if (_selected == mousePos) // кликнули на выделенном - снимаем выделение
_selected = -1;
else if (compatible(_selected, mousePos)) { // поменять фишки местами
startAnimation = _selected;
_selected = -1;
} else {
_selected = -1;
if (_quickReselect)
_selected = mousePos;
}
}
if (_selected != lastSelected) {
for (int idx = 0; idx < _fieldSize; ++idx) {
Node &node = _nodes[idx];
if (idx == _selected || compatible(_selected, idx)) { // с этой фишкой можно поменяться
if (!node._border)
node._border = _selectBorders[orientation(idx)].getObject();
node._border.setState(Node::getBorderStateName(idx == _selected));
node._border->set_R(slotCoord(idx));
node._border->update_screen_R();
_runtime->setDepth(node._border, _selectDepth);
} else if (node._border) {
_selectBorders[0].releaseObject(node._border, _runtime);
_selectBorders[1].releaseObject(node._border, _runtime);
}
}
}
if (_hovered != mousePos || _selected != lastSelected) {
highlight(_hovered, false);
highlight(_selected >= 0 ? _selected : lastSelected, false);
_hovered = mousePos;
if (_hovered >= 0 && startAnimation < 0) {
if (_selected >= 0) {
if (compatible(_selected, _hovered)) {
highlight(_hovered, true);
highlight(_selected, true);
}
} else
highlight(_hovered, true);
}
}
if (startAnimation >= 0) {
_hovered = -1;
swapNodes(startAnimation, mousePos, false);
}
if (_runtime->mouseRightPressed() && mousePos >= 0) {
debugC(2, kDebugMinigames, "----- DUBUG INFO FOR %d POSITION --------------------", mousePos);
debugC(2, kDebugMinigames, "row = %d, begin = %d, orientation = %d", rowByNum(mousePos), rowBegin(rowByNum(mousePos)), orientation(mousePos));
_nodes[mousePos].debugInfo();
}
}
int MinigameTriangle::rowBegin(int row) const {
if (row == _fieldLines)
return _fieldSize;
switch (_gameType) {
case TRIANGLE:
return sqr(row);
case RECTANGLE:
return row * _fieldWidth;
default:
break;
}
//case HEXAGON:
assert(row >= 0 && row < _fieldLines);
if (row >= _fieldLines / 2) {
row -= _fieldLines / 2;
return _fieldSize / 2 + (2 * _fieldLines - row) * row;
}
return (_fieldLines + row) * row;
}
int MinigameTriangle::rowByNum(int num) const {
if (num >= _fieldSize)
return _fieldLines;
switch (_gameType) {
case TRIANGLE:
return floor(sqrt((float)num));
case RECTANGLE:
return num / _fieldWidth;
default:
break;
}
//case HEXAGON:
int row = num < _fieldSize / 2 ? 0 : _fieldLines / 2;
while (row < _fieldLines && num >= rowBegin(row))
++row;
return row > 0 ? row - 1 : 0;
}
int MinigameTriangle::orientation(int num) const {
switch (_gameType) {
case TRIANGLE:
return (rowByNum(num) + num) % 2;
case RECTANGLE:
return num % 2;
default:
break;
}
//case HEXAGON:
return (num + rowByNum(num) + (num >= _fieldSize / 2 ? 1 : 0)) % 2;
}
bool MinigameTriangle::compatible(int num1, int num2) const {
if (num1 > num2)
SWAP(num1, num2);
if (num1 < 0)
return false;
int row1 = rowByNum(num1);
int row2 = rowByNum(num2);
if (row2 >= _fieldLines)
return false;
if (row1 == row2) // в одном слое
return num2 - num1 == 1; // должны быть рядом
else if (row2 - row1 != 1) // или на соседних слоях
return false;
else if (orientation(num1) != 0) // широкими сторонами друг к другу
return false;
int center1 = (rowBegin(row1) + rowBegin(row1 + 1) - 1) / 2;
int center2 = (rowBegin(row2) + rowBegin(row2 + 1) - 1) / 2;
return center1 - num1 == center2 - num2; // и точно друг под другом
}
int MinigameTriangle::getRotate(int num1, int num2) const {
static int solves[3][2][3] = {
{{0, 2, 1}, {0, 2, 1}},
{{2, 1, 0}, {1, 0, 2}},
{{1, 0, 2}, {2, 1, 0}}
};
assert(compatible(num1, num2));
return solves[rowByNum(num1) != rowByNum(num2) ? 0 : (num2 < num1 ? 1 : 2)]
[orientation(num1)][_nodes[num1]._rotation];
}
int MinigameTriangle::destination(int num1, int num2) const {
if (orientation(num1) == 0)
return rowByNum(num1) != rowByNum(num2) ? 0 : (num2 < num1 ? 1 : 2);
else
return rowByNum(num1) != rowByNum(num2) ? 0 : (num2 < num1 ? 2 : 1);
}
mgVect3f MinigameTriangle::slotCoord(int pos, int angle) const {
assert(pos * 3 + angle < (int)_positions.size());
return _positions[pos * 3 + angle];
}
} // namespace QDEngine

View File

@@ -0,0 +1,137 @@
/* 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 QDENGINE_MINIGAMES_ADV_M_TRIANGLES_H
#define QDENGINE_MINIGAMES_ADV_M_TRIANGLES_H
#include "qdengine/minigames/adv/common.h"
#include "qdengine/minigames/adv/MinigameInterface.h"
#include "qdengine/minigames/adv/ObjectContainer.h"
namespace QDEngine {
MinigameInterface *createMinigameTriangle(MinigameManager *runtime);
class MinigameTriangle : public MinigameInterface {
enum GameType {
TRIANGLE,
RECTANGLE,
HEXAGON
};
enum AnimationState {
NO_ANIMATION,
FIRST_PHASE,
SECOND_PHASE,
FIRD_PHASE
};
struct Node {
Node(int number = -1, int rot = -1);
void release(MinigameManager *runtime);
void debugInfo() const;
const QDObject &obj() const {
return _isBack ? _back : _face[_flip];
}
bool hit(const mgVect2f &pos) const;
int _number; // правильная позиция (номер слота)
int _rotation; // текущий угол поворота (правильный угол = 0)
int _flip;
QDObjects _face; // набор возможных углов переворота для лицевой стороны
QDObject _back; // обратная сторона
QDObject _border; // рамка
bool _isBack; // повернут лицом (true) или рубашкой (false)
bool _highlight;
bool _animated;
static const Common::String getFaceStateName(int angle, bool selected, bool animated, bool instantaneous);
static const char *getBackStateName(bool selected, bool animated, bool instantaneous);
static const char *getBorderStateName(bool selected);
};
typedef Std::vector<Node> Nodes;
public:
MinigameTriangle(MinigameManager *runtime);
~MinigameTriangle();
void quant(float dt);
private:
GameType _gameType = TRIANGLE;
Coords _positions;
int _selectDepth = 0;
int _fieldLines = 0;
int _fieldWidth = 0;
int _fieldSize = 0;
Nodes _nodes;
ObjectContainer _selectBorders[2];
ObjectContainer _backSides[6];
int _selected = 0;
int _hovered = 0;
bool _quickReselect = false;
AnimationState _animationState = NO_ANIMATION;
int _animatedNodes[2] = { 0 };
float _animationTime = 0.0;
float _animationTimer = 0.0;
/// очистить рубашку фишки
void releaseNodeBack(Node &node);
/// выставить графические состояния соответствующие текущему логическому
void updateNode(Node &node, int position, int flip = 0, bool quick = false);
/// подсветить/потушить фрагмент
void highlight(int idx, bool hl);
/// поменять местами фишки
void swapNodes(int pos1, int pos2, bool quick);
/// начать анимацию обмена
void beginSwapNodes(int pos1, int pos2);
/// отработка анимации переворота фишек
bool animate(float dt);
/// вызывается после окончания переворота
void endSwapNodes(int pos1, int pos2);
/// по номеру фишки вычисляет слой
int rowByNum(int num) const;
/// возвращает с какой фишки начинается слой
int rowBegin(int row) const;
/// 0 - угол вверх
int orientation(int num) const;
/// можно поменять местами
bool compatible(int num1, int num2) const;
/// определить какой будет угол поворота у num1 при переходе в num2
int getRotate(int num1, int num2) const;
/// направление переворота
int destination(int num1, int num2) const;
/// по номеру слота и углу переворота (с учетом типа игры) возвращает экранные координаты
mgVect3f slotCoord(int pos, int angle = 0) const;
MinigameManager *_runtime;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_M_TRIANGLES_H

View 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 QDENGINE_MINIGAMES_ADV_QDMATH_H
#define QDENGINE_MINIGAMES_ADV_QDMATH_H
#include "qdengine/xmath.h"
namespace QDEngine {
#define SQRT2 1.41421356f
#define SQRT3 1.73205081f
inline float dist(const mgVect2f& v1, const mgVect2f& v2) {
return sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y));
}
inline float abs(const mgVect2f& v) {
return sqrt(v.x * v.x + v.y * v.y);
}
inline void norm(mgVect2f& v) {
float mod = abs(v);
if (mod < FLT_EPS) {
v = mgVect2f(0, 1);
return;
}
v.x /= mod;
v.y /= mod;
}
template<class T, class T1, class T2>
inline T clamp(const T& x, const T1& xmin, const T2& xmax) {
if (x < xmin) return xmin;
if (x > xmax) return xmax;
return x;
}
template<class T>
inline T abs(const T& x) {
if (x < 0) return -x;
return x;
}
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ADV_QDMATH_H

View File

@@ -0,0 +1,576 @@
/* 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 QDENGINE_MINIGAMES_ARKADA_AVTOMAT_H
#define QDENGINE_MINIGAMES_ARKADA_AVTOMAT_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdArkadaAvtomatMiniGame : public qdMiniGameInterface {
public:
qdArkadaAvtomatMiniGame() {}
~qdArkadaAvtomatMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "ArkadaAvtomat::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_patronMouseObj = _scene->object_interface(_scene->minigame_parameter("patron_mouse"));
_patronTomatoObj = _scene->object_interface(_scene->minigame_parameter("patron_tomato"));
_killObj = _scene->object_interface(_scene->minigame_parameter("kill"));
_fazaObj = _scene->object_interface(_scene->minigame_parameter("faza"));
_menObj = _scene->object_interface(_scene->minigame_parameter("men"));
_bloodObj = _scene->object_interface(_scene->minigame_parameter("blood"));
_shotsEggObj = _scene->object_interface(_scene->minigame_parameter("shots_egg"));
_shotsTomatoObj = _scene->object_interface(_scene->minigame_parameter("shots_tomato"));
_shotsBananObj = _scene->object_interface(_scene->minigame_parameter("shots_banan"));
_doneObj = _scene->object_interface(_scene->minigame_parameter("done"));
_livesObj = _scene->object_interface(_scene->minigame_parameter("lives"));
_bublObj = _scene->object_interface(_scene->minigame_parameter("bubl"));
_walkFlagObj = _scene->object_interface(_scene->minigame_parameter("walk_flag"));
_jumpFlagObj = _scene->object_interface(_scene->minigame_parameter("jump_flag"));
_goingLeft = false;
_goingRight = false;
_manSpeed = 2;
_doingJump = false;
_stepsToJump = -1;
// stand(time(0));
_jumpNextPhase = -1;
_shotsTomatoCounter = 9;
_shotsBananaCounter = 10;
_shoteEggCounter = 10;
_livesCounter = 5;
_isFinal = false;
_jumpPhase = 2;
_doingWalk = false;
_jumpFlag = false;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "ArkadaAvtomat::quant(%f)", dt);
mgVect2i menCoords;
int randomCond = 0;
menCoords = _scene->world2screen_coords(_menObj->R());
_bublObj->set_R(_scene->screen2world_coords(menCoords, -5000.0));
if (_isFinal) {
updateWalkState();
return true;
}
if (!_shotsTomatoCounter && !_shotsBananaCounter && !_shoteEggCounter) {
_shotsTomatoCounter = 9;
_shotsBananaCounter = 10;
_shoteEggCounter = 10;
_livesCounter = 5;
_patronMouseObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
updateStats();
_manSpeed = 2;
}
if (!_doingJump) {
if (_scene->world2screen_coords(_menObj->R()).x < _jumpingPhase3Y
&& _menObj->is_state_active("\xf1\xf2\xee\xe8\xf2")) { // "стоит"
_menObj->set_R(_menCoords);
_bloodObj->set_R(_scene->screen2world_coords(_scene->world2screen_coords(_menCoords), 0.0)); // check 0.0 v96
_stepsToJump = -1;
}
}
if (_menObj->is_state_active("\xf1\xf2\xee\xe8\xf2")) { // "стоит"
_goingLeft = false;
_goingRight = false;
_doingJump = false;
}
if (!_goingRight) {
if (_goingLeft || _doingJump || _menObj->is_state_active("\xf1\xf2\xee\xe8\xf2")) { // "стоит"
LABEL_44:
if (!_goingRight)
goto LABEL_47;
goto LABEL_45;
}
_stepsToLeft = -1;
_stepsToRight = -1;
switch (qd_rnd(5)) {
case 0:
case 3: {
_goingRight = true;
int maxSteps = (500 - _menObj->screen_R().x) / _manSpeed;
if (maxSteps < 10)
maxSteps = 10;
_stepsToRight = qd_rnd(maxSteps);
_menObj->set_state("\xe8\xe4\xe5\xf2 \xe2\xef\xf0\xe0\xe2\xee"); // "идет вправо"
goto LABEL_44;
}
case 1:
case 4: {
_goingLeft = true;
int maxSteps = (_menObj->screen_R().x - 300) / _manSpeed;
if (maxSteps < 10)
maxSteps = 10;
_stepsToLeft = qd_rnd(maxSteps);
_menObj->set_state("\xe8\xe4\xe5\xf2 \xe2\xeb\xe5\xe2\xee"); // "идет влево"
goto LABEL_44;
}
case 2:
_doingJump = true;
_stepsToJump = 30;
_menCoords = _menObj->R();
{
int y = _scene->world2screen_coords(_menObj->R()).y;
_manOrigPosY = y;
_jumpingPhase3Y = y;
_jumpHeight = y - 60;
}
randomCond = qd_rnd(3);
switch (_jumpPhase) {
case 1:
if (!randomCond) {
_jumpingPhase3Y = _manOrigPosY;
goto LABEL_43;
}
if (randomCond == 1)
goto LABEL_29;
if (randomCond != 2)
goto LABEL_43;
break;
case 2:
if (!randomCond) {
_jumpingPhase3Y = _manOrigPosY;
goto LABEL_43;
}
if (randomCond == 1) {
_jumpingPhase3Y = 307;
_jumpNextPhase = 1;
goto LABEL_43;
}
if (randomCond != 2)
goto LABEL_43;
break;
case 3:
if (!randomCond) {
_jumpingPhase3Y = _manOrigPosY;
goto LABEL_43;
}
if (randomCond != 1) {
if (randomCond == 2) {
_jumpingPhase3Y = 307;
_jumpNextPhase = 1;
}
goto LABEL_43;
}
LABEL_29:
_jumpingPhase3Y = 332;
_jumpNextPhase = 2;
goto LABEL_43;
default:
LABEL_43:
_jumpPhaseIsGoingDown = false;
goto LABEL_44;
}
_jumpingPhase3Y = 357;
_jumpNextPhase = 3;
goto LABEL_43;
default:
goto LABEL_44;
}
}
LABEL_45:
{
mgVect2i pos = _scene->world2screen_coords(_menObj->R());
pos.x += _manSpeed;
_menObj->set_R(_scene->screen2world_coords(pos, 0.0));
}
_stepsToRight--;
if (_stepsToRight <= 0)
_goingRight = false;
LABEL_47:
if (_goingLeft) {
mgVect2i pos = _scene->world2screen_coords(_menObj->R());
pos.x -= _manSpeed;
_menObj->set_R(_scene->screen2world_coords(pos, 0.0));
_stepsToLeft--;
if (_stepsToLeft <= 0)
_goingLeft = false;
}
if (_doingJump) {
mgVect2i pos = _scene->world2screen_coords(_menObj->R());
if (pos.y >= _manOrigPosY - 10) {
if (!_menObj->is_state_active("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x31") && !_jumpPhaseIsGoingDown) // "прыгает1"
_menObj->set_state("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x31"); // "прыгает1"
}
if (pos.y <= _manOrigPosY - 10) {
if (_menObj->is_state_active("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x31") && !_jumpPhaseIsGoingDown) // "прыгает1"
_menObj->set_state("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x32"); // "прыгает2"
}
if (pos.y >= _jumpingPhase3Y - 10) {
if (_menObj->is_state_active("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x32") && _jumpPhaseIsGoingDown) // "прыгает2"
_menObj->set_state("\xef\xf0\xfb\xe3\xe0\xe5\xf2\x33"); // "прыгает3"
}
if (pos.y <= _jumpHeight)
goto LABEL_176;
if (!_jumpPhaseIsGoingDown) {
pos.y -= 4;
LABEL_75:
LABEL_76:
if (pos.y < _jumpingPhase3Y) {
LABEL_79:
_menObj->set_R(_scene->screen2world_coords(pos, 0.0));
goto LABEL_80;
}
LABEL_77:
if (_jumpPhaseIsGoingDown) {
_doingJump = false;
_jumpPhase = _jumpNextPhase;
}
goto LABEL_79;
}
if (pos.y > _jumpHeight) {
if (!_jumpPhaseIsGoingDown)
goto LABEL_76;
} else {
LABEL_176:
if (!_jumpPhaseIsGoingDown) {
_jumpPhaseIsGoingDown = true;
goto LABEL_76;
}
}
if (pos.y > _jumpingPhase3Y)
goto LABEL_77;
pos.y += 4;
goto LABEL_75;
}
LABEL_80:
_patronMouseObj->set_R(_scene->screen2world_coords(_engine->mouse_cursor_position(), -5000.0));
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)) {
if (_patronMouseObj->is_state_active("\xef\xee\xec\xe8\xe4\xee\xf0")) { // "помидор"
if (_shoteEggCounter <= 0) {
if (_shotsBananaCounter > 0) {
_patronMouseObj->set_state("\xe1\xe0\xed\xe0\xed"); // "банан"
if (_shotsTomatoCounter > 0)
_shotsTomatoCounter++;
--_shotsBananaCounter;
}
goto LABEL_107;
}
_patronMouseObj->set_state("\xff\xe9\xf6\xee"); // "яйцо"
if (_shotsTomatoCounter > 0)
_shotsTomatoCounter++;
} else {
if (_patronMouseObj->is_state_active("\xff\xe9\xf6\xee")) { // "яйцо"
if (_shotsBananaCounter <= 0) {
if (_shotsTomatoCounter > 0) {
_patronMouseObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
if (_shoteEggCounter > 0)
_shoteEggCounter++;
--_shotsTomatoCounter;
}
} else {
_patronMouseObj->set_state("\xe1\xe0\xed\xe0\xed"); // "банан"
if (_shoteEggCounter > 0)
_shoteEggCounter++;
--_shotsBananaCounter;
}
goto LABEL_107;
}
if (!_patronMouseObj->is_state_active("\xe1\xe0\xed\xe0\xed")) // "банан"
goto LABEL_107;
if (_shotsTomatoCounter > 0) {
_patronMouseObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
if (_shotsBananaCounter > 0)
_shotsBananaCounter++;
--_shotsTomatoCounter;
goto LABEL_107;
}
if (_shoteEggCounter <= 0) {
LABEL_107:
updateStats();
goto LABEL_108;
}
_patronMouseObj->set_state("\xff\xe9\xf6\xee"); // "яйцо"
if (_shotsBananaCounter > 0)
_shotsBananaCounter = _shotsBananaCounter + 1;
}
--_shoteEggCounter;
goto LABEL_107;
}
LABEL_108:
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)
&& !_bloodObj->is_state_active("\xe5\xf1\xf2\xfc") // "есть"
&& !_patronTomatoObj->is_state_active("\xef\xee\xec\xe8\xe4\xee\xf0") // "помидор"
&& !_patronTomatoObj->is_state_active("\xff\xe9\xf6\xee") // "яйцо"
&& !_patronTomatoObj->is_state_active("\xe1\xe0\xed\xe0\xed")) { // "банан"
_cursorPos = _engine->mouse_cursor_position();
_patronTomatoObj->set_R(_patronMouseObj->R());
if (_patronMouseObj->is_state_active("\xef\xee\xec\xe8\xe4\xee\xf0")) { // "помидор"
_patronTomatoObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
--_shotsTomatoCounter;
} else if (_patronMouseObj->is_state_active("\xff\xe9\xf6\xee")) { // "яйцо"
_patronTomatoObj->set_state("\xff\xe9\xf6\xee"); // "яйцо"
--_shoteEggCounter;
} else if (_patronMouseObj->is_state_active("\xe1\xe0\xed\xe0\xed")) { // "банан"
_patronTomatoObj->set_state("\xe1\xe0\xed\xe0\xed"); // "банан"
--_shotsBananaCounter;
}
_bloodObj->set_R(_patronMouseObj->R());
updateStats();
if (_shotsTomatoCounter <= 0
&& _patronTomatoObj->is_state_active("\xef\xee\xec\xe8\xe4\xee\xf0")) { // "помидор"
if (_shoteEggCounter <= 0) {
if (_shotsBananaCounter <= 0)
_patronMouseObj->set_state("\xed\xe8\xf7\xe5\xe3\xee"); // "ничего"
else
_patronMouseObj->set_state("\xe1\xe0\xed\xe0\xed"); // "банан"
} else {
_patronMouseObj->set_state("\xff\xe9\xf6\xee"); // "яйцо"
}
}
if (_shoteEggCounter <= 0 && _patronTomatoObj->is_state_active("\xff\xe9\xf6\xee")) { // "яйцо"
if (_shotsBananaCounter <= 0) {
if (_shotsTomatoCounter <= 0)
_patronMouseObj->set_state("\xed\xe8\xf7\xe5\xe3\xee"); // "ничего"
else
_patronMouseObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
} else {
_patronMouseObj->set_state("\xe1\xe0\xed\xe0\xed"); // "банан"
}
}
if (_shotsBananaCounter <= 0 && _patronTomatoObj->is_state_active("\xe1\xe0\xed\xe0\xed")) { // "банан"
if (_shotsTomatoCounter <= 0) {
if (_shoteEggCounter <= 0)
_patronMouseObj->set_state("\xed\xe8\xf7\xe5\xe3\xee"); // "ничего"
else
_patronMouseObj->set_state("\xff\xe9\xf6\xee"); // "яйцо"
} else {
_patronMouseObj->set_state("\xef\xee\xec\xe8\xe4\xee\xf0"); // "помидор"
}
}
}
// Hit check
if (_fazaObj->is_state_active("\xe4\xe0") // "да"
&& !_bloodObj->is_state_active("\xe5\xf1\xf2\xfc")) { // "есть"
mgVect2i pos = _menObj->screen_R();
if (ABS(pos.x - _cursorPos.x) <= 15 && ABS(pos.y - _cursorPos.y) <= 35) {
_killObj->set_state("\xe4\xe0"); // "да"
--_livesCounter;
updateStats();
_doingJump = false;
_manSpeed = 7 - _livesCounter;
if (_manSpeed > 4)
_manSpeed = 4;
}
}
if (!_livesCounter) {
_isFinal = true;
_doneObj->set_state("\xe4\xe0"); // "да"
_goingLeft = false;
_goingRight = false;
_doingJump = false;
}
updateWalkState();
return true;
}
void updateWalkState() {
if ((_goingLeft || _goingRight) && !_doingWalk) {
_doingWalk = true;
_walkFlagObj->set_state("\xe4\xe0"); // "да"
_jumpFlag = false;
_jumpFlagObj->set_state("\xed\xe5\xf2"); // "нет"
return;
}
if (_doingJump) {
_doingWalk = false;
_walkFlagObj->set_state("\xed\xe5\xf2"); // "нет"
_jumpFlag = true;
_jumpFlagObj->set_state("\xe4\xe0"); // "да"
return;
}
_doingWalk = false;
_walkFlagObj->set_state("\xed\xe5\xf2"); // "нет"
_jumpFlag = false;
_jumpFlagObj->set_state("\xed\xe5\xf2"); // "нет"
}
bool finit() {
debugC(1, kDebugMinigames, "ArkadaAvtomat::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
void updateStats() {
_shotsEggObj->set_state(Common::String::format("%i", _shoteEggCounter).c_str());
_shotsBananObj->set_state(Common::String::format("%i", _shotsBananaCounter).c_str());
_shotsTomatoObj->set_state(Common::String::format("%d", _shotsTomatoCounter).c_str());
_livesObj->set_state(Common::String::format("%d", _livesCounter).c_str());
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_patronMouseObj = nullptr;
qdMinigameObjectInterface *_patronTomatoObj = nullptr;
qdMinigameObjectInterface *_killObj = nullptr;
qdMinigameObjectInterface *_fazaObj = nullptr;
qdMinigameObjectInterface *_menObj = nullptr;
qdMinigameObjectInterface *_bloodObj = nullptr;
qdMinigameObjectInterface *_shotsEggObj = nullptr;
qdMinigameObjectInterface *_shotsTomatoObj = nullptr;
qdMinigameObjectInterface *_shotsBananObj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
qdMinigameObjectInterface *_livesObj = nullptr;
qdMinigameObjectInterface *_bublObj = nullptr;
qdMinigameObjectInterface *_walkFlagObj = nullptr;
qdMinigameObjectInterface *_jumpFlagObj = nullptr;
bool _goingLeft = false;
bool _goingRight = false;
bool _doingJump = false;
bool _doingWalk = false;
bool _jumpFlag = false;
int _stepsToLeft = 0;
int _stepsToRight = 0;
int _stepsToJump = -1;
mgVect3f _menCoords;
int _manSpeed = 2;
int _shotsTomatoCounter = 9;
int _shotsBananaCounter = 10;
int _shoteEggCounter = 10;
int _livesCounter = 5;
bool _isFinal = false;
mgVect2i _cursorPos;
int _manOrigPosY = 0;
int _jumpHeight = 0;
int _jumpingPhase3Y = 0;
bool _jumpPhaseIsGoingDown = false;
int _jumpPhase = 2;
int _jumpNextPhase = -1;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ARKADA_AVTOMAT_H

View File

@@ -0,0 +1,482 @@
/* 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 QDENGINE_MINIGAMES_BOOK_ALL_H
#define QDENGINE_MINIGAMES_BOOK_ALL_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
const float bookGusenica[95 * 2] = {
0.000f, 0.036f, 0.514f, 1.154f, 1.787f, 2.370f, 2.862f, 4.242f, 4.921f, 5.979f,
6.434f, 6.820f, 7.228f, 8.297f, 8.963f, 9.170f, 9.825f, 10.698f, 11.401f, 12.169f,
12.868f, 13.416f, 14.107f, 15.232f, 16.679f, 17.048f, 17.618f, 18.119f, 19.437f, 19.882f,
20.492f, 21.583f, 22.646f, 23.566f, 25.343f, 25.521f, 25.758f, 26.371f, 26.561f, 27.310f,
27.692f, 28.216f, 28.685f, 29.035f, 29.596f, 30.499f, 31.886f, 32.309f, 32.441f, 33.276f,
33.689f, 34.260f, 34.769f, 35.776f, 36.569f, 37.678f, 38.885f, 39.007f, 39.608f, 40.160f,
41.874f, 42.118f, 42.637f, 42.775f, 43.555f, 43.949f, 44.187f, 44.761f, 45.475f, 45.861f,
47.240f, 47.428f, 47.639f, 48.227f, 48.746f, 49.456f, 49.690f, 50.298f, 50.961f, 51.173f,
51.770f, 52.395f, 52.937f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.665f, 1.136f, 1.633f, 2.600f, 2.973f, 3.558f, 3.996f, 4.657f, 6.140f,
7.132f, 8.223f, 9.114f, 9.288f, 10.437f, 10.624f, 11.307f, 11.479f, 11.913f, 12.505f,
13.162f, 13.287f, 14.580f, 15.192f, 16.004f, 16.552f, 17.128f, 17.805f, 19.214f, 19.860f,
20.571f, 22.766f, 23.256f, 24.098f, 24.888f, 26.421f, 26.786f, 26.893f, 27.351f, 27.804f,
28.530f, 29.882f, 30.415f, 31.506f, 31.614f, 32.150f, 33.647f, 34.333f, 34.811f, 35.659f,
35.809f, 36.192f, 36.612f, 37.062f, 37.756f, 39.359f, 40.266f, 41.407f, 41.828f, 41.901f,
42.447f, 43.290f, 43.980f, 45.047f, 46.263f, 46.407f, 47.836f, 48.311f, 49.430f, 49.752f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookGusenicaCZ[95 * 2] = {
0.000f, 0.075f, 0.372f, 1.112f, 1.399f, 1.851f, 1.975f, 2.232f, 3.738f, 3.987f,
4.133f, 4.479f, 5.108f, 5.316f, 5.754f, 6.463f, 7.273f, 7.406f, 7.636f, 8.092f,
8.797f, 9.319f, 9.833f, 10.238f, 10.968f, 11.075f, 11.876f, 12.620f, 14.243f, 14.438f,
15.089f, 15.530f, 16.004f, 16.088f, 17.014f, 17.328f, 17.962f, 18.477f, 18.561f, 19.695f,
19.965f, 20.253f, 20.585f, 20.939f, 21.223f, 21.577f, 22.161f, 22.369f, 22.950f, 24.185f,
24.474f, 24.797f, 25.107f, 25.678f, 26.258f, 27.228f, 27.990f, 28.158f, 29.028f, 29.134f,
29.688f, 30.675f, 31.189f, 31.627f, 31.769f, 32.035f, 32.455f, 32.741f, 33.277f, 33.503f,
34.048f, 34.442f, 34.836f, 35.009f, 35.629f, 36.094f, 36.856f, 36.993f, 37.596f, 37.914f,
38.561f, 39.106f, 39.612f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.042f, 0.500f, 0.667f, 1.460f, 1.627f, 1.960f, 2.336f, 3.587f, 3.712f,
4.004f, 4.713f, 5.339f, 6.215f, 6.381f, 7.674f, 8.091f, 8.425f, 8.925f, 9.676f,
10.052f, 10.302f, 11.220f, 11.595f, 12.137f, 12.221f, 12.721f, 13.430f, 13.597f, 13.722f,
14.097f, 15.390f, 15.766f, 16.558f, 16.975f, 17.226f, 18.352f, 19.269f, 19.603f, 20.646f,
21.355f, 21.897f, 22.105f, 23.065f, 23.607f, 23.732f, 24.316f, 25.817f, 26.276f, 26.568f,
26.944f, 27.402f, 27.569f, 28.403f, 28.695f, 29.154f, 29.279f, 30.447f, 31.615f, 32.032f,
33.075f, 33.283f, 33.784f, 34.660f, 34.910f, 35.369f, 35.661f, 36.036f, 36.995f, 37.329f,
37.996f, 38.455f, 38.580f, 38.997f, 39.581f, 39.998f, 40.290f, 40.874f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookGusenicaPL[95 * 2] = {
0.000f, 0.013f, 0.405f, 1.197f, 1.586f, 2.114f, 2.633f, 2.862f, 3.238f, 4.114f,
4.635f, 4.859f, 5.486f, 5.850f, 6.228f, 7.325f, 7.761f, 8.261f, 8.729f, 9.157f,
9.513f, 10.407f, 11.073f, 11.522f, 12.354f, 13.158f, 14.035f, 15.855f, 16.093f, 16.745f,
17.328f, 17.860f, 18.567f, 18.687f, 19.078f, 19.724f, 20.749f, 21.082f, 21.420f, 21.955f,
22.239f, 22.696f, 23.539f, 24.086f, 24.535f, 24.675f, 25.476f, 25.824f, 26.386f, 26.877f,
27.460f, 28.287f, 29.472f, 30.219f, 31.194f, 31.612f, 32.107f, 32.994f, 34.493f, 35.242f,
36.080f, 36.523f, 36.943f, 37.226f, 37.774f, 38.002f, 38.870f, 39.646f, 40.221f, 40.680f,
41.391f, 41.956f, 42.252f, 43.124f, 43.433f, 43.860f, 44.614f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.073f, 0.630f, 0.858f, 0.858f, 1.441f, 1.885f, 2.411f, 3.071f, 4.120f,
4.448f, 4.825f, 5.804f, 6.527f, 7.351f, 8.893f, 9.375f, 9.727f, 10.260f, 10.644f,
10.832f, 11.356f, 11.578f, 12.227f, 12.460f, 13.082f, 13.249f, 0.000f, 13.865f, 14.415f,
15.587f, 16.120f, 17.213f, 17.414f, 18.224f, 18.874f, 20.081f, 20.468f, 21.119f, 22.381f,
23.443f, 24.101f, 24.426f, 25.481f, 26.111f, 26.742f, 26.899f, 27.238f, 28.290f, 28.587f,
28.885f, 29.248f, 29.871f, 30.494f, 31.756f, 32.621f, 32.975f, 33.610f, 33.877f, 34.870f,
35.669f, 36.198f, 36.959f, 37.513f, 37.706f, 38.353f, 39.042f, 39.692f, 40.505f, 41.076f,
41.747f, 42.254f, 42.601f, 43.200f, 43.833f, 44.092f, 44.550f, 44.961f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookLes[95 * 2] = {
0.000f, 0.046f, 0.577f, 0.809f, 1.623f, 1.985f, 2.635f, 3.536f, 3.642f, 4.560f,
5.071f, 6.558f, 7.007f, 7.876f, 8.998f, 9.548f, 10.387f, 10.471f, 11.054f, 12.062f,
12.081f, 12.462f, 12.647f, 12.900f, 13.987f, 14.265f, 14.809f, 15.558f, 16.332f, 17.643f,
18.000f, 19.285f, 19.512f, 19.867f, 20.158f, 20.517f, 20.822f, 21.240f, 21.741f, 23.193f,
23.704f, 24.338f, 25.117f, 26.058f, 26.845f, 26.989f, 27.455f, 28.551f, 28.859f, 29.181f,
30.094f, 30.833f, 31.519f, 32.497f, 33.339f, 34.638f, 34.723f, 35.053f, 35.474f, 36.280f,
37.317f, 38.190f, 38.846f, 39.988f, 40.098f, 40.768f, 41.784f, 42.443f, 42.580f, 43.299f,
44.911f, 45.276f, 45.679f, 45.935f, 46.393f, 47.825f, 48.345f, 49.492f, 49.723f, 49.915f,
50.109f, 50.629f, 51.285f, 51.536f, 52.749f, 52.903f, 53.364f, 54.450f, 54.539f, 54.998f,
55.853f, 56.888f, 57.261f, 58.080f, 58.723f,
0.000f, 0.221f, 0.891f, 1.479f, 2.604f, 2.712f, 3.110f, 3.786f, 3.917f, 4.529f,
5.952f, 6.322f, 6.555f, 6.676f, 7.046f, 7.185f, 7.567f, 8.643f, 8.802f, 9.154f,
9.889f, 10.886f, 11.069f, 11.385f, 12.181f, 12.403f, 12.578f, 12.732f, 13.013f, 14.520f,
14.680f, 15.121f, 15.278f, 16.030f, 16.396f, 16.897f, 18.072f, 18.506f, 18.687f, 19.255f,
19.370f, 20.322f, 20.484f, 20.640f, 20.981f, 21.615f, 21.820f, 22.347f, 22.901f, 23.924f,
24.430f, 24.810f, 25.187f, 26.132f, 26.958f, 27.109f, 28.126f, 28.286f, 28.851f, 29.557f,
31.111f, 31.308f, 31.858f, 32.155f, 32.680f, 33.127f, 33.368f, 34.789f, 35.089f, 35.577f,
35.664f, 36.126f, 36.316f, 36.537f, 36.897f, 37.138f, 38.507f, 38.776f, 39.316f, 39.511f,
39.876f, 40.096f, 41.040f, 41.315f, 41.513f, 41.688f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookLesCZ[95 * 2] = {
0.000f, 0.200f, 0.459f, 0.959f, 1.210f, 1.627f, 2.628f, 2.836f, 3.045f, 3.837f,
3.962f, 4.254f, 4.493f, 4.796f, 4.880f, 5.422f, 6.673f, 7.299f, 7.466f, 8.133f,
8.800f, 9.927f, 10.719f, 11.303f, 11.637f, 12.512f, 13.388f, 13.680f, 13.972f, 14.306f,
15.432f, 15.557f, 15.807f, 16.308f, 16.683f, 16.892f, 17.768f, 18.560f, 19.186f, 20.145f,
20.437f, 20.854f, 21.146f, 21.980f, 22.189f, 22.856f, 23.732f, 24.399f, 25.108f, 25.400f,
25.609f, 26.109f, 26.568f, 27.277f, 28.320f, 28.487f, 29.029f, 29.196f, 29.363f, 29.863f,
30.405f, 30.614f, 32.074f, 32.616f, 32.950f, 33.825f, 34.117f, 34.618f, 35.285f, 36.536f,
36.745f, 37.204f, 37.704f, 38.288f, 38.789f, 39.039f, 40.374f, 40.874f, 41.250f, 42.084f,
43.126f, 43.460f, 44.586f, 45.045f, 45.545f, 45.879f, 46.588f, 46.880f, 47.130f, 47.547f,
48.382f, 49.883f, 50.467f, 51.009f, 0.000f,
0.000f, 0.027f, 0.686f, 1.208f, 1.510f, 1.702f, 2.471f, 2.677f, 3.267f, 3.405f,
3.940f, 4.517f, 5.986f, 6.521f, 6.700f, 6.988f, 7.153f, 7.304f, 7.880f, 8.306f,
8.773f, 9.830f, 10.530f, 11.038f, 11.381f, 12.205f, 12.576f, 13.056f, 14.429f, 14.709f,
15.121f, 15.725f, 16.000f, 16.892f, 17.249f, 17.977f, 19.212f, 19.487f, 19.665f, 19.748f,
20.022f, 21.464f, 22.027f, 22.317f, 22.740f, 22.800f, 23.468f, 23.899f, 24.284f, 25.176f,
25.862f, 26.027f, 26.727f, 26.906f, 27.441f, 27.565f, 28.045f, 28.210f, 29.185f, 29.473f,
29.803f, 30.750f, 30.956f, 31.532f, 32.191f, 32.521f, 33.605f, 33.984f, 34.450f, 34.752f,
34.945f, 35.315f, 35.453f, 35.617f, 35.837f, 36.647f, 37.004f, 37.594f, 37.883f, 38.075f,
38.638f, 38.996f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookLesPL[95 * 2] = {
0.000f, 0.072f, 0.664f, 1.336f, 2.142f, 2.437f, 3.296f, 3.308f, 3.425f, 3.603f,
3.990f, 4.822f, 5.575f, 5.957f, 7.337f, 7.859f, 8.353f, 8.677f, 9.730f, 9.879f,
10.159f, 10.560f, 11.114f, 11.981f, 12.989f, 13.362f, 13.924f, 14.366f, 14.584f, 15.354f,
16.034f, 16.773f, 16.982f, 17.840f, 19.140f, 20.033f, 20.844f, 21.035f, 21.974f, 22.290f,
22.517f, 22.869f, 23.351f, 24.770f, 25.351f, 25.829f, 26.259f, 26.670f, 27.151f, 27.509f,
28.082f, 28.280f, 29.379f, 30.469f, 31.227f, 31.797f, 32.229f, 33.304f, 33.736f, 34.095f,
34.716f, 35.155f, 35.955f, 37.063f, 37.767f, 38.074f, 38.762f, 39.627f, 41.192f, 41.731f,
42.163f, 42.528f, 43.289f, 43.859f, 45.113f, 45.357f, 46.221f, 46.840f, 47.433f, 47.810f,
48.331f, 48.982f, 49.074f, 49.576f, 49.969f, 50.432f, 51.004f, 51.275f, 52.037f, 52.216f,
52.429f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.026f, 0.416f, 0.842f, 1.848f, 2.491f, 2.969f, 3.270f, 3.964f, 4.610f,
4.882f, 5.857f, 6.393f, 6.757f, 6.997f, 7.295f, 7.907f, 8.083f, 8.366f, 9.285f,
9.828f, 10.064f, 10.701f, 10.980f, 11.474f, 11.681f, 12.150f, 12.431f, 13.486f, 13.994f,
14.588f, 14.777f, 14.962f, 15.419f, 16.823f, 17.387f, 17.694f, 17.954f, 18.918f, 19.110f,
19.778f, 20.946f, 21.810f, 22.115f, 22.371f, 22.601f, 23.044f, 23.331f, 23.687f, 24.021f,
24.764f, 25.043f, 25.508f, 25.922f, 26.541f, 27.062f, 27.799f, 28.416f, 29.538f, 29.938f,
30.446f, 31.323f, 32.151f, 32.955f, 33.578f, 34.438f, 34.676f, 35.063f, 35.384f, 35.889f,
36.407f, 37.322f, 38.309f, 39.471f, 39.662f, 40.135f, 40.756f, 40.882f, 41.483f, 41.599f,
41.869f, 42.765f, 43.065f, 43.750f, 44.136f, 44.469f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookBuhta[95 * 2] = {
0.000f, 0.284f, 0.750f, 1.287f, 1.965f, 2.410f, 2.975f, 3.819f, 4.682f, 6.184f,
6.735f, 7.182f, 7.918f, 8.786f, 10.161f, 11.182f, 11.970f, 12.297f, 13.910f, 14.518f,
15.989f, 16.419f, 17.332f, 18.960f, 19.471f, 20.762f, 21.473f, 22.749f, 23.452f, 24.547f,
26.140f, 26.339f, 26.598f, 27.266f, 28.012f, 28.609f, 29.459f, 29.746f, 30.216f, 31.683f,
32.613f, 34.180f, 34.987f, 35.505f, 36.508f, 37.457f, 39.046f, 39.387f, 40.471f, 40.896f,
41.958f, 42.591f, 42.847f, 43.120f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.811f, 1.190f, 1.754f, 2.475f, 3.367f, 5.026f, 5.580f, 6.202f, 6.455f,
7.050f, 8.709f, 9.114f, 9.551f, 10.241f, 11.304f, 11.936f, 13.122f, 13.897f, 15.227f,
16.105f, 16.782f, 17.773f, 19.608f, 20.655f, 21.015f, 21.520f, 22.579f, 24.167f, 24.942f,
25.727f, 27.149f, 28.267f, 28.736f, 29.372f, 30.030f, 30.841f, 31.751f, 32.170f, 32.743f,
33.234f, 34.740f, 35.880f, 36.294f, 37.218f, 38.147f, 38.543f, 39.309f, 40.896f, 41.469f,
42.046f, 42.461f, 42.944f, 43.079f, 44.093f, 45.324f, 46.062f, 47.153f, 47.798f, 48.970f,
49.612f, 50.230f, 51.343f, 51.780f, 52.083f, 52.326f, 52.728f, 53.143f, 54.139f, 55.112f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookBuhtaCZ[95 * 2] = {
0.000f, 0.133f, 0.434f, 0.767f, 1.134f, 1.802f, 2.169f, 2.369f, 2.636f, 2.736f,
3.036f, 3.770f, 4.004f, 4.605f, 4.771f, 5.305f, 5.706f, 6.106f, 7.808f, 8.141f,
8.275f, 8.575f, 8.976f, 10.077f, 10.177f, 10.477f, 10.878f, 11.278f, 11.745f, 12.746f,
13.046f, 13.180f, 13.714f, 13.947f, 15.282f, 16.350f, 17.084f, 17.284f, 18.151f, 18.952f,
19.653f, 19.920f, 20.320f, 21.622f, 22.022f, 22.089f, 22.522f, 22.956f, 23.790f, 23.891f,
24.725f, 24.791f, 25.459f, 25.626f, 26.760f, 27.127f, 27.761f, 28.495f, 28.662f, 29.129f,
29.296f, 30.163f, 30.464f, 31.265f, 32.399f, 33.133f, 33.367f, 33.934f, 34.134f, 34.334f,
34.601f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.200f, 0.667f, 1.134f, 1.635f, 2.402f, 2.469f, 2.803f, 3.136f, 3.303f,
3.704f, 4.171f, 4.204f, 4.671f, 4.838f, 5.205f, 6.240f, 6.373f, 6.507f, 6.607f,
7.207f, 8.242f, 8.442f, 8.709f, 9.042f, 9.509f, 10.310f, 11.111f, 11.311f, 11.778f,
12.112f, 12.246f, 13.113f, 14.781f, 15.315f, 15.582f, 16.250f, 16.717f, 16.884f, 17.384f,
18.519f, 18.752f, 19.419f, 19.553f, 20.087f, 20.520f, 21.088f, 21.722f, 22.623f, 23.924f,
24.591f, 24.992f, 25.525f, 25.859f, 25.993f, 27.227f, 27.794f, 28.262f, 28.862f, 29.196f,
29.897f, 29.997f, 30.731f, 32.699f, 33.200f, 33.934f, 34.701f, 35.068f, 35.235f, 35.903f,
36.370f, 36.770f, 37.971f, 38.338f, 38.672f, 39.006f, 39.539f, 39.673f, 40.707f, 40.974f,
41.742f, 42.442f, 43.176f, 43.343f, 43.877f, 44.544f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
const float bookBuhtaPL[95 * 2] = {
0.000f, 0.023f, 0.480f, 0.982f, 1.912f, 2.264f, 2.747f, 3.054f, 3.621f, 4.120f,
5.207f, 6.111f, 6.508f, 7.338f, 8.678f, 9.335f, 9.817f, 10.016f, 10.812f, 11.567f,
12.078f, 13.060f, 13.604f, 14.150f, 15.211f, 15.822f, 16.176f, 16.640f, 17.817f, 18.353f,
18.790f, 19.880f, 20.847f, 22.189f, 22.954f, 23.744f, 23.916f, 24.627f, 25.240f, 25.341f,
25.727f, 26.229f, 26.943f, 27.991f, 28.702f, 29.004f, 30.128f, 30.514f, 31.176f, 32.223f,
32.850f, 33.542f, 34.375f, 34.746f, 35.416f, 35.920f, 37.227f, 37.767f, 38.658f, 39.417f,
39.932f, 40.717f, 41.051f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.016f, 0.552f, 1.090f, 1.752f, 2.685f, 3.623f, 4.351f, 4.942f, 5.223f,
6.036f, 6.420f, 6.660f, 7.004f, 7.495f, 7.982f, 8.183f, 8.775f, 9.372f, 10.378f,
10.680f, 12.081f, 12.771f, 13.465f, 14.306f, 15.346f, 15.829f, 16.440f, 17.191f, 18.362f,
18.998f, 19.630f, 19.830f, 21.057f, 21.863f, 22.681f, 23.797f, 25.020f, 25.621f, 26.137f,
26.804f, 28.078f, 29.077f, 29.586f, 30.024f, 30.360f, 30.990f, 31.509f, 31.893f, 33.320f,
33.815f, 34.541f, 35.274f, 35.542f, 36.178f, 36.826f, 37.776f, 38.459f, 39.971f, 40.603f,
41.432f, 42.203f, 42.634f, 43.145f, 43.944f, 44.321f, 45.638f, 46.481f, 47.315f, 47.904f,
48.102f, 48.877f, 49.468f, 49.909f, 50.274f, 50.950f, 51.477f, 51.778f, 52.710f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
0.000f, 0.000f, 0.000f, 0.000f, 0.000f,
};
class qdBookAllMiniGame : public qdMiniGameInterface {
public:
qdBookAllMiniGame(Common::String dll, Common::Language language) : _dll(dll), _language(language) {}
~qdBookAllMiniGame() { };
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "BookAll::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return 0;
_artObject = _scene->object_interface("art");
_startReading = _scene->object_interface("$start_reading");
_recordPlayer = _scene->object_interface("\xe3\xf0\xe0\xec\xee\xf4\xee\xed"); // "грамофон"
_pageDurations[0] = 0.0;
_totalPageArts[0] = 0;
if (_dll == "DLL\\Book_gusenica.dll") {
if (_language == Common::CS_CZE) {
_artTimeStamps = bookGusenicaCZ;
_pageDurations[1] = 40.607f;
_pageDurations[2] = 41.854f;
_totalPageArts[1] = 82;
_totalPageArts[2] = 77;
} else if (_language == Common::PL_POL) {
_artTimeStamps = bookGusenicaPL;
_pageDurations[1] = 45.209f;
_pageDurations[2] = 45.580002f;
_totalPageArts[1] = 76;
_totalPageArts[2] = 77;
} else {
_artTimeStamps = bookGusenica;
_pageDurations[1] = 54.300f;
_pageDurations[2] = 50.400f;
_totalPageArts[1] = 82;
_totalPageArts[2] = 69;
}
} else if (_dll == "DLL\\Book_les.dll") {
if (_language == Common::CS_CZE) {
_artTimeStamps = bookLesCZ;
_pageDurations[1] = 51.84f;
_pageDurations[2] = 39.832f;
_totalPageArts[1] = 93;
_totalPageArts[2] = 81;
} else if (_language == Common::PL_POL) {
_artTimeStamps = bookLesPL;
_pageDurations[1] = 53.042f;
_pageDurations[2] = 45.653f;
_totalPageArts[1] = 90;
_totalPageArts[2] = 85;
} else {
_artTimeStamps = bookLes;
_pageDurations[1] = 59.809f;
_pageDurations[2] = 42.30f;
_totalPageArts[1] = 94;
_totalPageArts[2] = 85;
}
} else if (_dll == "DLL\\Book_buhta.dll") {
if (_language == Common::CS_CZE) {
_artTimeStamps = bookBuhtaCZ;
_pageDurations[1] = 35.424f;
_pageDurations[2] = 45.128f;
_totalPageArts[1] = 70;
_totalPageArts[2] = 85;
} else if (_language == Common::PL_POL) {
_artTimeStamps = bookBuhtaPL;
_pageDurations[1] = 42.032001f;
_pageDurations[2] = 54.594002f;
_totalPageArts[1] = 62;
_totalPageArts[2] = 78;
} else {
_artTimeStamps = bookBuhta;
_pageDurations[1] = 43.913f;
_pageDurations[2] = 55.698f;
_totalPageArts[1] = 53;
_totalPageArts[2] = 69;
}
}
#if 0
const int pageSize = 91;
float artTimeStamps[pageSize * 3];
memset(artTimeStamps, 0, sizeof(artTimeStamps));
debugN("\t");
for (int i = 0; i < pageSize; i++) {
debugN("%6.3ff, ", artTimeStamps[pageSize + i]);
if ((i + 1) % 10 == 0)
debugN("\n\t");
}
for (int i = pageSize; i < 95; i++) {
debugN("%6.3ff, ", 0.0f);
if ((i + 1) % 10 == 0)
debugN("\n\t");
}
debugN("\n\n\t");
for (int i = 0; i < pageSize; i++) {
debugN("%6.3ff, ", artTimeStamps[pageSize * 2 + i]);
if ((i + 1) % 10 == 0)
debugN("\n\t");
}
for (int i = pageSize; i < 95; i++) {
debugN("%6.3ff, ", 0.0f);
if ((i + 1) % 10 == 0)
debugN("\n\t");
}
debug("");
#endif
_pageNum = 0;
_playbackOn = 0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "BookAll::quant(%f). _playbackOn: %d _playbackOn: %d _currentPageArt: %d _totalPageArts: %d _time: %f",
dt, _playbackOn, _playbackOn, _currentPageArt, _totalPageArts[_pageNum], _time);
if (!_playbackOn) {
if (_startReading->is_state_active("page1")) {
debugC(1, kDebugMinigames, "BookAll::quant(). Resetting to PAGE1");
_pageNum = 1;
_startReading->set_state("reading_page1");
_currentPageArt = 1;
_time = 0.0;
_playbackOn = true;
} else if (_startReading->is_state_active("page2")) {
debugC(1, kDebugMinigames, "BookAll::quant(). Resetting to PAGE2");
_pageNum = 2;
_startReading->set_state("reading_page2");
_currentPageArt = 1;
_time = 0.0;
_playbackOn = true;
}
}
if (_playbackOn && _recordPlayer->is_state_active("\xf1\xf2\xe0\xf2\xe8\xea")) { // "статик"
debugC(1, kDebugMinigames, "BookAll::quant(). Stopping playback externally");
_playbackOn = false;
_startReading->set_state("no");
}
if (_playbackOn) {
if (_currentPageArt > _totalPageArts[_pageNum]) {
_time = _time + dt;
if (_pageDurations[_pageNum] < (double)_time) {
debugC(1, kDebugMinigames, "BookAll::quant(). Stopping playback by time");
_startReading->set_state("stopping");
}
} else {
_time = _time + dt;
if (_artTimeStamps[95 * (_pageNum - 1) + _currentPageArt] <= (double)_time) {
_artObject->set_state(Common::String::format("page%i_art_%02i", _pageNum, _currentPageArt).c_str());
++_currentPageArt;
debugC(1, kDebugMinigames, "BookAll::quant(). Switching pageArt to %d", _currentPageArt);
}
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "BookAll::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
const float *_artTimeStamps = nullptr;
float _pageDurations[3] = { 0.0, 0.0, 0.0 };
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_artObject = nullptr;
qdMinigameObjectInterface *_startReading = nullptr;
qdMinigameObjectInterface *_recordPlayer = nullptr;
int _pageNum = 0;
bool _playbackOn = false;
int _currentPageArt = 1;
int _totalPageArts[3] = { 0, 0, 0 };
float _time = 0.0f;
Common::String _dll;
Common::Language _language;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_BOOK_LES_H

View File

@@ -0,0 +1,356 @@
/* 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 QDENGINE_MINIGAMES_INV_POPUP_H
#define QDENGINE_MINIGAMES_INV_POPUP_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdInvPopupMiniGame : public qdMiniGameInterface {
public:
qdInvPopupMiniGame() {}
~qdInvPopupMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "InvPopup::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
//_invClickObj = _scene->object_interface("$inv_click_flag");
_invDescObj = _scene->object_interface("%inv_desc");
_invDescCloseupObj = _scene->object_interface("%inv_desc_closeup");
//_invActiveFlagObj = _scene->object_interface("$inv_active_flag");
_blockPersObj = _scene->object_interface("\x24\xe1\xeb\xee\xea\xe8\xf0\xee\xe2\xea\xe0\x5f\xef\xe5\xf0\xf1\xee\xed\xe0\xe6\xe0"); // "$блокировка_персонажа"
_blockPersFlagObj = _scene->object_interface("\x24\xe1\xeb\xee\xea\xe8\xf0\xee\xe2\xea\xe0\x5f\xef\xe5\xf0\xf1\xee\xed\xe0\xe6\xe0\x5f\xf4\xeb\xe0\xe3"); // "$блокировка_персонажа_флаг"
_shveikObj = _scene->personage_interface("\xd8\xe2\xe5\xe9\xea"); // "Швейк"
_shveikLookObj = _scene->object_interface("\x24\xf8\xe2\xe5\xe9\xea\x20\xf1\xec\xee\xf2\xf0\xe8\xf2"); // "$швейк смотрит"
_shveikMoveObj = _scene->object_interface("\x25\xF3\xEF\xF0\xE0\xE2\xEB\xE5\xED\xE8\xE5\x20\xEE\xE6\xE8\xE2\xEB\xFF\xE6\xE5\xEC\x20\xD8\xE2\xE5\xE9\xEA\xE0"); // "%управление оживляжем Швейка"
_shveikMoveEnabledObj = _scene->object_interface("\x25\xEE\xE6\xE8\xE2\xEB\xFF\xE6\x20\xD8\xE2\xE5\xE9\xEA\xE0\x20\xF0\xE0\xE7\xF0\xE5\xF8\xE5\xED"); // "%оживляж Швейка разрешен"
_someFlag = false;
_scene->activate_personage("\xd8\xe2\xe5\xe9\xea"); // "Швейк"
// srand(time(0));
_shveikIsMoving = 0;
_time = -1.0;
_timeout = -1;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "InvPopup::quant(%f)", dt);
if (_blockPersObj->is_state_active("\xe2\xea\xeb\xfe\xf7\xe8\xf2\xfc")) { // "включить"
_scene->activate_personage("Lock");
} else if (_blockPersObj->is_state_active("\xe2\xfb\xea\xeb\xfe\xf7\xe8\xf2\xfc")) { // "выключить"
_scene->activate_personage("\xd8\xe2\xe5\xe9\xea"); // "Швейк"
_blockPersObj->set_state("\xe2\xfb\xea\xeb\xfe\xf7\xe5\xed\xe0"); // "выключена"
}
qdMinigameObjectInterface *obj;
char buf[5];
const char *state = nullptr;
if (_scene->mouse_hover_object_interface())
state = _scene->mouse_hover_object_interface()->current_state_name();
if (!_scene->mouse_hover_object_interface() || _scene->mouse_object_interface()) {
_invDescObj->set_state("00");
obj = _invDescCloseupObj;
obj->set_state("00");
} else if (!strstr(state, "#inv#")) {
obj = _invDescObj;
obj->set_state("00");
} else {
const char *pos = strstr(state, "#inv#");
char buf2[5];
Common::strlcpy(buf2, pos + 5, 3);
Common::strlcpy(buf, _invDescCloseupObj->current_state_name(), 3);
if (buf2[0] != buf[0] || buf2[1] != buf[1]) {
_invDescObj->set_state(buf2);
_hoverObjectPos = _scene->mouse_hover_object_interface()->screen_R();
if (_hoverObjectPos.x + _invDescObj->screen_size().x / 2 >= 800
|| (_hoverObjectPos.x - _invDescObj->screen_size().x / 2 <= 0)) {
if (_hoverObjectPos.x + _invDescObj->screen_size().x / 2 < 800) {
if (_hoverObjectPos.x - _invDescObj->screen_size().x / 2 <= 0)
_invDescPos.x = _invDescObj->screen_size().x / 2 + 10;
} else {
_invDescPos.x = 790 - _invDescObj->screen_size().x / 2;
}
} else {
_invDescPos.x = _hoverObjectPos.x;
}
_invDescPos.y = _invDescObj->screen_size().y / 2 + 73;
_invDescObj->set_R(_scene->screen2world_coords(_invDescPos, -1000.0));
_invDescCloseupObj->set_state("00");
}
}
if (_scene->mouse_right_click_object_interface()) {
if (!_scene->mouse_object_interface()) {
state = _scene->mouse_hover_object_interface()->current_state_name();
if (strstr(state, "#closeup#")) {
const char *pos = strstr(state, "#inv#");
Common::strlcpy(buf, pos + 5, 3);
buf[2] = 0;
_invDescCloseupObj->set_state(buf);
_invDescPos.y = 300;
_invDescPos.x = 400;
_invDescCloseupObj->set_R( _scene->screen2world_coords(_invDescPos, -1000.0));
_invDescObj->set_state("00");
}
}
}
if (Common::String(_blockPersFlagObj->current_state_name()) == "\xe4\xe0") { // "да"
if (!_blockPersObj->is_state_active("\xe2\xea\xeb\xfe\xf7\xe8\xf2\xfc")) // "включить"
_blockPersObj->set_state("\xe2\xea\xeb\xfe\xf7\xe8\xf2\xfc"); // "включить"
} else if (_blockPersObj->is_state_active("\xe2\xea\xeb\xfe\xf7\xe8\xf2\xfc")) { // "включить"
_blockPersObj->set_state("\xe2\xfb\xea\xeb\xfe\xf7\xe8\xf2\xfc"); // "выключить"
}
_direction = -10;
int angle = (int)(_shveikObj->direction_angle() * 180.0 * 0.3183098865475127);
if (angle > 220 && angle < 230)
_direction = 1;
else if (angle > 265 && angle < 275)
_direction = 2;
else if (angle > 310 && angle < 320)
_direction = 3;
else if (angle > 175 && angle < 185)
_direction = 4;
else if (angle >= 0 && angle < 5)
_direction = 6;
else if (angle > 40 && angle < 50)
_direction = 9;
else if (angle > 85 && angle < 95)
_direction = 8;
else if (angle > 130 && angle < 140)
_direction = 7;
Common::String curState = _shveikObj->current_state_name();
if (curState == "#1#") {
_direction = 1;
} else if (curState == "#2#") {
_direction = 2;
} else if (curState == "#3#") {
_direction = 3;
} else if (curState == "#4#") {
_direction = 4;
} else if (curState == "#6#") {
_direction = 6;
} else if (curState == "#7#") {
_direction = 7;
} else if (curState == "#8#") {
_direction = 8;
} else if (curState == "#9#") {
_direction = 9;
}
switch (_direction) {
case -10:
_shveikLookObj->set_state("0");
break;
case 1:
_shveikLookObj->set_state("1");
break;
case 2:
_shveikLookObj->set_state("2");
break;
case 3:
_shveikLookObj->set_state("3");
break;
case 4:
_shveikLookObj->set_state("4");
break;
case 6:
_shveikLookObj->set_state("6");
break;
case 7:
_shveikLookObj->set_state("7");
break;
case 8:
_shveikLookObj->set_state("8");
break;
case 9:
_shveikLookObj->set_state("9");
break;
default:
break;
}
if (curState == "?1?") {
_direction = 10;
} else if (curState == "?2?") {
_direction = 20;
} else if (curState == "?3?") {
_direction = 30;
} else if (curState == "?4?") {
_direction = 40;
} else if (curState == "?6?") {
_direction = 60;
} else if (curState == "?7?") {
_direction = 70;
} else if (curState == "?8?") {
_direction = 80;
} else if (curState == "?9?") {
_direction = 90;
}
switch (_direction) {
case 10:
_shveikObj->set_direction_angle(5 * M_PI / 4);
break;
case 20:
_shveikObj->set_direction_angle(6 * M_PI / 4);
break;
case 30:
_shveikObj->set_direction_angle(7 * M_PI / 4);
break;
case 40:
_shveikObj->set_direction_angle(M_PI);
break;
case 60:
_shveikObj->set_direction_angle(0.0);
break;
case 70:
_shveikObj->set_direction_angle(3 * M_PI / 4);
break;
case 80:
_shveikObj->set_direction_angle(2 * M_PI / 4);
break;
case 90:
_shveikObj->set_direction_angle(1 * M_PI / 4);
break;
default:
break;
}
if (strstr(_shveikMoveEnabledObj->current_state_name(), "\xe4\xe0")) { // "да"
if (!_shveikIsMoving) {
_shveikIsMoving = 1;
_time = 0.0;
_timeout = qd_rnd(10) + 5;
}
if (_timeout >= _time || _time == -1.0) {
_time = dt + _time;
} else {
_shveikIsMoving = 2;
_time = -1.0;
_shveikMoveObj->set_state("\xe2\xfb\xef\xee\xeb\xed\xe8\xf2\xfc"); // "выполнить"
}
}
if ((strstr(_shveikMoveEnabledObj->current_state_name(), "\xed\xe5\xf2") // "нет"
|| _shveikMoveObj->is_state_active("\xee\xf2\xf0\xe0\xe1\xee\xf2\xe0\xed")) // "отработан"
&& _shveikIsMoving > 0) {
_shveikIsMoving = 0;
_time = -1.0;
_timeout = -1;
_shveikMoveObj->set_state("\xee\xe6\xe8\xe4\xe0\xed\xe8\xe5"); // "ожидание"
}
if ((_shveikObj->R().x != _oldShveikPos.x
|| _shveikObj->R().y != _oldShveikPos.y)
&& _shveikIsMoving > 0) {
_shveikIsMoving = 0;
_time = -1.0;
_timeout = -1;
_shveikMoveObj->set_state("\xee\xe6\xe8\xe4\xe0\xed\xe8\xe5"); // "ожидание"
}
_oldShveikPos = _shveikObj->R();
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "InvPopup::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
// qdMinigameObjectInterface *_invClickObj = nullptr;
qdMinigameObjectInterface *_invDescObj = nullptr;
qdMinigameObjectInterface *_invDescCloseupObj = nullptr;
// qdMinigameObjectInterface *_invActiveFlagObj = nullptr;
qdMinigameObjectInterface *_shveikObj = nullptr;
qdMinigameObjectInterface *_blockPersObj = nullptr;
qdMinigameObjectInterface *_blockPersFlagObj = nullptr;
qdMinigameObjectInterface *_shveikMoveObj = nullptr;
qdMinigameObjectInterface *_shveikMoveEnabledObj = nullptr;
qdMinigameObjectInterface *_shveikLookObj = nullptr;
mgVect2i _hoverObjectPos;
mgVect2i _invDescPos;
bool _someFlag = false;
int _direction = 0;
int _shveikIsMoving = 0;
float _time = 0;
int _timeout = 0;
mgVect3f _oldShveikPos;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_INV_POPUP_H

View 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 QDENGINE_MINIGAMES_KARTINY_H
#define QDENGINE_MINIGAMES_KARTINY_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdKartinyMiniGame : public qdMiniGameInterface {
public:
qdKartinyMiniGame() {}
~qdKartinyMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "Kartiny::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return 0;
_bg_clickObj = _scene->object_interface(_scene->minigame_parameter("zad_click_flag_name"));
_bg1_l2Obj = _scene->object_interface(_scene->minigame_parameter("zad1_l2_object_name"));
_bg2_l2Obj = _scene->object_interface(_scene->minigame_parameter("zad2_l2_object_name"));
_bg3_l2Obj = _scene->object_interface(_scene->minigame_parameter("zad3_l2_object_name"));
_bg4_l2Obj = _scene->object_interface(_scene->minigame_parameter("zad4_l2_object_name"));
_doneObj = _scene->object_interface(_scene->minigame_parameter("done"));
_startObj = _scene->object_interface(_scene->minigame_parameter("start"));
_activateObj = _scene->object_interface(_scene->minigame_parameter("activate"));
_zFlagObj = _scene->object_interface(_scene->minigame_parameter("z_flag"));
_startObj2 = _scene->object_interface(_scene->minigame_parameter("start"));
_wasInited = 0;
_artDepth = -1.0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "Kartiny::quant(%f)", dt);
mgVect3f newPiecePos;
mgVect2i piecePos;
float depth1 = _scene->screen_depth(_bg1_l2Obj->R());
float depth2 = _scene->screen_depth(_bg2_l2Obj->R());
float depth3 = _scene->screen_depth(_bg3_l2Obj->R());
float depth4 = _scene->screen_depth(_bg4_l2Obj->R());
if (depth4 >= depth3 || depth3 >= depth2 || depth2 >= depth1)
_zFlagObj->set_state("\xed\xe5\xf2"); // "нет"
else
_zFlagObj->set_state("\xe4\xe0"); // "да"
if (!_wasInited) {
if (_startObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\xe8 \xee\xef\xf3\xf9\xe5\xed\xfb")) // "задники опущены"
_wasInited = 1;
if (!_wasInited) {
if (_startObj->is_state_active("\xed\xe5\xf2")) { // "нет"
_bg1_l2Obj->set_R(_scene->screen2world_coords(mgVect2i(400, -300), 600.0));
_bg2_l2Obj->set_R(_scene->screen2world_coords(mgVect2i(200, -300), 400.0));
_bg3_l2Obj->set_R(_scene->screen2world_coords(mgVect2i(400, -300), 200.0));
_bg4_l2Obj->set_R(_scene->screen2world_coords(mgVect2i(600, -300), 0.0));
_stage = 4;
_artDepth = -50.0;
_activateObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\x34"); // "задник4"
_startObj->set_state("\xe4\xe0"); // "да"
} else {
if (_startObj->is_state_active("\xe4\xe0")) { // "да"
if (_bg1_l2Obj->screen_R().y < 100) {
piecePos.x = 400;
piecePos.y = _bg1_l2Obj->screen_R().y + 3;
_bg1_l2Obj->set_R(_scene->screen2world_coords(piecePos, 600.0));
}
if (_bg2_l2Obj->screen_R().y < 50) {
piecePos.x = 200;
piecePos.y = _bg2_l2Obj->screen_R().y + 2;
_bg2_l2Obj->set_R(_scene->screen2world_coords(piecePos, 400.0));
}
if (_bg3_l2Obj->screen_R().y < 85) {
piecePos.x = 400;
piecePos.y = _bg3_l2Obj->screen_R().y + 2;
_bg3_l2Obj->set_R(_scene->screen2world_coords(piecePos, 200.0));
}
if (_bg4_l2Obj->screen_R().y < 0) {
piecePos.x = 600;
piecePos.y = _bg4_l2Obj->screen_R().y + 2;
_bg4_l2Obj->set_R(_scene->screen2world_coords(piecePos, 0.0));
}
if (_bg1_l2Obj->screen_R().y >= 100
&& _bg2_l2Obj->screen_R().y >= 50
&& _bg3_l2Obj->screen_R().y >= 85
&& _bg4_l2Obj->screen_R().y >= 0) {
_wasInited = 1;
_startObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\xe8 \xee\xef\xf3\xf9\xe5\xed\xfb"); // "задники опущены"
}
}
if (_startObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\xe8 \xee\xef\xf3\xf9\xe5\xed\xfb") // "задники опущены"
&& _artDepth == -1.0) {
_artState[0].depth = _scene->screen_depth(_bg1_l2Obj->R());
_artState[0].num = 1;
_artState[1].depth = _scene->screen_depth(_bg2_l2Obj->R());
_artState[1].num = 2;
_artState[2].depth = _scene->screen_depth(_bg3_l2Obj->R());
_artState[2].num = 3;
_artState[3].depth = _scene->screen_depth(_bg4_l2Obj->R());
_artState[3].num = 4;
// Sort
for (int i = 0; i < 3; i++) {
while (_artState[i + 1].depth < _artState[i].depth) {
int num = _artState[i].num;
float depth = _artState[i].depth;
_artState[i].depth = _artState[i + 1].depth;
_artState[i].num = _artState[i + 1].num;
_artState[i + 1].depth = depth;
_artState[i + 1].num = num;
i = 0;
}
}
_wasInited = 1;
_stage = _artState[0].num;
_artDepth = _artState[0].depth;
}
}
}
}
if (!checkSolution() && _wasInited) {
_doneObj->set_state("false");
if (_engine->is_key_pressed(VK_LEFT)
|| _engine->is_key_pressed(VK_RIGHT)
|| _engine->is_key_pressed(VK_UP)
|| _engine->is_key_pressed(VK_DOWN)) {
++_keyDownCounter;
} else {
_keyDownCounter = 0;
}
if (_engine->is_key_pressed(VK_LEFT)) {
switch (_stage) {
case 1:
moveLeft(_bg1_l2Obj);
break;
case 2:
moveLeft(_bg2_l2Obj);
break;
case 3:
moveLeft(_bg3_l2Obj);
break;
case 4:
moveLeft(_bg4_l2Obj);
break;
default:
break;
}
}
if (_engine->is_key_pressed(VK_RIGHT)) {
switch (_stage) {
case 1:
moveRight(_bg1_l2Obj);
break;
case 2:
moveRight(_bg2_l2Obj);
break;
case 3:
moveRight(_bg3_l2Obj);
break;
case 4:
moveRight(_bg4_l2Obj);
break;
default:
break;
}
}
if (_engine->is_key_pressed(VK_UP)) {
switch (_stage) {
case 1:
moveUp(_bg1_l2Obj);
break;
case 2:
moveUp(_bg2_l2Obj);
break;
case 3:
moveUp(_bg3_l2Obj);
break;
case 4:
moveUp(_bg4_l2Obj);
break;
default:
break;
}
}
if (_engine->is_key_pressed(VK_DOWN)) {
switch (_stage) {
case 1:
moveDown(_bg1_l2Obj);
break;
case 2:
moveDown(_bg2_l2Obj);
break;
case 3:
moveDown(_bg3_l2Obj);
break;
case 4:
moveDown(_bg4_l2Obj);
break;
default:
break;
}
}
if ((_bg_clickObj->is_state_active("zad1_level2")
|| _activateObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\x31")) && _stage != 1) { // "задник1"
_stage = 1;
_activateObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\x31"); // "задник1"
_artDepth -= 200.0;
_bg1_l2Obj->set_R(_scene->screen2world_coords(_bg1_l2Obj->screen_R(), _artDepth));
snapPieces();
}
if ((_bg_clickObj->is_state_active("zad2_level2")
|| _activateObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\x32")) && _stage != 2) { // "задник2"
_stage = 2;
_activateObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\x32"); // "задник2"
_artDepth -= 200.0;
_bg2_l2Obj->set_R(_scene->screen2world_coords(_bg2_l2Obj->screen_R(), _artDepth));
snapPieces();
}
if ((_bg_clickObj->is_state_active("zad3_level2")
|| _activateObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\x33")) && _stage != 3) { // "задник3"
_stage = 3;
_activateObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\x33"); // "задник3"
_artDepth -= 200.0;
_bg3_l2Obj->set_R(_scene->screen2world_coords(_bg3_l2Obj->screen_R(), _artDepth));
snapPieces();
}
if ((_bg_clickObj->is_state_active("zad4_level2")
|| _activateObj->is_state_active("\xe7\xe0\xe4\xed\xe8\xea\x34")) && _stage != 4) { // "задник4"
_stage = 4;
_activateObj->set_state("\xe7\xe0\xe4\xed\xe8\xea\x34"); // "задник4"
_artDepth -= 200.0;
_bg4_l2Obj->set_R(_scene->screen2world_coords(_bg4_l2Obj->screen_R(), _artDepth));
snapPieces();
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "Kartiny::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
void snapPieces() {
mgVect2i piecePos;
mgVect3f newPiecePos;
float depth;
piecePos = _bg1_l2Obj->screen_R();
depth = _scene->screen_depth(_bg1_l2Obj->R());
if (ABS(399 - ABS(piecePos.x)) <= 10 && ABS(278 - ABS(piecePos.y)) <= 10) {
piecePos.x = 399;
piecePos.y = 278;
newPiecePos = _scene->screen2world_coords(piecePos, depth);
_bg1_l2Obj->set_R(newPiecePos);
}
piecePos = _bg2_l2Obj->screen_R();
depth = _scene->screen_depth(_bg2_l2Obj->R());
if (piecePos.x >= 387 && piecePos.x <= 440 && ABS(267 - ABS(piecePos.y)) <= 20) {
piecePos.x = 408;
piecePos.y = 267;
newPiecePos = _scene->screen2world_coords(piecePos, depth);
_bg2_l2Obj->set_R(newPiecePos);
}
piecePos = _bg3_l2Obj->screen_R();
depth = _scene->screen_depth(_bg3_l2Obj->R());
if (ABS(ABS(piecePos.x) - 413) < 25 && ABS(ABS(piecePos.y) - 43) < 40) {
piecePos.x = 406;
piecePos.y = -43;
newPiecePos = _scene->screen2world_coords(piecePos, depth);
_bg3_l2Obj->set_R(newPiecePos);
}
}
void moveDown(qdMinigameObjectInterface *obj) {
int speed = MAX(10, _keyDownCounter / 10 + 1);
int maxCoords;
if (obj == _bg1_l2Obj)
maxCoords = 279;
else if (obj == _bg2_l2Obj)
maxCoords = 267;
// FIXME: Remove this as covered by the default case?
//else if (obj == _bg3_l2Obj)
// maxCoords = 258;
else
maxCoords = 258;
mgVect2i objPos = obj->screen_R();
if (objPos.y + speed < maxCoords)
objPos.y += speed;
obj->set_R(_scene->screen2world_coords(objPos, _artDepth));
}
void moveUp(qdMinigameObjectInterface *obj) {
int speed = MAX(10, _keyDownCounter / 10 + 1);
mgVect2i objPos = obj->screen_R();
if (objPos.y > -100)
objPos.y -= speed;
obj->set_R(_scene->screen2world_coords(objPos, _artDepth));
}
void moveRight(qdMinigameObjectInterface *obj) {
int speed = MAX(10, _keyDownCounter / 10 + 1);
mgVect2i objPos = obj->screen_R();
if (objPos.x < 900)
objPos.x += speed;
obj->set_R(_scene->screen2world_coords(objPos, _artDepth));
}
void moveLeft(qdMinigameObjectInterface *obj) {
int speed = MAX(10, _keyDownCounter / 10 + 1);
mgVect2i objPos = obj->screen_R();
if (objPos.x > -100)
objPos.x -= speed;
obj->set_R(_scene->screen2world_coords(objPos, _artDepth));
}
bool checkSolution() {
if (_scene->screen_depth(_bg1_l2Obj->R()) < _scene->screen_depth(_bg2_l2Obj->R()))
return false;
if (_scene->screen_depth(_bg2_l2Obj->R()) < _scene->screen_depth(_bg3_l2Obj->R()))
return false;
if (_scene->screen_depth(_bg3_l2Obj->R()) < _scene->screen_depth(_bg4_l2Obj->R()))
return false;
if (ABS(_bg1_l2Obj->screen_R().x - 399) > 5
|| ABS(_bg1_l2Obj->screen_R().y - 278) > 5
|| (ABS(_bg2_l2Obj->screen_R().x - 407) > 10
&& ABS(_bg2_l2Obj->screen_R().x - 420) > 10)) // copy/paste error in the originaL?
return false;
if (ABS(_bg2_l2Obj->screen_R().y - 267) > 10)
return false;
if (_bg2_l2Obj->screen_R().x - _bg3_l2Obj->screen_R().x > 6)
return false;
if (_bg3_l2Obj->screen_R().x - _bg2_l2Obj->screen_R().x > 5)
return false;
if (ABS(_bg3_l2Obj->screen_R().y + 43) > 10)
return false;
if (_bg4_l2Obj->screen_R().x - _bg3_l2Obj->screen_R().x > 5)
return false;
if (_bg3_l2Obj->screen_R().x - _bg4_l2Obj->screen_R().x > 3)
return false;
if (ABS(_bg4_l2Obj->screen_R().y + 42) > 10)
return false;
if (ABS(_bg4_l2Obj->screen_R().y) - ABS(_bg3_l2Obj->screen_R().y) > 3)
return false;
_doneObj->set_state("true");
return true;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_bg_clickObj = nullptr;
qdMinigameObjectInterface *_bg1_l2Obj = nullptr;
qdMinigameObjectInterface *_bg2_l2Obj = nullptr;
qdMinigameObjectInterface *_bg3_l2Obj = nullptr;
qdMinigameObjectInterface *_bg4_l2Obj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
qdMinigameObjectInterface *_startObj = nullptr;
qdMinigameObjectInterface *_activateObj = nullptr;
qdMinigameObjectInterface *_zFlagObj = nullptr;
qdMinigameObjectInterface *_startObj2 = nullptr;
bool _wasInited = false;
float _artDepth = -1.0;
int _keyDownCounter = 0;
int _stage = 0;
struct {
float depth = 0;
int num = 0;
} _artState[4];
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_KARTINY_H

View File

@@ -0,0 +1,133 @@
/* 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 QDENGINE_MINIGAMES_MASKI_21_H
#define QDENGINE_MINIGAMES_MASKI_21_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdMaski21MiniGame : public qdMiniGameInterface {
public:
qdMaski21MiniGame(bool randomDll) { _randomDll = randomDll; }
~qdMaski21MiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "Maski21::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_flagObj = _scene->object_interface(_scene->minigame_parameter("command_object"));
if (!_randomDll)
_commandObj = _scene->object_interface(_scene->minigame_parameter("command_object"));
// srand(time(0))
_timePassed = -1.0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "Maski21::quant(%f)", dt);
if (!_randomDll) {
mgVect2i pos = _engine->mouse_cursor_position();
if (pos.x < 25)
_commandObj->set_state("\xe2\xeb\xe5\xe2\xee"); // "влево"
if (pos.x > 775)
_commandObj->set_state("\xe2\xef\xf0\xe0\xe2\xee"); // "вправо"
if (pos.x > 25 && pos.x < 775)
_commandObj->set_state("\xed\xe5\xf2"); // "нет"
}
if (_flagObj->is_state_active("\xe7\xe0\xef\xf3\xf1\xea")) { // "запуск"
_timePassed = 0.0;
_targetTime = qd_rnd(20) + 10;
_flagObj->set_state("\xe2\xfb\xef\xee\xeb\xed\xe5\xed\xe8\xe5"); // "выполнение"
} else if (_flagObj->is_state_active("\xe2\xfb\xef\xee\xeb\xed\xe5\xed\xe8\xe5")) { // "выполнение"
_timePassed += dt;
}
if ((float)_targetTime < _timePassed && _timePassed != -1.0 ) {
_timePassed = -1.0;
_flagObj->set_state("\xea\xee\xed\xe5\xf6"); // "конец"
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "Maski21::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_commandObj = nullptr;
qdMinigameObjectInterface *_flagObj = nullptr;
float _timePassed = -1.0;
int _targetTime = 0;
bool _randomDll = false;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_MASKI_21_H

View File

@@ -0,0 +1,326 @@
/* 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 QDENGINE_MINIGAMES_MASKY_ORDER_H
#define QDENGINE_MINIGAMES_MASKY_ORDER_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
const int pieceCoordsFront[24] = {
280, 93, 284, 163, 394, 140, 505, 120, 511, 225,
392, 255, 296, 288, 444, 369, 309, 406, 446, 479,
289, 478, 548, 420,
};
const int pieceCoordsBack[24] = {
516, 94, 511, 162, 398, 139, 293, 120, 286, 227,
404, 247, 500, 287, 353, 363, 488, 407, 354, 476,
508, 478, 247, 420,
};
class qdMaskyOrderMiniGame : public qdMiniGameInterface {
public:
qdMaskyOrderMiniGame() {
for (uint i = 0; i < ARRAYSIZE(_pieces); i++)
_pieces[i] = nullptr;
}
~qdMaskyOrderMiniGame() {};
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "MaskyOrder::init()");
_engine = engine_interface;
_scene = _engine->current_scene_interface();
if (!_scene)
return false;
for (int i = 0; i < 12; i++)
_pieces[i] = _scene->object_interface(_scene->minigame_parameter(Common::String::format("object_%i", i + 1).c_str()));
_finalObj = _scene->object_interface(_scene->minigame_parameter("final"));
_doneObj = _scene->object_interface(_scene->minigame_parameter("done_object"));
_object3Flag = _scene->object_interface(_scene->minigame_parameter("object_3_flag"));
_loadGameObj = _scene->object_interface(_scene->minigame_parameter("loadgame"));
_wasInited = false;
_isFinal = false;
_minDepthPiece = findMinDepthPiece();
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "MaskyOrder::quant(%f)", dt);
if (!_wasInited && _loadGameObj->is_state_active("\xed\xe5\xf2")) { // "нет"
_rotatingPiece = -1;
_currentPieceState = -1;
_pieceIsPut = false;
_isFinal = false;
_flipped = false;
_wasInited = true;
_loadGameObj->set_state("\xe4\xe0"); // "да"
}
if ( _object3Flag->is_state_active("\xe4\xe0")) { // "да"
_flipped = true;
_pieces[2]->set_state("back");
_object3Flag->set_state("\xed\xe5\xf2"); // "нет"
_minDepthPiece = findMinDepthPiece();
mgVect3f coords = _scene->screen2world_coords(_pieces[2]->screen_R(), _minDepthPiece);
_pieces[2]->set_R(coords);
}
if (_isFinal)
return true;
if (!checkSolution() || _scene->mouse_object_interface()) {
qdMinigameObjectInterface *mouseObj = _scene->mouse_object_interface();
if (_pieceIsPut) {
for (int i = 0; i < 12; i++) {
if (_pieces[i]->is_state_active("to_inv_flag_back")
|| _pieces[i]->is_state_active("to_inv_flag_front")) {
if (_pieces[i]->is_state_active("to_inv_flag_back"))
_currentPieceState = _pieces[i]->state_index("inv_back");
else if (_pieces[i]->is_state_active("to_inv_flag_front"))
_currentPieceState = _pieces[i]->state_index("inv_front");
_rotatingPiece = i;
_pieces[i]->set_state("to_inv");
_pieceIsPut = false;
}
}
}
if (mouseObj) {
if (_rotatingPiece != -1) {
_pieces[_rotatingPiece]->set_state(_currentPieceState);
_currentPieceState = -1;
_rotatingPiece = -1;
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)) {
mgVect2i mousePos = _engine->mouse_cursor_position();
qdMinigameObjectInterface *obj = _scene->mouse_object_interface();
if (obj) {
if (obj->is_state_active("inv_back"))
obj->set_state("back");
else if (obj->is_state_active("inv_front"))
obj->set_state("front");
_minDepthPiece -= 60.0;
mgVect3f coords = _scene->screen2world_coords(mousePos, _minDepthPiece);
obj->set_R(coords);
snapPieces();
} else {
_pieceIsPut = true;
}
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)) {
qdMinigameObjectInterface *obj = _scene->mouse_object_interface();
if (obj) {
if (obj->is_state_active("inv_back"))
obj->set_state("inv_front");
else if (obj->is_state_active("inv_front"))
obj->set_state("inv_back");
}
}
return true;
}
bool checkSolution() {
if (_scene->mouse_object_interface())
return false;
if (_pieces[0]->is_state_active("front")) {
for (int i = 0; i < 12; i++)
if (!_pieces[0]->is_state_active("front"))
return false;
} else if (_pieces[0]->is_state_active("back")) {
for (int i = 0; i < 12; i++)
if (!_pieces[0]->is_state_active("back"))
return false;
} else {
return false;
}
mgVect2i piecePos;
if (_pieces[0]->is_state_active("front"))
for (int i = 0; i < 12; i++) {
piecePos = _pieces[i]->screen_R();
if (ABS(pieceCoordsFront[i * 2 + 0] - piecePos.x) > 10 ||
ABS(pieceCoordsFront[i * 2 + 1] - piecePos.y) > 10)
return false;
}
if (_pieces[0]->is_state_active("back"))
for (int i = 0; i < 12; i++) {
piecePos = _pieces[i]->screen_R();
if (ABS(pieceCoordsBack[i * 2 + 0] - piecePos.x) > 10 ||
ABS(pieceCoordsBack[i * 2 + 1] - piecePos.y) > 10)
return false;
}
_isFinal = true;
_finalObj->set_state("\xe4\xe0"); // "да"
setPiecePositions();
return true;
}
void snapPieces() {
mgVect2i piecePos;
mgVect3f newPiecePos;
for (int i = 0; i < 12; i++) {
piecePos = _pieces[i]->screen_R();
float depth = _scene->screen_depth(_pieces[i]->R());
bool modified = false;
if (_pieces[i]->is_state_active("front")) {
if (ABS(pieceCoordsFront[i * 2 + 0] - piecePos.x) <= 10 &&
ABS(pieceCoordsFront[i * 2 + 1] - piecePos.y) <= 10) {
piecePos.x = pieceCoordsFront[i * 2 + 0];
piecePos.y = pieceCoordsFront[i * 2 + 1];
modified = true;
}
}
if (_pieces[i]->is_state_active("back")) {
if (ABS(pieceCoordsBack[i * 2 + 0] - piecePos.x) <= 10 &&
ABS(pieceCoordsBack[i * 2 + 1] - piecePos.y) <= 10) {
piecePos.x = pieceCoordsBack[i * 2 + 0];
piecePos.y = pieceCoordsBack[i * 2 + 1];
modified = true;
}
}
if (modified) {
newPiecePos = _scene->screen2world_coords(piecePos, depth);
_pieces[i]->set_R(newPiecePos);
}
}
}
bool finit() {
debugC(1, kDebugMinigames, "MaskyOrder::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
float findMinDepthPiece() {
float min = 100000.0;
for (int i = 0; i < 12; i++) {
float depth = _scene->screen_depth(_pieces[i]->R());
if (min > depth)
min = depth;
}
return min;
}
void setPiecePositions() {
mgVect3f coords(1000.0, 1000.0, 0.0);
for (int i = 0; i < 12; i++) {
_pieces[i]->set_R(coords);
}
if (_pieces[0]->is_state_active("back"))
_doneObj->set_state("back");
else
_doneObj->set_state("front");
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_pieces[12];
qdMinigameObjectInterface *_finalObj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
qdMinigameObjectInterface *_object3Flag = nullptr;
qdMinigameObjectInterface *_loadGameObj = nullptr;
bool _wasInited = false;
bool _isFinal = false;
bool _flipped = false;
float _minDepthPiece = 0.0;
int _rotatingPiece = -1;
bool _pieceIsPut = true;
int _currentPieceState = 0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_MASKY_ORDER_H

View File

@@ -0,0 +1,121 @@
/* 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 QDENGINE_MINIGAMES_ORCHESTRA_H
#define QDENGINE_MINIGAMES_ORCHESTRA_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdOrchestraMiniGame : public qdMiniGameInterface {
public:
qdOrchestraMiniGame() {}
~qdOrchestraMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "Orchestra::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_clickObj = _scene->object_interface(_scene->minigame_parameter("click_object"));
_doneObj = _scene->object_interface(_scene->minigame_parameter("done_object"));
_needReset = false;
_counter = 0;
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "Orchestra::quant(%f)", dt);
if (!_needReset) {
if (_clickObj->is_state_active("\xe4\xe0")) { // "да"
_counter++;
_clickObj->set_state("\xed\xe5\xf2"); // "нет"
if (_counter >= 20) {
_needReset = 1;
_doneObj->set_state("\xe4\xe0"); // "да"
}
}
}
if (_needReset) {
if (_doneObj->is_state_active("\xed\xe5\xf2\x31")) { // "нет1"
_needReset = false;
_counter = 0;
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "Orchestra::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_clickObj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
bool _needReset = false;
int _counter = 0;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_ORCHESTRA_H

View File

@@ -0,0 +1,351 @@
/* 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 QDENGINE_MINIGAMES_PUZZLE_ALL_H
#define QDENGINE_MINIGAMES_PUZZLE_ALL_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
const int puzzle_ep01[] = {
220, 193, 340, 186, 464, 193, 577, 186, 227, 306,
340, 306, 465, 305, 585, 306, 220, 419, 340, 426,
464, 418, 577, 426
};
const int puzzle_ep02[] = {
218, 197, 335, 194, 465, 178, 579, 181, 220, 305,
347, 304, 473, 300, 582, 298, 222, 410, 342, 416,
469, 426, 579, 427
};
const int puzzle_ep04[] = {
205, 224, 298, 224, 404, 195, 503, 189, 601, 204,
218, 319, 306, 308, 416, 287, 504, 263, 587, 285,
218, 400, 313, 408, 418, 386, 504, 387, 588, 384
};
const int puzzle_ep05[] = {
205, 223, 297, 223, 404, 194, 503, 189, 601, 203,
217, 316, 305, 306, 415, 287, 503, 262, 586, 284,
217, 397, 312, 405, 417, 384, 503, 384, 587, 382
};
const int puzzle_ep07[] = {
199, 188, 276, 185, 362, 177, 444, 172, 531, 185,
601, 183, 202, 263, 282, 258, 362, 245, 440, 248,
524, 254, 598, 265, 200, 342, 282, 341, 357, 342,
439, 341, 519, 344, 595, 340, 203, 423, 276, 420,
359, 425, 441, 421, 525, 419, 602, 414
};
const int puzzle_ep08[] = {
217, 188, 337, 181, 462, 188, 575, 181, 224, 302,
338, 301, 462, 301, 582, 301, 217, 415, 337, 422,
462, 414, 575, 421
};
const int puzzle_ep13[] = {
196, 194, 273, 194, 362, 169, 445, 164, 538, 188,
606, 188, 197, 266, 283, 255, 365, 231, 438, 235,
533, 246, 593, 271, 197, 345, 283, 341, 354, 344,
437, 341, 516, 348, 592, 340, 197, 425, 270, 424,
357, 430, 440, 427, 526, 416, 601, 412
};
class qdPuzzleAllMiniGame : public qdMiniGameInterface {
public:
qdPuzzleAllMiniGame(Common::String dll, Common::Language language) : _dll(dll), _language(language) {
for (uint i = 0; i < ARRAYSIZE(_pieces); i++)
_pieces[i] = nullptr;
}
~qdPuzzleAllMiniGame() {};
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "PuzzleAll::init(), dll: %s lang: %d", _dll.c_str(), _language);
_engine = engine_interface;
_scene = _engine->current_scene_interface();
if (!_scene)
return 0;
if (_dll == "DLL\\Puzzle_ep01.dll") { // worm
_numPieces = 12;
_pieceCoords = puzzle_ep01;
} else if (_dll == "DLL\\Puzzle_ep02.dll") { // mushrooms
_numPieces = 12;
_pieceCoords = puzzle_ep02;
} else if (_dll == "DLL\\Puzzle_ep04.dll") { // bird
_numPieces = 15;
_pieceCoords = puzzle_ep04;
} else if (_dll == "DLL\\Puzzle_ep05.dll") { // forest
_numPieces = 15;
_pieceCoords = puzzle_ep05;
} else if (_dll == "DLL\\Puzzle_ep07.dll") { // bears
_numPieces = 24;
_pieceCoords = puzzle_ep07;
} else if (_dll == "DLL\\Puzzle_ep08.dll") { // house
_numPieces = 12;
_pieceCoords = puzzle_ep08;
} else if (_dll == "DLL\\Puzzle_ep13.dll") { // harbor
_numPieces = 24;
_pieceCoords = puzzle_ep13;
}
for (int i = 0; i < _numPieces; i++)
_pieces[i] = _scene->object_interface(Common::String::format("\xee\xe1\xfa\xe5\xea\xf2_%i", i + 1).c_str()); // "объект_%i"
_objFinal = _scene->object_interface("$\xf4\xe8\xed\xe0\xeb"); // "$финал"
_objRan = _scene->object_interface("$\xe7\xe0\xef\xf3\xf1\xf2\xe8\xeb\xe8"); // "$запустили""
_wasInited = false;
if (_objFinal->is_state_active("\xed\xe5\xf2")) { // "нет"
_isFinal = false;
_minDepthPiece = findMinDepthPiece();
return true;
} else {
if (_objFinal->is_state_active("\xe4\xe0")) // "да"
_isFinal = true;
_minDepthPiece = findMinDepthPiece();
return true;
}
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "PuzzleAll::quant(%f)", dt);
if (!_wasInited && _objRan->is_state_active("\xed\xe5\xf2")) { // "нет"
_rotatingPiece = -1;
_currentPieceState = -1;
_pieceIsPut = false;
_isFinal = false;
_wasInited = 1;
_objRan->set_state("\xe4\xe0"); // "да"
}
if (_isFinal)
return true;
if (!checkSolution() || _scene->mouse_object_interface()) {
qdMinigameObjectInterface *mouseObj = _scene->mouse_object_interface();
if (_pieceIsPut) {
for (int i = 0; i < _numPieces; i++) {
if (_pieces[i]->is_state_active("to_inv_flag_0")
|| _pieces[i]->is_state_active("to_inv_flag_90")
|| _pieces[i]->is_state_active("to_inv_flag_180")
|| _pieces[i]->is_state_active("to_inv_flag_270")) {
if (_pieces[i]->is_state_active("to_inv_flag_0"))
_currentPieceState = _pieces[i]->state_index("inv_0");
else if (_pieces[i]->is_state_active("to_inv_flag_90"))
_currentPieceState = _pieces[i]->state_index("inv_90");
else if (_pieces[i]->is_state_active("to_inv_flag_180"))
_currentPieceState = _pieces[i]->state_index("inv_180");
else if (_pieces[i]->is_state_active("to_inv_flag_270"))
_currentPieceState = _pieces[i]->state_index("inv_270");
_rotatingPiece = i;
_pieces[i]->set_state("to_inv");
_pieceIsPut = false;
}
}
}
if (mouseObj) {
if (_rotatingPiece != -1) {
_pieces[_rotatingPiece]->set_state(_currentPieceState);
_currentPieceState = -1;
_rotatingPiece = -1;
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)) {
mgVect2i mousePos = _engine->mouse_cursor_position();
qdMinigameObjectInterface *obj = _scene->mouse_object_interface();
if (obj) {
if (obj->is_state_active("inv_0"))
obj->set_state("0");
else if (obj->is_state_active("inv_90"))
obj->set_state("90");
else if (obj->is_state_active("inv_180"))
obj->set_state("180");
else if (obj->is_state_active("inv_270"))
obj->set_state("270");
_minDepthPiece -= 250.0;
mgVect3f coords = _scene->screen2world_coords(mousePos, _minDepthPiece);
obj->set_R(coords);
snapPieces();
} else {
_pieceIsPut = true;
}
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)) {
qdMinigameObjectInterface *obj = _scene->mouse_object_interface();
if (obj) {
if (obj->is_state_active("inv_0"))
obj->set_state("inv_270");
else if (obj->is_state_active("inv_90"))
obj->set_state("inv_0");
else if (obj->is_state_active("inv_180"))
obj->set_state("inv_90");
else if (obj->is_state_active("inv_270"))
obj->set_state("inv_180");
}
}
return true;
}
bool checkSolution() {
if (_scene->mouse_object_interface())
return false;
for (int i = 0; i < _numPieces; i++)
if (!_pieces[0]->is_state_active("0"))
return false;
mgVect2i piecePos;
for (int i = 0; i < _numPieces; i++) {
piecePos = _pieces[i]->screen_R();
if (ABS(_pieceCoords[i * 2 + 0] - piecePos.x) > 10 ||
ABS(_pieceCoords[i * 2 + 1] - piecePos.y) > 10)
return false;
}
_isFinal = true;
_objFinal->set_state("\xe4\xe0"); // "да"
_minDepthPiece -= 250.0;
mgVect3f coords = _scene->screen2world_coords(_objFinal->screen_R(), _minDepthPiece);
_objFinal->set_R(coords);
return true;
}
void snapPieces() {
mgVect2i piecePos;
mgVect3f newPiecePos;
for (int i = 0; i < _numPieces; i++) {
piecePos = _pieces[i]->screen_R();
float depth = _scene->screen_depth(_pieces[i]->R());
if (_pieces[i]->is_state_active("0")) {
if (ABS(_pieceCoords[i * 2 + 0] - piecePos.x) <= 10 &&
ABS(_pieceCoords[i * 2 + 1] - piecePos.y) <= 10) {
piecePos.x = _pieceCoords[i * 2 + 0];
piecePos.y = _pieceCoords[i * 2 + 1];
newPiecePos = _scene->screen2world_coords(piecePos, depth);
_pieces[i]->set_R(newPiecePos);
}
}
}
}
bool finit() {
debugC(1, kDebugMinigames, "PuzzleAll::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
float findMinDepthPiece() {
float min = 100000.0;
for (int i = 0; i < _numPieces; i++) {
float depth = _scene->screen_depth(_pieces[i]->R());
if (min > depth)
min = depth;
}
return min;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_pieces[24];
const int *_pieceCoords = nullptr;
qdMinigameObjectInterface *_objFinal = nullptr;
qdMinigameObjectInterface *_objRan = nullptr;
bool _wasInited = false;
bool _isFinal = false;
float _minDepthPiece = 0.0;
int _rotatingPiece = -1;
bool _pieceIsPut = true;
int _currentPieceState = 0;
int _numPieces = 12;
Common::String _dll;
Common::Language _language;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_PUZZLE_ALL_H

View 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/>.
*
*/
#ifndef QDENGINE_MINIGAMES_QD_EMPTY_INTERFACE_H
#define QDENGINE_MINIGAMES_QD_EMPTY_INTERFACE_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdEmptyMiniGameInterface : public qdMiniGameInterface {
public:
typedef qdEmptyMiniGameInterface *(*interface_open_proc)(const char *game_name);
typedef bool (*interface_close_proc)(qdEmptyMiniGameInterface *p);
~qdEmptyMiniGameInterface() { };
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "qdEmptyMinigameInterface: This is a placeholder class");
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "qdEmptyMiniGameInterface::quant()");
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "qdEmptyMiniGameInterface::finit()");
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "qdEmptyMiniGameInterface::new_game()");
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
debugC(1, kDebugMinigames, "qdEmptyMiniGameInterface::save_game()");
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
debugC(1, kDebugMinigames, "qdEmptyMiniGameInterface::load_game()");
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_QD_EMPTY_INTERFACE_H

View File

@@ -0,0 +1,105 @@
/* 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 QDENGINE_MINIGAMES_SCROLL_H
#define QDENGINE_MINIGAMES_SCROLL_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdScrollMiniGame : public qdMiniGameInterface {
public:
qdScrollMiniGame() {}
~qdScrollMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "Scroll::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_commandObj = _scene->object_interface(_scene->minigame_parameter("command_object"));
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "Scroll::quant(%f)", dt);
mgVect2i pos = _engine->mouse_cursor_position();
if (pos.x < 25)
_commandObj->set_state("\xe2\xeb\xe5\xe2\xee"); // "влево"
if (pos.x > 775)
_commandObj->set_state("\xe2\xef\xf0\xe0\xe2\xee"); // "вправо"
if (pos.x > 25 && pos.x < 775)
_commandObj->set_state("\xed\xe5\xf2"); // "нет"
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "Scroll::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface *_commandObj = nullptr;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_SCROLL_H

View File

@@ -0,0 +1,546 @@
/* 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 QDENGINE_MINIGAMES_SHVEIK_PORTRET_H
#define QDENGINE_MINIGAMES_SHVEIK_PORTRET_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdShveikPortretMiniGame : public qdMiniGameInterface {
public:
qdShveikPortretMiniGame() {}
~qdShveikPortretMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "ShveikPortret::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_objArray[1].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31"); // "объект1"
_objArray[1].x = -1;
_objArray[1].y = -1;
_objArray[2].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32"); // "объект2"
_objArray[2].x = -1;
_objArray[2].y = -1;
_objArray[3].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x33"); // "объект3"
_objArray[3].x = -1;
_objArray[3].y = -1;
_objArray[4].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x34"); // "объект4"
_objArray[4].x = -1;
_objArray[4].y = -1;
_objArray[5].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x35"); // "объект5"
_objArray[5].x = -1;
_objArray[5].y = -1;
_objArray[6].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x36"); // "объект6"
_objArray[6].x = -1;
_objArray[6].y = -1;
_objArray[7].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x37"); // "объект7"
_objArray[7].x = -1;
_objArray[7].y = -1;
_objArray[8].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x38"); // "объект8"
_objArray[8].x = -1;
_objArray[8].y = -1;
_objArray[9].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x39"); // "объект9"
_objArray[9].x = -1;
_objArray[9].y = -1;
_objArray[10].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x30"); // "объект10"
_objArray[10].x = -1;
_objArray[10].y = -1;
_objArray[11].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x31"); // "объект11"
_objArray[11].x = -1;
_objArray[11].y = -1;
_objArray[12].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x32"); // "объект12"
_objArray[12].x = -1;
_objArray[12].y = -1;
_objArray[13].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x33"); // "объект13"
_objArray[13].x = -1;
_objArray[13].y = -1;
_objArray[14].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x34"); // "объект14"
_objArray[14].x = -1;
_objArray[14].y = -1;
_objArray[15].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x35"); // "объект15"
_objArray[15].x = -1;
_objArray[15].y = -1;
_objArray[16].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x36"); // "объект16"
_objArray[16].x = -1;
_objArray[16].y = -1;
_objArray[17].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x37"); // "объект17"
_objArray[17].x = -1;
_objArray[17].y = -1;
_objArray[18].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x38"); // "объект18"
_objArray[18].x = -1;
_objArray[18].y = -1;
_objArray[19].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x31\x39"); // "объект19"
_objArray[19].x = -1;
_objArray[19].y = -1;
_objArray[20].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32\x30"); // "объект20"
_objArray[20].x = -1;
_objArray[20].y = -1;
_objArray[21].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32\x31"); // "объект21"
_objArray[21].x = -1;
_objArray[21].y = -1;
_objArray[22].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32\x32"); // "объект22"
_objArray[22].x = -1;
_objArray[22].y = -1;
_objArray[23].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32\x33"); // "объект23"
_objArray[23].x = -1;
_objArray[23].y = -1;
_objArray[24].obj = _scene->object_interface("\xee\xe1\xfa\xe5\xea\xf2\x32\x34"); // "объект24"
_objArray[24].x = -1;
_objArray[24].y = -1;
_clickObj = _scene->object_interface("\x24\xea\xeb\xe8\xea\xe8\x20\xee\xe1\xfa\xe5\xea\xf2\xee\xec"); // "$клики объектом"
_maskOutsideObj = _scene->object_interface("\x5f\xcc\xc0\xd1\xca\xc0\x20\xec\xe5\xf1\xf2\xee\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec"); // "_МАСКА место за полем"
_objectClickObj = _scene->object_interface("\x24\xea\xeb\xe8\xea\xe8\x20\xef\xee\x20\xee\xe1\xfa\xe5\xea\xf2\xf3"); // "$клики по объекту"
_doneObj = _scene->object_interface("$done");
_wasStartedObj = _scene->object_interface("\x24\xe7\xe0\xef\xf3\xf1\xea\x5f\xe1\xfb\xeb"); // "$запуск_был"
_oneAbsentObj = _scene->object_interface("$one_absent");
_exitClickObj = _scene->object_interface("\x24\xea\xeb\xe8\xea\x20\xef\xee\x20\xe2\xfb\xf5\xee\xe4\xf3"); // "$клик по выходу"
_completePicObj = _scene->object_interface("\xe3\xee\xf2\xee\xe2\xe0\xff\x20\xea\xe0\xf0\xf2\xe8\xed\xea\xe0"); // "готовая картинка"
_currentPieceRow = -1;
_currentPieceCol = -1;
if (_wasStartedObj->is_state_active("\xed\xe5\xf2")) { // "нет"
// srand(time(0))
for (int i = 1; i <= 24; i++) {
switch (qd_rnd(3)) {
case 0:
_objArray[i].obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 0"); // "лежит за полем 0")
break;
case 1:
_objArray[i].obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 90"); // "лежит за полем 90")
break;
case 2:
_objArray[i].obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 180"); // "лежит за полем 180")
break;
case 3:
_objArray[i].obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 270"); // "лежит за полем 270")
break;
default:
break;
}
}
_wasStartedObj->set_state("\xe4\xe0"); // "да"
for (int i = 0; i < 7; i++)
for (int j = 0; j < 6; j++) {
_fieldState[i][j].angle = -1;
_fieldState[i][j].pieceNum = -1;
}
} else {
for (int i = 0; i < 7; i++)
for (int j = 0; j < 6; j++) {
_fieldState[i][j].angle = -1;
_fieldState[i][j].pieceNum = -1;
}
if (!_doneObj->is_state_active("\xe4\xe0")) // "да"
processState();
}
_exitClickObj->set_state("\xed\xe5\xf2"); // "нет"
_draggedInvObjectState = 0;
_draggedObjectState = 0;
setPiecesDepth();
setPiecesPos();
if (_oneAbsentObj->is_state_active("\xed\xe5\xf2")) { // "нет"
_objArray[2].obj->set_R(_scene->screen2world_coords(mgVect2i(700, 500), 0.0));
_oneAbsentObj->set_state("\xf4\xeb\xe0\xe3\x20\xee\xf2\xf0\xe0\xe1\xee\xf2\xe0\xed"); // "флаг отработан"
}
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "ShveikPortret::quant(%f)", dt);
if (_engine->is_key_pressed(VK_F1)) {
for (int j = 0; j < 7; j++) {
for (int i = 0; i < 6; i++) {
debugN("%02d ", _fieldState[j][i].pieceNum);
}
debugN(" ");
for (int i = 0; i < 6; i++) {
debugN("%3d ", _fieldState[j][i].angle);
}
debugN("\n");
}
debug("\n");
}
if (!_doneObj->is_state_active("\xe4\xe0")) { // "да"
if (checkSolution()) {
_doneObj->set_state("\xe4\xe0"); // "да"
_completePicObj->set_state("\xeb\xe8\xf6\xe5\xe2\xe0\xff\x20\xf1\xf2\xee\xf0\xee\xed\xe0"); // "лицевая сторона"
for (int i = 1; i <= 24; i++)
_objArray[i].obj->set_R(mgVect3f(-1000.0, -1000.0, -100.0));
_scene->activate_personage("\xd8\xe2\xe5\xe9\xea"); // "Швейк"
return true;
}
}
if (_exitClickObj->is_state_active("\xe4\xe0")) // "да"
_exitClickObj->set_state("\xe2\xfb\xf5\xee\xe4\x20\xf0\xe0\xe7\xf0\xe5\xf8\xe5\xed"); // "выход разрешен"
mgVect2i curPos = _engine->mouse_cursor_position();
if (_scene->mouse_object_interface()) {
if (_draggedObjectState) {
_objArray[_draggedObjectState].obj->set_state(_draggedInvObjectState);
_draggedInvObjectState = 0;
_draggedObjectState = 0;
}
}
int state = _clickObj->current_state_index();
qdMinigameObjectInterface *obj;
if (state > 24) {
obj = _objArray[state - 24].obj;
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 0")) { // "inv на мыши 0"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 0"); // "лежит за полем 0"
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 90")) { // "inv на мыши 90"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 90"); // "лежит за полем 90"
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 180")) { // "inv на мыши 180"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 180"); // "лежит за полем 180"
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 270")) { // "inv на мыши 270"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec 270"); // "лежит за полем 270"
}
if (_engine->mouse_cursor_position().x > 205
|| _engine->mouse_cursor_position().x <= 155) {
if (_engine->mouse_cursor_position().x < 600
|| _engine->mouse_cursor_position().x >= 649) {
obj->set_R(_scene->screen2world_coords(_engine->mouse_cursor_position(), 0.0));
} else {
mgVect2i pos = _engine->mouse_cursor_position();
pos.x = 649;
obj->set_R(_scene->screen2world_coords(pos, 0.0));
}
} else {
mgVect2i pos = _engine->mouse_cursor_position();
pos.x = 155;
obj->set_R(_scene->screen2world_coords(pos, 0.0));
}
obj->update_screen_R();
_objArray[state - 24].depth = 25.0f;
setPiecesPos();
_clickObj->set_state("\xed\xe5\xf2"); // "нет"
_maskOutsideObj->set_state("\x21\xec\xe0\xf1\xea\xe0"); // "!маска"
} else if (state > 0) {
_currentPieceRow = getPieceNumber(curPos.x, 204, 4, 99);
_currentPieceCol = getPieceNumber(curPos.y, 4, 6, 99);
obj = _objArray[state].obj;
if (_fieldState[_currentPieceRow][_currentPieceCol].pieceNum == -1) {
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 0")) { // "inv на мыши 0"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 0"); // "лежит на поле 0"
_fieldState[_currentPieceRow][_currentPieceCol].angle = 0;
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 90")) { // "inv на мыши 90"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 90"); // "лежит на поле 90"
_fieldState[_currentPieceRow][_currentPieceCol].angle = 90;
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 180")) { // "inv на мыши 180"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 180"); // "лежит на поле 180"
_fieldState[_currentPieceRow][_currentPieceCol].angle = 180;
} else if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 270")) { // "inv на мыши 270"
obj->set_state("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 270"); // "лежит на поле 270"
_fieldState[_currentPieceRow][_currentPieceCol].angle = 270;
}
mgVect2i pos;
pos.x = 99 * _currentPieceRow + 154;
pos.y = 99 * _currentPieceCol - 46;
obj->set_R(_scene->screen2world_coords(pos, 0.0));
_objArray[state].x = _currentPieceRow;
_objArray[state].y = _currentPieceCol;
_fieldState[_currentPieceRow][_currentPieceCol].pieceNum = state;
}
_clickObj->set_state("\xed\xe5\xf2"); // "нет"
_maskOutsideObj->set_state("\x21\xec\xe0\xf1\xea\xe0"); // "!маска"
}
state = _objectClickObj->current_state_index();
if (state > 0) {
obj = _objArray[state].obj;
if (obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 0") // "лежит на поле 0"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 90") // "лежит на поле 90"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 180") // "лежит на поле 180"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 270")) { // "лежит на поле 270"
_fieldState[_objArray[state].x][_objArray[state].y].pieceNum = -1;
_fieldState[_objArray[state].x][_objArray[state].y].angle = -1;
_objArray[state].x = -1;
_objArray[state].y = -1;
}
if (obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 0") // "лежит на поле 0"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec\x20\x30")) { // "лежит за полем 0"
_draggedInvObjectState = obj->state_index("inv \xed\xe0\x20\xec\xfb\xf8\xe8 0"); // "inv на мыши 0"
}
if (obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 90") // "лежит на поле 90"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec\x20\x39\x30")) { // "лежит за полем 90"
_draggedInvObjectState = obj->state_index("inv \xed\xe0\x20\xec\xfb\xf8\xe8 90"); // "inv на мыши 90"
}
if (obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 180") // "лежит на поле 180"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec\x20\x31\x38\x30")) { // "лежит за полем 180"
_draggedInvObjectState = obj->state_index("inv \xed\xe0\x20\xec\xfb\xf8\xe8 180"); // "inv на мыши 180"
}
if (obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5 270") // "лежит на поле 270"
|| obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xe7\xe0\x20\xef\xee\xeb\xe5\xec\x20\x32\x37\x30")) { // "лежит за полем 270"
_draggedInvObjectState = obj->state_index("inv \xed\xe0\x20\xec\xfb\xf8\xe8 270"); // "inv на мыши 270"
}
_draggedObjectState = state;
obj->set_state("to_inv");
_objectClickObj->set_state("\xed\xe5\xf2"); // "нет"
_maskOutsideObj->set_state("\xd4\xee\xed\x20\x2d\x20\xec\xe0\xf1\xea\xe0"); // Фон - маска"
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DOWN)
|| _engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_RIGHT_DBLCLICK)) {
obj =_scene->mouse_object_interface();
if (obj) {
if (obj->has_state("\xf3\xe4\xe0\xeb\xe8\xf2\xfc")) { // "удалить"
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 0")) { // "inv на мыши 0"
obj->set_state("inv \xed\xe0\x20\xec\xfb\xf8\xe8 90"); // "inv на мыши 90"
return true;
}
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 90")) { // "inv на мыши 90"
obj->set_state("inv \xed\xe0\x20\xec\xfb\xf8\xe8 180"); // "inv на мыши 180"
return true;
}
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 180")) { // "inv на мыши 180"
obj->set_state("inv \xed\xe0\x20\xec\xfb\xf8\xe8 270"); // "inv на мыши 270"
return true;
}
if (obj->is_state_active("inv \xed\xe0\x20\xec\xfb\xf8\xe8 270")) { // "inv на мыши 270"
obj->set_state("inv \xed\xe0\x20\xec\xfb\xf8\xe8 0"); // "inv на мыши 0"
return true;
}
}
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "ShveikPortret::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
void processState() {
for (int i = 1; i <= 24; i++) {
if (_objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x30") // "лежит на поле 0"
|| _objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x39\x30") // "лежит на поле 90"
|| _objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x31\x38\x30") // "лежит на поле 180"
|| _objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x32\x37\x30")) { // "лежит на поле 270"
mgVect2i pos = _objArray[i].obj->screen_R();
_objArray[i].x = (pos.x - 204) / 99 + 1;
_objArray[i].y = (pos.y - 4) / 99 + 1;
_fieldState[_objArray[i].x][_objArray[i].y].pieceNum = i;
if (_objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x30")) { // "лежит на поле 0"
_fieldState[_objArray[i].x][_objArray[i].y].angle = 0;
} else if (_objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x39\x30")) { // "лежит на поле 90"
_fieldState[_objArray[i].x][_objArray[i].y].angle = 90;
} else if (_objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x31\x38\x30")) { // "лежит на поле 180"
_fieldState[_objArray[i].x][_objArray[i].y].angle = 180;
} else if (_objArray[i].obj->is_state_active("\xeb\xe5\xe6\xe8\xf2\x20\xed\xe0\x20\xef\xee\xeb\xe5\x20\x32\x37\x30")) { // "лежит на поле 270"
_fieldState[_objArray[i].x][_objArray[i].y].angle = 270;
}
} else {
_objArray[i].x = -1;
_objArray[i].y = -1;
}
}
}
void setPiecesDepth() {
for (int i = 1; i <= 24; i++) {
_objArray[i].depth = i;
_objArray[i].obj->set_R(_scene->screen2world_coords(_objArray[i].obj->screen_R(), 0.0));
}
}
void setPiecesPos() {
int target = -1;
for (int j = 1; j <= 24; j++) {
int i;
for (i = 1; i <= 24; ++i) {
if (j == _objArray[i].depth)
i = 26;
}
if (i == 25) {
target = j;
break;
}
}
if (target != -1) {
for (int i = 1; i <= 24; i++) {
if (target < _objArray[i].depth)
_objArray[i].depth -= 1.0;
}
for (int i = 1; i <= 24; i++) {
_objArray[i].obj->set_R(_scene->screen2world_coords(_objArray[i].obj->screen_R(), 100.0 - _objArray[i].depth * 100.0));
}
}
}
bool checkSolution() {
int n = 1;
// The original was comparing with the static array
for (int j = 1; j < 6; j++)
for (int i = 0; i < 6; i++) {
if ((j == 1 && i == 0) || (j == 5 && i > 0))
continue;
if (_fieldState[j][i].pieceNum != n || _fieldState[j][i].angle != 0)
return false;
n++;
}
return true;
}
int getPieceNumber(int left, int right, int dimSize, int step) {
if (dimSize < 1)
return dimSize;
int res = dimSize;
int curPos = step + 204;
for (int i = 1; i <= dimSize; i++) {
if (right <= left && curPos > left)
res = i;
right += step;
curPos += step;
}
return res;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
struct PieceState {
int pieceNum = -1;
int angle = -1;
};
struct ObjectStruct {
qdMinigameObjectInterface *obj = nullptr;
int x = 0;
int y = 0;
float depth = 0.0;
};
ObjectStruct _objArray[25];
int _draggedObjectState = 0;
int _draggedInvObjectState = 0;
qdMinigameObjectInterface *_clickObj = nullptr;
qdMinigameObjectInterface *_objectClickObj = nullptr;
qdMinigameObjectInterface *_maskOutsideObj = nullptr;
qdMinigameObjectInterface *_wasStartedObj = nullptr;
qdMinigameObjectInterface *_oneAbsentObj = nullptr;
qdMinigameObjectInterface *_exitClickObj = nullptr;
qdMinigameObjectInterface *_completePicObj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
int _currentPieceRow = 0;
int _currentPieceCol = 0;
PieceState _fieldState[7][6];
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_SHVEIK_PORTRET_H

View File

@@ -0,0 +1,398 @@
/* 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 QDENGINE_MINIGAMES_SHVEIK_SHKATULKA_H
#define QDENGINE_MINIGAMES_SHVEIK_SHKATULKA_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdShveikShkatulkaMiniGame : public qdMiniGameInterface {
public:
qdShveikShkatulkaMiniGame() {}
~qdShveikShkatulkaMiniGame() {}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "ShveikShkatulka::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
_stones[0] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31"); // "камень1"
_stones[1] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x32"); // "камень2"
_stones[2] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x33"); // "камень3"
_stones[3] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x34"); // "камень4"
_stones[4] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x35"); // "камень5"
_stones[5] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x36"); // "камень6"
_stones[6] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x37"); // "камень7"
_stones[7] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x38"); // "камень8"
_stones[8] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x39"); // "камень9"
_stones[9] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31\x30"); // "камень10"
_stones[10] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31\x31"); // "камень11"
_stones[11] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31\x32"); // "камень12"
_stones[12] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31\x33"); // "камень13"
_stones[13] = _scene->object_interface("\xea\xe0\xec\xe5\xed\xfc\x31\x34"); // "камень14"
_cursorObj = _scene->object_interface("\xea\xf3\xf0\xf1\xee\xf0"); // "курсор"
_doneObj = _scene->object_interface("$done");
_startObj = _scene->object_interface("\x24\xe7\xe0\xef\xf3\xf1\xea"); // "$запуск"
_jumpSoundObj = _scene->object_interface("\xe7\xe2\xf3\xea\x20\xef\xe5\xf0\xe5\xf1\xea\xee\xea\xe0"); // "звук перескока"
_direction = kDirNone;
_cursorTakenFlag = 0;
_someVar3 = 0;
_needSnap = false;
if (_startObj->is_state_active("\xed\xe5\x20\xe1\xfb\xeb")) { // "не был"
resetStones();
_startObj->set_state("\xe1\xfb\xeb"); // "был"
}
return true;
}
enum {
kDirNone,
kDirUp,
kDirRight,
kDirDown,
kDirLeft
};
bool quant(float dt) {
debugC(3, kDebugMinigames, "ShveikShkatulka::quant(%f)", dt);
if (checkSolution()) {
_doneObj->set_state("\xe4\xe0"); // "да"
_cursorObj->set_state("nottaken");
_draggedStone = 0;
_direction = kDirNone;
_cursorTakenFlag = 0;
_someVar3 = 0;
_needSnap = 0;
return true;
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_DOWN)
&& _scene->mouse_click_object_interface()) {
const char *state = _scene->mouse_click_object_interface()->current_state_name();
if (state[0] == '1' || state[0] == '2') {
_draggedStone = _scene->mouse_click_object_interface();
_mousePos = _engine->mouse_cursor_position();
_cursorTakenFlag = 1;
_someVar3 = 1;
} else if (state[0] == '0') {
resetStones();
}
}
if (_engine->is_mouse_event_active(qdmg::qdEngineInterfaceImpl::MOUSE_EV_LEFT_UP) && _cursorTakenFlag) {
_draggedStone = 0;
_cursorTakenFlag = 0;
_someVar3 = 0;
_needSnap = false;
_direction = kDirNone;
}
mgVect2i curPos = _engine->mouse_cursor_position();
if (_cursorTakenFlag) {
if (!_needSnap) {
_mouseDelta.x = curPos.x - _mousePos.x;
_mouseDelta.y = curPos.y - _mousePos.y;
if (ABS(_mouseDelta.x) <= ABS(_mouseDelta.y)) { // Going down
const char *state = _draggedStone->current_state_name();
int draggedStonePos;
if (state[2] == '\0')
draggedStonePos = state[1] - '0';
else if (state[2] == '0')
draggedStonePos = 10;
else
draggedStonePos = 11;
int off = 60;
if (draggedStonePos == 3 || draggedStonePos == 8) {
int delta = 0;
if (curPos.y <= _mousePos.y) {
if (draggedStonePos == 3)
delta = 186;
else
delta = 0;
} else {
if (draggedStonePos == 8)
delta = 196;
else
delta = 0;
}
off = delta + 150;
}
if (ABS(_mouseDelta.y) > off) {
if (curPos.y <= _mousePos.y)
_direction = kDirUp;
else
_direction = kDirDown;
_needSnap = true;
}
} else if (ABS(_mouseDelta.x) > 60) {
if (curPos.x <= _mousePos.x)
_direction = kDirLeft;
else
_direction = kDirRight;
_needSnap = true;
}
}
if (_cursorTakenFlag && _needSnap) {
const char *state = _draggedStone->current_state_name();
int draggedStonePos;
if (state[2] == '\0')
draggedStonePos = state[1] - '0';
else if (state[2] == '0')
draggedStonePos = 10;
else
draggedStonePos = 11;
int side = state[0] - '0';
int pos = -1;
if (side == 1) {
switch (_direction) {
case kDirUp:
if (draggedStonePos != 8 || checkStonePosition(3, 1) || checkStonePosition(8, 2))
break;
pos = 3;
break;
case kDirRight:
if (draggedStonePos == 4
|| draggedStonePos == 11
|| checkStonePosition(draggedStonePos + 1, 1)
|| checkStonePosition(draggedStonePos, 2))
break;
pos = draggedStonePos + 1;
break;
case kDirDown:
if (draggedStonePos != 3 || checkStonePosition(8, 1) || checkStonePosition(8, 2))
break;
pos = 8;
break;
case kDirLeft:
if (draggedStonePos == 1
|| draggedStonePos == 5
|| checkStonePosition(draggedStonePos - 1, 1)
|| checkStonePosition(draggedStonePos - 1, 2))
break;
pos = draggedStonePos - 1;
break;
default:
break;
}
} else {
switch (_direction) {
case kDirUp:
if (draggedStonePos != 8 || checkStonePosition(3, 1) || checkStonePosition(3, 2))
break;
pos = 3;
break;
case kDirRight:
if (draggedStonePos == 4
|| draggedStonePos == 11
|| checkStonePosition(draggedStonePos + 1, 1)
|| checkStonePosition(draggedStonePos + 1, 2))
break;
pos = draggedStonePos + 1;
break;
case kDirDown:
if (draggedStonePos != 3 || checkStonePosition(8, 2) || checkStonePosition(3, 1))
break;
pos = 8;
break;
case kDirLeft:
if (draggedStonePos == 1
|| draggedStonePos == 5
|| checkStonePosition(draggedStonePos, 1)
|| checkStonePosition(draggedStonePos - 1, 2))
break;
pos = draggedStonePos - 1;
break;
default:
break;
}
}
if (pos == -1) {
_cursorTakenFlag = 0;
_someVar3 = 0;
} else {
_draggedStone->set_state(Common::String::format("%d%d", side, pos).c_str());
_mousePos = curPos;
_jumpSoundObj->set_state("\xe4\xe0"); // "да"
}
_direction = kDirNone;
_needSnap = false;
}
}
if (_cursorTakenFlag)
_cursorObj->set_state("taken");
else
_cursorObj->set_state("nottaken");
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "ShveikShkatulka::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 112 };
int version() const {
return INTERFACE_VERSION;
}
private:
void resetStones() {
_stones[0]->set_state("15");
_stones[1]->set_state("16");
_stones[2]->set_state("17");
_stones[3]->set_state("110");
_stones[4]->set_state("11");
_stones[5]->set_state("12");
_stones[6]->set_state("14");
_stones[7]->set_state("26");
_stones[8]->set_state("27");
_stones[9]->set_state("210");
_stones[10]->set_state("211");
_stones[11]->set_state("21");
_stones[12]->set_state("22");
_stones[13]->set_state("24");
}
bool checkSolution() {
return
_stones[0]->is_state_active("110")
&& _stones[1]->is_state_active("16")
&& _stones[2]->is_state_active("17")
&& _stones[3]->is_state_active("18")
&& _stones[4]->is_state_active("15")
&& _stones[5]->is_state_active("111")
&& _stones[6]->is_state_active("19")
&& _stones[7]->is_state_active("26")
&& _stones[8]->is_state_active("28")
&& _stones[9]->is_state_active("210")
&& _stones[10]->is_state_active("211")
&& _stones[11]->is_state_active("29")
&& _stones[12]->is_state_active("27")
&& _stones[13]->is_state_active("25");
}
bool checkStonePosition(int targetPos, int leftStones) {
int n = leftStones == 1 ? 0 : 7;
for (int i = 0; i < 7; i++) {
const char *state = _stones[n + i]->current_state_name();
int pos;
if (state[2] == '\0')
pos = state[1] - '0';
else if (state[2] == '0')
pos = 10;
else
pos = 11;
if (pos == targetPos)
return true;
}
return false;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
int _direction = kDirNone;
bool _cursorTakenFlag = false;
mgVect2i _mousePos;
mgVect2i _mouseDelta;
int _someVar3 = 0;
bool _needSnap = false;
qdMinigameObjectInterface *_stones[14] = { nullptr };
qdMinigameObjectInterface *_draggedStone = nullptr;
qdMinigameObjectInterface *_cursorObj = nullptr;
qdMinigameObjectInterface *_doneObj = nullptr;
qdMinigameObjectInterface *_startObj = nullptr;
qdMinigameObjectInterface *_jumpSoundObj = nullptr;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_SHVEIK_SHKATULKA_H

View File

@@ -0,0 +1,200 @@
/* 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 QDENGINE_MINIGAMES_TETRIS_H
#define QDENGINE_MINIGAMES_TETRIS_H
#include "common/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_minigame_interface.h"
namespace QDEngine {
class qdTetrisMiniGame : public qdMiniGameInterface {
public:
qdTetrisMiniGame() {
_flyingObjs = _hiddenObjs = nullptr;
}
~qdTetrisMiniGame() {
free(_flyingObjs);
free(_hiddenObjs);
}
bool init(const qdEngineInterface *engine_interface) {
debugC(1, kDebugMinigames, "Tetris::init()");
_engine = engine_interface;
_scene = engine_interface->current_scene_interface();
if (!_scene)
return false;
if (!_flyingObjs) {
_flyingObjs = (qdMinigameObjectInterface **)malloc(5 * sizeof(qdMinigameObjectInterface *));
if (!_flyingObjs)
return false;
for (int i = 0; i < 5; i++) {
Common::String name = Common::String::format("\xeb\xe5\xf2\xe8\xf2%d", i + 1); // "летит%i"
_flyingObjs[i] = _scene->object_interface(_scene->minigame_parameter(name.c_str()));
}
}
if (!_hiddenObjs) {
_hiddenObjs = (qdMinigameObjectInterface **)malloc(5 * sizeof(qdMinigameObjectInterface *));
if (!_hiddenObjs)
return false;
for (int i = 0; i < 5; i++) {
Common::String name = Common::String::format("\xf1\xea\xf0\xfb\xf2%d", i + 1); // "скрыт%i"
_hiddenObjs[i] = _scene->object_interface(_scene->minigame_parameter(name.c_str()));
}
}
_lastRowObj = _scene->object_interface(_scene->minigame_parameter("last_row"));
return true;
}
bool quant(float dt) {
debugC(3, kDebugMinigames, "Tetris::quant(%f)", dt);
for (int i = 0; i < 5; i++ ) {
if (_flyingObjs[i]->is_state_active("\xeb\xe5\xf2\xe8\xf2") // "летит"
&& _hiddenObjs[i]->is_state_active("\xed\xe5\xf2")) { // "нет"
mgVect2i pos = _flyingObjs[i]->screen_R();
if (pos.x <= 251) {
int activeColumn = getActiveColumn();
if (activeColumn < 12)
activeColumn = 12;
if (pos.y > 535 - 10 * activeColumn)
_hiddenObjs[i]->set_state("\xe4\xe0"); // "да"
} else {
if (pos.y > 535 - 10 * getActiveColumn())
_hiddenObjs[i]->set_state("\xe4\xe0"); // "да"
}
}
}
return true;
}
bool finit() {
debugC(1, kDebugMinigames, "Tetris::finit()");
if (_scene) {
_engine->release_scene_interface(_scene);
_scene = 0;
}
return true;
}
bool new_game(const qdEngineInterface *engine_interface) {
return true;
}
int save_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, char *buffer, int buffer_size) {
return 0;
}
int load_game(const qdEngineInterface *engine_interface, const qdMinigameSceneInterface *scene_interface, const char *buffer, int buffer_size) {
return 0;
}
enum { INTERFACE_VERSION = 99 };
int version() const {
return INTERFACE_VERSION;
}
private:
int getActiveColumn() {
if (_lastRowObj->is_state_active("0"))
return 0;
if (_lastRowObj->is_state_active("1"))
return 1;
if (_lastRowObj->is_state_active("2"))
return 2;
if (_lastRowObj->is_state_active("3"))
return 3;
if (_lastRowObj->is_state_active("4"))
return 4;
if (_lastRowObj->is_state_active("5"))
return 5;
if (_lastRowObj->is_state_active("6"))
return 6;
if (_lastRowObj->is_state_active("7"))
return 7;
if (_lastRowObj->is_state_active("8"))
return 8;
if (_lastRowObj->is_state_active("9"))
return 9;
if (_lastRowObj->is_state_active("10"))
return 10;
if (_lastRowObj->is_state_active("11"))
return 11;
if (_lastRowObj->is_state_active("12"))
return 12;
if (_lastRowObj->is_state_active("13"))
return 13;
if (_lastRowObj->is_state_active("14"))
return 14;
if (_lastRowObj->is_state_active("15"))
return 15;
if (_lastRowObj->is_state_active("16"))
return 16;
if (_lastRowObj->is_state_active("17"))
return 17;
if (_lastRowObj->is_state_active("18"))
return 18;
if (_lastRowObj->is_state_active("19"))
return 19;
if (_lastRowObj->is_state_active("20"))
return 20;
if (_lastRowObj->is_state_active("21"))
return 21;
if (_lastRowObj->is_state_active("22"))
return 22;
if (_lastRowObj->is_state_active("23"))
return 23;
if (_lastRowObj->is_state_active("24"))
return 24;
return 0;
}
private:
const qdEngineInterface *_engine = nullptr;
qdMinigameSceneInterface *_scene = nullptr;
qdMinigameObjectInterface **_flyingObjs = nullptr;
qdMinigameObjectInterface **_hiddenObjs = nullptr;
qdMinigameObjectInterface *_lastRowObj = nullptr;
};
} // namespace QDEngine
#endif // QDENGINE_MINIGAMES_TETRIS_H

130
engines/qdengine/module.mk Normal file
View File

@@ -0,0 +1,130 @@
MODULE := engines/qdengine
MODULE_OBJS = \
qdengine.o \
console.o \
dialogs.o \
metaengine.o \
minigames/adv/common.o \
minigames/adv/EffectManager.o \
minigames/adv/EventManager.o \
minigames/adv/ExportInterface.o \
minigames/adv/FlyObject.o \
minigames/adv/ObjectContainer.o \
minigames/adv/Range.o \
minigames/adv/RunTime.o \
minigames/adv/TextManager.o \
minigames/adv/m_karaoke.o \
minigames/adv/m_puzzle.o \
minigames/adv/m_scores.o \
minigames/adv/m_swap.o \
minigames/adv/m_triangles.o \
parser/qdscr_parser.o \
parser/xml_parser.o \
parser/xml_tag_buffer.o \
system/sound/snd_dispatcher.o \
system/sound/snd_sound.o \
system/sound/wav_sound.o \
system/graphics/gr_dispatcher.o \
system/graphics/gr_draw_sprite_rle_z.o \
system/graphics/gr_draw_sprite_rle.o \
system/graphics/gr_draw_sprite_z.o \
system/graphics/gr_draw_sprite.o \
system/graphics/gr_font.o \
system/graphics/gr_tile_animation.o \
system/graphics/gr_tile_sprite.o \
system/graphics/rle_compress.o \
system/graphics/UI_TextParser.o \
system/input/input_wndproc.o \
system/input/keyboard_input.o \
system/input/mouse_input.o \
qdcore/util/AIAStar_API.o \
qdcore/util/fps_counter.o \
qdcore/util/LZ77.o \
qdcore/util/plaympp_api.o \
qdcore/util/ResourceDispatcher.o \
qdcore/util/splash_screen.o \
qdcore/util/WinVideo.o \
qdcore/qd_animation_frame.o \
qdcore/qd_animation_info.o \
qdcore/qd_animation_set_info.o \
qdcore/qd_animation_set_preview.o \
qdcore/qd_animation_set.o \
qdcore/qd_animation.o \
qdcore/qd_camera.o \
qdcore/qd_camera_mode.o \
qdcore/qd_condition.o \
qdcore/qd_condition_data.o \
qdcore/qd_condition_group.o \
qdcore/qd_condition_object_reference.o \
qdcore/qd_conditional_object.o \
qdcore/qd_contour.o \
qdcore/qd_coords_animation_point.o \
qdcore/qd_coords_animation.o \
qdcore/qd_counter.o \
qdcore/qd_d3dutils.o \
qdcore/qd_file_manager.o \
qdcore/qd_font_info.o \
qdcore/qd_game_dispatcher.o \
qdcore/qd_game_dispatcher_base.o \
qdcore/qd_game_end.o \
qdcore/qd_game_object.o \
qdcore/qd_game_object_animated.o \
qdcore/qd_game_object_mouse.o \
qdcore/qd_game_object_moving.o \
qdcore/qd_game_object_state.o \
qdcore/qd_game_object_static.o \
qdcore/qd_game_scene.o \
qdcore/qd_grid_zone.o \
qdcore/qd_grid_zone_state.o \
qdcore/qd_interface_background.o \
qdcore/qd_interface_button.o \
qdcore/qd_interface_counter.o \
qdcore/qd_interface_dispatcher.o \
qdcore/qd_interface_element.o \
qdcore/qd_interface_element_state_mode.o \
qdcore/qd_interface_element_state.o \
qdcore/qd_interface_object_base.o \
qdcore/qd_interface_save.o \
qdcore/qd_interface_screen.o \
qdcore/qd_interface_slider.o \
qdcore/qd_interface_text_window.o \
qdcore/qd_inventory.o \
qdcore/qd_inventory_cell.o \
qdcore/qd_minigame.o \
qdcore/qd_minigame_config.o \
qdcore/qd_minigame_interface.o \
qdcore/qd_music_track.o \
qdcore/qd_named_object.o \
qdcore/qd_named_object_base.o \
qdcore/qd_named_object_indexer.o \
qdcore/qd_named_object_reference.o \
qdcore/qd_resource.o \
qdcore/qd_scale_info.o \
qdcore/qd_screen_text.o \
qdcore/qd_screen_text_dispatcher.o \
qdcore/qd_screen_text_set.o \
qdcore/qd_setup.o \
qdcore/qd_sound.o \
qdcore/qd_sound_info.o \
qdcore/qd_sprite.o \
qdcore/qd_textdb.o \
qdcore/qd_trigger_chain.o \
qdcore/qd_trigger_element.o \
qdcore/qd_video.o
ifdef USE_IMGUI
MODULE_OBJS += \
debugger/debugtools.o
endif
# This module can be built as a plugin
ifeq ($(ENABLE_QDENGINE), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

View File

@@ -0,0 +1,378 @@
/* 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 "qdengine/qd_fwd.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/parser/xml_parser.h"
namespace QDEngine {
xml::parser *parser = nullptr;
void cleanup_XML_Parser() {
delete parser;
parser = nullptr;
}
xml::parser &qdscr_XML_Parser() {
if (!parser)
parser = new xml::parser;
if (!parser->num_tag_formats()) {
parser->register_tag_format("qd_script", xml::tag(QDSCR_ROOT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("ID", xml::tag(QDSCR_ID, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("x", xml::tag(QDSCR_X, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("y", xml::tag(QDSCR_Y, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("sx", xml::tag(QDSCR_SX, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("sy", xml::tag(QDSCR_SY, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("pos_2d", xml::tag(QDSCR_POS2D, xml::tag::TAG_DATA_FLOAT, 2));
parser->register_tag_format("pos_3d", xml::tag(QDSCR_POS3D, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("src_pos", xml::tag(QDSCR_SRC_POS, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("dest_pos", xml::tag(QDSCR_DEST_POS, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("file", xml::tag(QDSCR_FILE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("start_time", xml::tag(QDSCR_START_TIME, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("period", xml::tag(QDSCR_PERIOD, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("length", xml::tag(QDSCR_LENGTH, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("speed", xml::tag(QDSCR_SPEED, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("animation_speed", xml::tag(QDSCR_ANIMATION_SPEED, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("interpolation_time", xml::tag(QDSCR_INTERPOLATION_TIME, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("scale", xml::tag(QDSCR_SCALE, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("name", xml::tag(QDSCR_NAME, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("flag", xml::tag(QDSCR_FLAG, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("flags", xml::tag(QDSCR_FLAG, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("rnd", xml::tag(QDSCR_RND, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("mask_size", xml::tag(QDSCR_MASK_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("mask_attributes", xml::tag(QDSCR_MASK_ATTRIBUTES, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("mask_heights", xml::tag(QDSCR_MASK_HEIGHTS, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("bound", xml::tag(QDSCR_BOUND, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("type", xml::tag(QDSCR_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("size", xml::tag(QDSCR_SIZE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("state", xml::tag(QDSCR_STATE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("text", xml::tag(QDSCR_TEXT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("short_text", xml::tag(QDSCR_SHORT_TEXT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("value", xml::tag(QDSCR_VALUE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("time", xml::tag(QDSCR_TIME, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("cd", xml::tag(QDSCR_CD, xml::tag::TAG_DATA_UNSIGNED_INT, 1));
parser->register_tag_format("align", xml::tag(QDSCR_ALIGN, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("valign", xml::tag(QDSCR_VALIGN, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("orientation", xml::tag(QDSCR_ORIENTATION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("color", xml::tag(QDSCR_COLOR, xml::tag::TAG_DATA_UNSIGNED_INT, 1));
parser->register_tag_format("comment", xml::tag(QDSCR_COMMENT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("font_info", xml::tag(QDSCR_FONT_INFO, xml::tag::TAG_DATA_VOID, -1));
parser->register_tag_format("screen_size", xml::tag(QDSCR_SCREEN_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("text_set", xml::tag(QDSCR_TEXT_SET, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("text_color", xml::tag(QDSCR_TEXT_COLOR, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("text_hover_color", xml::tag(QDSCR_TEXT_HOVER_COLOR, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("text_align", xml::tag(QDSCR_TEXT_ALIGN, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("contour_rect", xml::tag(QDSCR_CONTOUR_RECTANGLE, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("contour_circle", xml::tag(QDSCR_CONTOUR_CIRCLE, xml::tag::TAG_DATA_SHORT, 1));
parser->register_tag_format("contour_polygon", xml::tag(QDSCR_CONTOUR_POLYGON, xml::tag::TAG_DATA_SHORT, -1));
parser->register_tag_format("named_object", xml::tag(QDSCR_NAMED_OBJECT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("types", xml::tag(QDSCR_NAMED_OBJECT_TYPES, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("grid_zone", xml::tag(QDSCR_GRID_ZONE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("grid_zone_cells", xml::tag(QDSCR_GRID_ZONE_CELLS, xml::tag::TAG_DATA_SHORT, -1));
parser->register_tag_format("grid_zone_height", xml::tag(QDSCR_GRID_ZONE_HEIGHT, xml::tag::TAG_DATA_UNSIGNED_INT, 1));
parser->register_tag_format("grid_zone_contour", xml::tag(QDSCR_GRID_ZONE_CONTOUR, xml::tag::TAG_DATA_SHORT, -1));
parser->register_tag_format("grid_zone_state", xml::tag(QDSCR_GRID_ZONE_STATE, xml::tag::TAG_DATA_VOID, -1));
parser->register_tag_format("shadow_color", xml::tag(QDSCR_GRID_ZONE_SHADOW_COLOR, xml::tag::TAG_DATA_UNSIGNED_INT, 1));
parser->register_tag_format("shadow_alpha", xml::tag(QDSCR_GRID_ZONE_SHADOW_ALPHA, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("trigger_element", xml::tag(QDSCR_TRIGGER_ELEMENT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("trigger_element_link", xml::tag(QDSCR_TRIGGER_ELEMENT_LINK, xml::tag::TAG_DATA_INT, 3));
parser->register_tag_format("parent_links", xml::tag(QDSCR_TRIGGER_ELEMENT_PARENT_LINKS, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("child_links", xml::tag(QDSCR_TRIGGER_ELEMENT_CHILD_LINKS, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("link", xml::tag(QDSCR_TRIGGER_ELEMENT_LINK, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("auto_restart", xml::tag(QDSCR_TRIGGER_ELEMENT_LINK_AUTO_RESTART, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("start_element", xml::tag(QDSCR_TRIGGER_START_ELEMENT, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("trigger_chain", xml::tag(QDSCR_TRIGGER_CHAIN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("trigger_chain_root", xml::tag(QDSCR_TRIGGER_CHAIN_ROOT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("sound", xml::tag(QDSCR_SOUND, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("volume", xml::tag(QDSCR_SOUND_VOLUME, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("music_track", xml::tag(QDSCR_MUSIC_TRACK, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("cycled", xml::tag(QDSCR_MUSIC_TRACK_CYCLED, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("video", xml::tag(QDSCR_VIDEO, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("video_position", xml::tag(QDSCR_VIDEO_POSITION, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("video_background", xml::tag(QDSCR_VIDEO_BACKGROUND, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("minigame", xml::tag(QDSCR_MINIGAME, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("dll_name", xml::tag(QDSCR_MINIGAME_DLL_NAME, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("game_name", xml::tag(QDSCR_MINIGAME_GAME_NAME, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("config_file", xml::tag(QDSCR_MINIGAME_CONFIG_FILE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("minigame_state", xml::tag(QDSCR_MINIGAME_STATE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("score", xml::tag(QDSCR_MINIGAME_SCORE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("minigame_config_prm", xml::tag(QDSCR_MINIGAME_CONFIG_PARAMETER, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animation_frame", xml::tag(QDSCR_ANIMATION_FRAME, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("animation_info", xml::tag(QDSCR_ANIMATION_INFO, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("animation_file", xml::tag(QDSCR_ANIMATION_FILE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animation", xml::tag(QDSCR_ANIMATION, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animation_set", xml::tag(QDSCR_ANIMATION_SET, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("start_angle", xml::tag(QDSCR_ANIMATION_SET_START_ANGLE, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("animation_turn", xml::tag(QDSCR_ANIMATION_SET_TURN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("walk_sound_frequency", xml::tag(QDSCR_OBJECT_STATE_WALK_SOUND_FREQUENCY, xml::tag::TAG_DATA_FLOAT, -1));
parser->register_tag_format("center_offsets", xml::tag(QDSCR_STATE_CENTER_OFFSETS, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("static_center_offsets", xml::tag(QDSCR_STATE_STATIC_CENTER_OFFSETS, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("start_center_offsets", xml::tag(QDSCR_STATE_START_CENTER_OFFSETS, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("stop_center_offsets", xml::tag(QDSCR_STATE_STOP_CENTER_OFFSETS, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("coords_animation_point", xml::tag(QDSCR_COORDS_ANIMATION_POINT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("coords_animation", xml::tag(QDSCR_COORDS_ANIMATION, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animation_phase", xml::tag(QDSCR_ANIMATION_PHASE, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("parallax_offset", xml::tag(QDSCR_PARALLAX_OFFSET, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("static_object", xml::tag(QDSCR_STATIC_OBJECT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animated_object", xml::tag(QDSCR_ANIMATED_OBJECT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("object_state", xml::tag(QDSCR_OBJECT_STATE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("movement_states", xml::tag(QDSCR_OBJECT_MOVEMENT_STATES, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("object_movement_state", xml::tag(QDSCR_OBJECT_MOVEMENT_STATE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("object_direction", xml::tag(QDSCR_OBJECT_DIRECTION, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("default_pos", xml::tag(QDSCR_OBJECT_DEFAULT_POS, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("default_direction", xml::tag(QDSCR_OBJECT_DEFAULT_DIRECTION, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("object_state_static", xml::tag(QDSCR_OBJECT_STATE_STATIC, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("object_state_walk", xml::tag(QDSCR_OBJECT_STATE_WALK, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("object_state_mask", xml::tag(QDSCR_OBJECT_STATE_MASK, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("state_mask_pos", xml::tag(QDSCR_OBJECT_STATE_MASK_POS, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("state_mask_size", xml::tag(QDSCR_OBJECT_STATE_MASK_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("state_mask_data", xml::tag(QDSCR_OBJECT_STATE_MASK_DATA, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("state_mask_parent", xml::tag(QDSCR_OBJECT_STATE_MASK_PARENT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("state_mask_contour", xml::tag(QDSCR_OBJECT_STATE_MASK_CONTOUR, xml::tag::TAG_DATA_SHORT, -1));
parser->register_tag_format("center_offset", xml::tag(QDSCR_OBJECT_STATE_CENTER_OFFSET, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("state_activation_delay", xml::tag(QDSCR_OBJECT_STATE_DELAY, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("sound_delay", xml::tag(QDSCR_OBJECT_STATE_SOUND_DELAY, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("text_delay", xml::tag(QDSCR_OBJECT_STATE_TEXT_DELAY, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("cursor_id", xml::tag(QDSCR_OBJECT_STATE_CURSOR_ID, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("acceleration", xml::tag(QDSCR_OBJECT_STATE_ACCELERATION, xml::tag::TAG_DATA_FLOAT, 2));
parser->register_tag_format("rnd_move", xml::tag(QDSCR_OBJECT_STATE_RND_MOVE, xml::tag::TAG_DATA_FLOAT, 2));
parser->register_tag_format("condition", xml::tag(QDSCR_CONDITION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("condition_data_int", xml::tag(QDSCR_CONDITION_DATA_INT, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("condition_data_float", xml::tag(QDSCR_CONDITION_DATA_FLOAT, xml::tag::TAG_DATA_FLOAT, -1));
parser->register_tag_format("condition_data_string", xml::tag(QDSCR_CONDITION_DATA_STRING, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("condition_inverse", xml::tag(QDSCR_CONDITION_INVERSE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("conditions_mode", xml::tag(QDSCR_CONDITIONS_MODE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("condition_group", xml::tag(QDSCR_CONDITION_GROUP, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("condition_object", xml::tag(QDSCR_CONDITION_OBJECT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("counter", xml::tag(QDSCR_COUNTER, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("counter_element", xml::tag(QDSCR_COUNTER_ELEMENT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("inc_value", xml::tag(QDSCR_COUNTER_INC_VALUE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("limit", xml::tag(QDSCR_COUNTER_LIMIT, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("digits", xml::tag(QDSCR_COUNTER_DIGITS, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("counter_name", xml::tag(QDSCR_COUNTER_NAME, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("object_scale", xml::tag(QDSCR_OBJ_SCALE_INFO, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("mouse_object", xml::tag(QDSCR_MOUSE_OBJECT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("default_cursors", xml::tag(QDSCR_MOUSE_DEFAULT_CURSORS, xml::tag::TAG_DATA_INT, 6));
parser->register_tag_format("movement_animation_num", xml::tag(QDSCR_MOVEMENT_ANIMATION_NUMBER, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("movement_animations", xml::tag(QDSCR_MOVEMENT_ANIMATIONS, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("static_animations", xml::tag(QDSCR_STATIC_ANIMATIONS, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("moving_object", xml::tag(QDSCR_MOVING_OBJECT, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("collision_radius", xml::tag(QDSCR_COLLISION_RADIUS, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("collision_delay", xml::tag(QDSCR_COLLISION_DELAY, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("collision_path", xml::tag(QDSCR_COLLISION_PATH, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("follow_min_radius", xml::tag(QDSCR_FOLLOW_MIN_RADIUS, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("follow_max_radius", xml::tag(QDSCR_FOLLOW_MAX_RADIUS, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("attach_shift", xml::tag(QDSCR_ATTACH_SHIFT, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("control", xml::tag(QDSCR_PERSONAGE_CONTROL, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("movement", xml::tag(QDSCR_PERSONAGE_MOVEMENT_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("rotation_angle_per_quant", xml::tag(QDSCR_ROTATION_ANGLE_PER_QUANT, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("inventory_cell_type", xml::tag(QDSCR_INVENTORY_CELL_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("inventory_cell_set", xml::tag(QDSCR_INVENTORY_CELL_SET, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("inventory_cell_set_size", xml::tag(QDSCR_INVENTORY_CELL_SET_SIZE, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("inventory_cell_set_additional_cells", xml::tag(QDSCR_INVENTORY_CELL_SET_ADDITIONAL_CELLS, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("inventory_cell_set_pos", xml::tag(QDSCR_INVENTORY_CELL_SET_POS, xml::tag::TAG_DATA_SHORT, 2));
parser->register_tag_format("inventory", xml::tag(QDSCR_INVENTORY, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("camera", xml::tag(QDSCR_CAMERA, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("camera_grid_size", xml::tag(QDSCR_CAMERA_GRID_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("camera_grid_height", xml::tag(QDSCR_CAMERA_GRID_HEIGHT, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("camera_grid_attributes", xml::tag(QDSCR_CAMERA_GRID_ATTRIBUTES, xml::tag::TAG_DATA_INT, -1));
parser->register_tag_format("camera_grid_center", xml::tag(QDSCR_CAMERA_GRID_CENTER, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("camera_cell_size", xml::tag(QDSCR_CAMERA_CELL_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("camera_focus", xml::tag(QDSCR_CAMERA_FOCUS, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("camera_angles", xml::tag(QDSCR_CAMERA_ANGLES, xml::tag::TAG_DATA_FLOAT, 3));
parser->register_tag_format("camera_screen_size", xml::tag(QDSCR_CAMERA_SCREEN_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("camera_screen_offset", xml::tag(QDSCR_CAMERA_SCREEN_OFFSET, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("camera_screen_center", xml::tag(QDSCR_CAMERA_SCREEN_CENTER, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("camera_mode", xml::tag(QDSCR_CAMERA_MODE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("scrolling_speed", xml::tag(QDSCR_CAMERA_SCROLLING_SPEED, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("scrolling_dist", xml::tag(QDSCR_CAMERA_SCROLLING_DIST, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("smooth_switch", xml::tag(QDSCR_CAMERA_SMOOTH_SWITCH, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("camera_scale_pow", xml::tag(QDSCR_CAMERA_SCALE_POW, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("camera_scale_z_offset", xml::tag(QDSCR_CAMERA_SCALE_Z_OFFSET, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("game_end", xml::tag(QDSCR_GAME_END, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("end_screen", xml::tag(QDSCR_GAME_END_SCREEN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("interface", xml::tag(QDSCR_INTERFACE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("draw_scene", xml::tag(QDSCR_INTERFACE_SCENE_REDRAW, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("main_menu", xml::tag(QDSCR_INTERFACE_MAIN_MENU, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("ingame_screen0", xml::tag(QDSCR_INTERFACE_INGAME_SCREEN0, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("ingame_screen1", xml::tag(QDSCR_INTERFACE_INGAME_SCREEN1, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("save_prompt_screen", xml::tag(QDSCR_INTERFACE_SAVE_PROMPT_SCREEN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("save_title_screen", xml::tag(QDSCR_INTERFACE_SAVE_NAME_SCREEN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("highscore_name_screen", xml::tag(QDSCR_INTERFACE_HIGHSCORE_NAME_SCREEN, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("need_save_screenshot", xml::tag(QDSCR_INTERFACE_NEED_SAVE_SCREENSHOT, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("need_show_save_name", xml::tag(QDSCR_INTERFACE_NEED_SHOW_SAVE_NAME, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("need_show_save_time", xml::tag(QDSCR_INTERFACE_NEED_SHOW_SAVE_TIME, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("save_font_type", xml::tag(QDSCR_INTERFACE_SAVE_FONT_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("save_font_color", xml::tag(QDSCR_INTERFACE_SAVE_FONT_COLOR, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("is_autosave", xml::tag(QDSCR_INTERFACE_SAVE_IS_AUTOSAVE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("interface_screen", xml::tag(QDSCR_INTERFACE_SCREEN, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("hide_time", xml::tag(QDSCR_INTERFACE_SCREEN_HIDE_TIME, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("hide_offset", xml::tag(QDSCR_INTERFACE_SCREEN_HIDE_OFFSET, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("interface_element", xml::tag(QDSCR_INTERFACE_ELEMENT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("interface_element_state", xml::tag(QDSCR_INTERFACE_ELEMENT_STATE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("state_mode", xml::tag(QDSCR_INTERFACE_ELEMENT_STATE_MODE, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("pos", xml::tag(QDSCR_INTERFACE_ELEMENT_POS, xml::tag::TAG_DATA_INT, 3));
parser->register_tag_format("option_id", xml::tag(QDSCR_INTERFACE_OPTION_ID, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("event", xml::tag(QDSCR_INTERFACE_EVENT, xml::tag::TAG_DATA_VOID, 1));
parser->register_tag_format("event_data", xml::tag(QDSCR_INTERFACE_EVENT_DATA, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("before_animation", xml::tag(QDSCR_INTERFACE_EVENT_BEFORE_ANIMATION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("activation_type", xml::tag(QDSCR_INTERFACE_EVENT_ACTIVATION_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("action", xml::tag(QDSCR_INTERFACE_ACTION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("action_data", xml::tag(QDSCR_INTERFACE_ACTION_DATA, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("animation_flags", xml::tag(QDSCR_INTERFACE_ANIMATION_FLAGS, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("slider_rect", xml::tag(QDSCR_INTERFACE_SLIDER_RECTANGLE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("slider_orientation", xml::tag(QDSCR_INTERFACE_SLIDER_ORIENTATION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("background_offset", xml::tag(QDSCR_INTERFACE_BACKGROUND_OFFSET, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("thumbnail_size", xml::tag(QDSCR_INTERFACE_THUMBNAIL_SIZE, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("text_shift", xml::tag(QDSCR_INTERFACE_TEXT_SHIFT, xml::tag::TAG_DATA_INT, 2));
parser->register_tag_format("border_corner", xml::tag(QDSCR_TEXT_WINDOW_BORDER_CORNER, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("border_line", xml::tag(QDSCR_TEXT_WINDOW_BORDER_LINE_H, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("border_vline", xml::tag(QDSCR_TEXT_WINDOW_BORDER_LINE_V, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("border_back", xml::tag(QDSCR_TEXT_WINDOW_BORDER_BACK, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("window_slider", xml::tag(QDSCR_TEXT_WINDOW_SLIDER, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("window_type", xml::tag(QDSCR_TEXT_WINDOW_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("string_length", xml::tag(QDSCR_TEXT_WINDOW_MAX_STRING_LENGTH, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("info_type", xml::tag(QDSCR_TEXT_WINDOW_INFO_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("player_id", xml::tag(QDSCR_TEXT_WINDOW_PLAYER_ID, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("scene", xml::tag(QDSCR_SCENE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("save_slot", xml::tag(QDSCR_SCENE_SAVE_SLOT, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("startup_scene", xml::tag(QDSCR_STARTUP_SCENE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("restart_minigame", xml::tag(QDSCR_SCENE_RESTART_MINIGAME, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("location", xml::tag(QDSCR_LOCATION, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("game_title", xml::tag(QDSCR_GAME_TITLE, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("text_db", xml::tag(QDSCR_TEXT_DB, xml::tag::TAG_DATA_STRING, -1));
parser->register_tag_format("cd_key", xml::tag(QDSCR_CD_KEY, xml::tag::TAG_DATA_STRING, -1));
// For qdScreenTextFormat
parser->register_tag_format("screen_text_format", xml::tag(QDSCR_SCREEN_TEXT_FORMAT, xml::tag::TAG_DATA_VOID, -1));
parser->register_tag_format("font_type", xml::tag(QDSCR_FONT_TYPE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("default_font", xml::tag(QDSCR_DEFAULT_FONT, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("global_depend", xml::tag(QDSCR_GLOBAL_DEPEND, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("inverse_direction", xml::tag(QDSCR_INVERSE_DIRECTION, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("alpha", xml::tag(QDSCR_ALPHA, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("enable_background", xml::tag(QDSCR_ENABLE_BACKGROUND, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("fade_time", xml::tag(QDSCR_FADE_TIME, xml::tag::TAG_DATA_FLOAT, 1));
parser->register_tag_format("hof_size", xml::tag(QDSCR_HALL_OF_FAME_SIZE, xml::tag::TAG_DATA_INT, 1));
parser->register_tag_format("screen_transform", xml::tag(QDSCR_SCREEN_TRANSFORM, xml::tag::TAG_DATA_FLOAT, 6));
parser->register_tag_format("compression", xml::tag(QDSCR_RESOURCE_COMPRESSION, xml::tag::TAG_DATA_INT, 1));
}
return *parser;
}
const char *qdscr_XML_string(const char *p) {
static Common::String conv_str;
conv_str = p;
uint32 pos = conv_str.find("&");;
while (pos != Common::String::npos) {
conv_str.replace(pos, 1, "&amp;");
pos = conv_str.find("&", pos + 1);
}
pos = conv_str.find("<");
while (pos != Common::String::npos) {
conv_str.replace(pos, 1, "&lt;");
pos = conv_str.find("<", pos + 1);
}
pos = conv_str.find(">");
while (pos != Common::String::npos) {
conv_str.replace(pos, 1, "&gt;");
pos = conv_str.find(">", pos + 1);
}
pos = conv_str.find("\"");
while (pos != Common::String::npos) {
conv_str.replace(pos, 1, "&quot;");
pos = conv_str.find("\"", pos + 1);
}
pos = conv_str.find("'");
while (pos != Common::String::npos) {
conv_str.replace(pos, 1, "&#039;");
pos = conv_str.find("'", pos + 1);
}
return (const char *)transCyrillic(conv_str.c_str());
}
const char *qdscr_XML_string(const Common::String &s) {
return qdscr_XML_string(s.c_str());
}
} // namespace QDEngine

View File

@@ -0,0 +1,715 @@
/* 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 QDENGINE_PARSER_QDSCR_PARSER_H
#define QDENGINE_PARSER_QDSCR_PARSER_H
#include "qdengine/parser/xml_fwd.h"
namespace QDEngine {
/*
qda_version = 100: 20020404
qda_version = 101: 20020730
qda_version = 102: 20020822
qda_version = 103: 20030829
qda_version = 104: < 20060129
*/
/* Version 20050101 is artificial and used by mng between
20040601 and 20060129
*/
//! Идентификаторы тэгов скрипта.
enum qdscrTagID {
QDSCR_ROOT = 1,
// Common
QDSCR_ID,
QDSCR_X,
QDSCR_Y,
QDSCR_SX, // 5
QDSCR_SY,
QDSCR_POS2D,
QDSCR_POS3D,
QDSCR_SRC_POS,
QDSCR_DEST_POS, // 10
QDSCR_FILE,
QDSCR_START_TIME,
QDSCR_PERIOD,
QDSCR_LENGTH,
QDSCR_SPEED, // 15
QDSCR_ANIMATION_SPEED,
QDSCR_INTERPOLATION_TIME,
QDSCR_SCALE,
QDSCR_NAME,
QDSCR_FLAG, // 20
QDSCR_RND,
QDSCR_MASK_SIZE,
QDSCR_MASK_ATTRIBUTES,
QDSCR_MASK_HEIGHTS,
QDSCR_BOUND, // 25
QDSCR_TYPE,
QDSCR_SIZE,
QDSCR_STATE,
QDSCR_TEXT,
QDSCR_SHORT_TEXT, // 30
QDSCR_VALUE,
QDSCR_TIME,
QDSCR_CD,
QDSCR_ALIGN,
QDSCR_VALIGN, // 35
QDSCR_ORIENTATION,
QDSCR_COLOR,
QDSCR_COMMENT,
QDSCR_SCREEN_SIZE,
QDSCR_TEXT_SET, // 40
// Text
QDSCR_TEXT_COLOR,
QDSCR_TEXT_HOVER_COLOR,
QDSCR_TEXT_ALIGN,
// Fonts
QDSCR_FONT_INFO,
// Contours
QDSCR_CONTOUR_RECTANGLE, // 45
QDSCR_CONTOUR_CIRCLE,
QDSCR_CONTOUR_POLYGON,
// Named Object Reference
QDSCR_NAMED_OBJECT,
QDSCR_NAMED_OBJECT_TYPES,
// Grid zone
QDSCR_GRID_ZONE, // 50
QDSCR_GRID_ZONE_CELLS,
QDSCR_GRID_ZONE_HEIGHT,
QDSCR_GRID_ZONE_CONTOUR,
QDSCR_GRID_ZONE_STATE,
QDSCR_GRID_ZONE_SHADOW_COLOR, // 55
QDSCR_GRID_ZONE_SHADOW_ALPHA,
// Trigger Element
QDSCR_TRIGGER_ELEMENT,
QDSCR_TRIGGER_ELEMENT_LINK,
QDSCR_TRIGGER_ELEMENT_PARENT_LINKS,
QDSCR_TRIGGER_ELEMENT_CHILD_LINKS, // 60
QDSCR_TRIGGER_ELEMENT_LINK_AUTO_RESTART,
QDSCR_TRIGGER_ELEMENT_LINK_OFFSETS,
QDSCR_TRIGGER_ELEMENT_TITLE,
QDSCR_TRIGGER_ELEMENT_CELL_NUMBER,
QDSCR_TRIGGER_PARENT_LINK_OWNER_OFFSET, // 65
QDSCR_TRIGGER_PARENT_LINK_CHILD_OFFSET,
QDSCR_TRIGGER_CHILD_LINK_OWNER_OFFSET,
QDSCR_TRIGGER_CHILD_LINK_CHILD_OFFSET,
QDSCR_TRIGGER_START_ELEMENT,
// Trigger Chain
QDSCR_TRIGGER_CHAIN, // 70
QDSCR_TRIGGER_CHAIN_ROOT,
QDSCR_TRIGGER_CHAIN_WORK_AREA,
QDSCR_TRIGGER_CHAIN_LAYOUT,
QDSCR_TRIGGER_BOUND,
// Sound
QDSCR_SOUND, // 75
QDSCR_SOUND_VOLUME,
// Music
QDSCR_MUSIC_TRACK,
QDSCR_MUSIC_TRACK_CYCLED,
// Video
QDSCR_VIDEO,
QDSCR_VIDEO_POSITION, // 80
QDSCR_VIDEO_BACKGROUND,
// Minigame
QDSCR_MINIGAME,
QDSCR_MINIGAME_DLL_NAME,
QDSCR_MINIGAME_GAME_NAME,
QDSCR_MINIGAME_CONFIG_FILE, // 85
QDSCR_MINIGAME_STATE,
QDSCR_MINIGAME_SCORE,
QDSCR_MINIGAME_CONFIG_PARAMETER,
// Animation
QDSCR_ANIMATION_FRAME,
QDSCR_ANIMATION_INFO, // 90
QDSCR_ANIMATION_FILE,
QDSCR_ANIMATION,
// AnimationSet
QDSCR_ANIMATION_SET,
QDSCR_ANIMATION_SET_START_ANGLE,
QDSCR_ANIMATION_SET_TURN, // 95
// Coords Animation
QDSCR_COORDS_ANIMATION_POINT,
QDSCR_COORDS_ANIMATION,
QDSCR_ANIMATION_PHASE,
// Game Object
QDSCR_PARALLAX_OFFSET,
// Static Object
QDSCR_STATIC_OBJECT, // 100
// Animated Object
QDSCR_ANIMATED_OBJECT,
QDSCR_OBJECT_STATE,
QDSCR_OBJECT_MOVEMENT_STATES,
QDSCR_OBJECT_MOVEMENT_STATE,
QDSCR_OBJECT_DIRECTION, // 105
QDSCR_OBJECT_DEFAULT_POS,
QDSCR_OBJECT_DEFAULT_DIRECTION,
QDSCR_OBJECT_STATE_STATIC,
QDSCR_OBJECT_STATE_WALK,
QDSCR_OBJECT_STATE_MASK, // 110
QDSCR_OBJECT_STATE_MASK_POS,
QDSCR_OBJECT_STATE_MASK_SIZE,
QDSCR_OBJECT_STATE_MASK_DATA,
QDSCR_OBJECT_STATE_MASK_PARENT,
QDSCR_OBJECT_STATE_MASK_CONTOUR, // 115
QDSCR_OBJECT_STATE_CENTER_OFFSET,
QDSCR_OBJECT_STATE_DELAY,
QDSCR_OBJECT_STATE_SOUND_DELAY,
QDSCR_OBJECT_STATE_TEXT_DELAY,
QDSCR_OBJECT_STATE_CURSOR_ID, // 120
QDSCR_OBJECT_STATE_ACCELERATION,
QDSCR_OBJECT_STATE_RND_MOVE,
QDSCR_OBJECT_STATE_WALK_SOUND_FREQUENCY,
QDSCR_STATE_CENTER_OFFSETS,
QDSCR_STATE_STATIC_CENTER_OFFSETS, // 125
QDSCR_STATE_START_CENTER_OFFSETS,
QDSCR_STATE_STOP_CENTER_OFFSETS,
// State conditions
QDSCR_CONDITION,
QDSCR_CONDITION_DATA_INT,
QDSCR_CONDITION_DATA_FLOAT, // 130
QDSCR_CONDITION_DATA_STRING,
QDSCR_CONDITION_INVERSE,
QDSCR_CONDITIONS_MODE,
QDSCR_CONDITION_GROUP,
QDSCR_CONDITION_OBJECT, // 135
// Counter
QDSCR_COUNTER,
QDSCR_COUNTER_ELEMENT,
QDSCR_COUNTER_INC_VALUE,
QDSCR_COUNTER_LIMIT,
QDSCR_COUNTER_DIGITS, // 140
QDSCR_COUNTER_NAME,
// Object Scale
QDSCR_OBJ_SCALE_INFO,
// Mouse object
QDSCR_MOUSE_OBJECT,
QDSCR_MOUSE_DEFAULT_CURSORS,
// Moving Object
QDSCR_MOVEMENT_ANIMATION_NUMBER, // 145
QDSCR_MOVEMENT_ANIMATIONS,
QDSCR_STATIC_ANIMATIONS,
QDSCR_MOVING_OBJECT,
QDSCR_COLLISION_RADIUS,
QDSCR_COLLISION_DELAY, // 150
QDSCR_COLLISION_PATH,
QDSCR_FOLLOW_MIN_RADIUS,
QDSCR_FOLLOW_MAX_RADIUS,
QDSCR_ATTACH_SHIFT,
QDSCR_PERSONAGE_CONTROL, // 155
QDSCR_PERSONAGE_MOVEMENT_TYPE,
QDSCR_ROTATION_ANGLE_PER_QUANT,
// Inventory
QDSCR_INVENTORY_CELL_TYPE,
QDSCR_INVENTORY_CELL_SET,
QDSCR_INVENTORY_CELL_SET_SIZE, // 160
QDSCR_INVENTORY_CELL_SET_ADDITIONAL_CELLS,
QDSCR_INVENTORY_CELL_SET_POS,
QDSCR_INVENTORY,
// Camera & grid
QDSCR_CAMERA,
QDSCR_CAMERA_GRID_SIZE, // 165
QDSCR_CAMERA_GRID_HEIGHT,
QDSCR_CAMERA_GRID_ATTRIBUTES,
QDSCR_CAMERA_GRID_CENTER,
QDSCR_CAMERA_CELL_SIZE,
QDSCR_CAMERA_FOCUS, // 170
QDSCR_CAMERA_ANGLES,
QDSCR_CAMERA_SCREEN_SIZE,
QDSCR_CAMERA_SCREEN_OFFSET,
QDSCR_CAMERA_SCREEN_CENTER,
QDSCR_CAMERA_MODE, // 175
QDSCR_CAMERA_SCROLLING_SPEED,
QDSCR_CAMERA_SCROLLING_DIST,
QDSCR_CAMERA_SMOOTH_SWITCH,
QDSCR_CAMERA_SCALE_POW,
QDSCR_CAMERA_SCALE_Z_OFFSET, // 180
// Game end
QDSCR_GAME_END,
QDSCR_GAME_END_SCREEN,
// Interface
QDSCR_INTERFACE,
QDSCR_INTERFACE_SCENE_REDRAW,
QDSCR_INTERFACE_MAIN_MENU, // 185
QDSCR_INTERFACE_INGAME_SCREEN0,
QDSCR_INTERFACE_INGAME_SCREEN1,
QDSCR_INTERFACE_HIGHSCORE_NAME_SCREEN,
QDSCR_INTERFACE_SAVE_PROMPT_SCREEN,
QDSCR_INTERFACE_SAVE_NAME_SCREEN, // 190
QDSCR_INTERFACE_NEED_SAVE_SCREENSHOT,
QDSCR_INTERFACE_NEED_SHOW_SAVE_NAME,
QDSCR_INTERFACE_NEED_SHOW_SAVE_TIME,
QDSCR_INTERFACE_SAVE_FONT_TYPE,
QDSCR_INTERFACE_SAVE_FONT_COLOR, // 195
QDSCR_INTERFACE_SAVE_IS_AUTOSAVE,
QDSCR_INTERFACE_SCREEN,
QDSCR_INTERFACE_SCREEN_HIDE_TIME,
QDSCR_INTERFACE_SCREEN_HIDE_OFFSET,
QDSCR_INTERFACE_ELEMENT, // 200
QDSCR_INTERFACE_ELEMENT_STATE,
QDSCR_INTERFACE_ELEMENT_STATE_MODE,
QDSCR_INTERFACE_ELEMENT_POS,
QDSCR_INTERFACE_OPTION_ID,
QDSCR_INTERFACE_EVENT, // 205
QDSCR_INTERFACE_EVENT_DATA,
QDSCR_INTERFACE_EVENT_BEFORE_ANIMATION,
QDSCR_INTERFACE_EVENT_ACTIVATION_TYPE,
QDSCR_INTERFACE_ACTION,
QDSCR_INTERFACE_ACTION_DATA, // 210
QDSCR_INTERFACE_ANIMATION_FLAGS,
QDSCR_INTERFACE_SLIDER_RECTANGLE,
QDSCR_INTERFACE_SLIDER_ORIENTATION,
QDSCR_INTERFACE_BACKGROUND_OFFSET,
QDSCR_INTERFACE_THUMBNAIL_SIZE, // 215
QDSCR_INTERFACE_TEXT_SHIFT,
QDSCR_TEXT_WINDOW_BORDER_CORNER,
QDSCR_TEXT_WINDOW_BORDER_LINE_H,
QDSCR_TEXT_WINDOW_BORDER_LINE_V,
QDSCR_TEXT_WINDOW_BORDER_BACK, // 220
QDSCR_TEXT_WINDOW_SLIDER,
QDSCR_TEXT_WINDOW_TYPE,
QDSCR_TEXT_WINDOW_MAX_STRING_LENGTH,
QDSCR_TEXT_WINDOW_INFO_TYPE,
QDSCR_TEXT_WINDOW_PLAYER_ID, // 225
// Scene
QDSCR_SCENE,
QDSCR_SCENE_SAVE_SLOT,
QDSCR_STARTUP_SCENE,
QDSCR_SCENE_RESTART_MINIGAME,
// Location
QDSCR_LOCATION, // 230
QDSCR_GAME_TITLE,
QDSCR_TEXT_DB,
QDSCR_CD_KEY,
// For qdScreenTextFormat
QDSCR_SCREEN_TEXT_FORMAT,
QDSCR_FONT_TYPE, // 235
QDSCR_DEFAULT_FONT,
QDSCR_GLOBAL_DEPEND,
QDSCR_INVERSE_DIRECTION,
QDSCR_ALPHA,
QDSCR_ENABLE_BACKGROUND, // 240
QDSCR_FADE_TIME,
QDSCR_HALL_OF_FAME_SIZE,
QDSCR_RESOURCE_COMPRESSION,
QDSCR_SCREEN_TRANSFORM,
QDSCR_MAX_KEYWORD_ID // 245
};
const int idTagVersionAll[490] = {
20021114, QDSCR_ROOT,
// Common
20021114, QDSCR_ID,
20021114, QDSCR_X,
20021114, QDSCR_Y,
20021114, QDSCR_SX, // 5
20021114, QDSCR_SY,
20021114, QDSCR_POS2D,
20021114, QDSCR_POS3D,
20021114, QDSCR_SRC_POS,
20021114, QDSCR_DEST_POS, // 10
20021114, QDSCR_FILE,
20021114, QDSCR_START_TIME,
20021114, QDSCR_PERIOD,
20021114, QDSCR_LENGTH,
20021114, QDSCR_SPEED, // 15
20030422, QDSCR_ANIMATION_SPEED,
20021114, QDSCR_INTERPOLATION_TIME,
20021114, QDSCR_SCALE,
20021114, QDSCR_NAME,
20021114, QDSCR_FLAG, // 20
20021114, QDSCR_RND,
20021114, QDSCR_MASK_SIZE,
20021114, QDSCR_MASK_ATTRIBUTES,
20021114, QDSCR_MASK_HEIGHTS,
20021114, QDSCR_BOUND, // 25
20021114, QDSCR_TYPE,
20021114, QDSCR_SIZE,
20021114, QDSCR_STATE,
20021114, QDSCR_TEXT,
20021114, QDSCR_SHORT_TEXT, // 30
20021202, QDSCR_VALUE,
20030125, QDSCR_TIME,
20030822, QDSCR_CD,
20030918, QDSCR_ALIGN,
20070503, QDSCR_VALIGN, // 35
20030918, QDSCR_ORIENTATION,
20031007, QDSCR_COLOR,
20040601, QDSCR_COMMENT,
20021114, QDSCR_SCREEN_SIZE,
20030918, QDSCR_TEXT_SET, // 40
// Text
20040123, QDSCR_TEXT_COLOR,
20040210, QDSCR_TEXT_HOVER_COLOR,
20040123, QDSCR_TEXT_ALIGN,
// Fonts
20040308, QDSCR_FONT_INFO,
// Contours
20021114, QDSCR_CONTOUR_RECTANGLE, // 45
20021114, QDSCR_CONTOUR_CIRCLE,
20021114, QDSCR_CONTOUR_POLYGON,
// Named Object Reference
20021114, QDSCR_NAMED_OBJECT,
20030430, QDSCR_NAMED_OBJECT_TYPES,
// Grid zone
20021114, QDSCR_GRID_ZONE, // 50
20021114, QDSCR_GRID_ZONE_CELLS,
20021114, QDSCR_GRID_ZONE_HEIGHT,
20021114, QDSCR_GRID_ZONE_CONTOUR,
20021216, QDSCR_GRID_ZONE_STATE,
20040315, QDSCR_GRID_ZONE_SHADOW_COLOR, // 55
20040315, QDSCR_GRID_ZONE_SHADOW_ALPHA,
// Trigger Element
20021114, QDSCR_TRIGGER_ELEMENT,
20021114, QDSCR_TRIGGER_ELEMENT_LINK,
20030429, QDSCR_TRIGGER_ELEMENT_PARENT_LINKS,
20030429, QDSCR_TRIGGER_ELEMENT_CHILD_LINKS, // 60
20030227, QDSCR_TRIGGER_ELEMENT_LINK_AUTO_RESTART,
20030429, QDSCR_TRIGGER_ELEMENT_LINK_OFFSETS,
20021114, QDSCR_TRIGGER_ELEMENT_TITLE,
20021114, QDSCR_TRIGGER_ELEMENT_CELL_NUMBER,
20021114, QDSCR_TRIGGER_PARENT_LINK_OWNER_OFFSET, // 65
20021114, QDSCR_TRIGGER_PARENT_LINK_CHILD_OFFSET,
20021114, QDSCR_TRIGGER_CHILD_LINK_OWNER_OFFSET,
20021114, QDSCR_TRIGGER_CHILD_LINK_CHILD_OFFSET,
20021204, QDSCR_TRIGGER_START_ELEMENT,
// Trigger Chain
20021114, QDSCR_TRIGGER_CHAIN, // 70
20021114, QDSCR_TRIGGER_CHAIN_ROOT,
20021114, QDSCR_TRIGGER_CHAIN_WORK_AREA,
20021114, QDSCR_TRIGGER_CHAIN_LAYOUT,
20021114, QDSCR_TRIGGER_BOUND,
// Sound
20021114, QDSCR_SOUND, // 75
20030512, QDSCR_SOUND_VOLUME,
// Music
20021213, QDSCR_MUSIC_TRACK,
20021213, QDSCR_MUSIC_TRACK_CYCLED,
// Video
20021114, QDSCR_VIDEO,
20021114, QDSCR_VIDEO_POSITION, // 80
20021114, QDSCR_VIDEO_BACKGROUND,
// Minigame
20021114, QDSCR_MINIGAME,
20021114, QDSCR_MINIGAME_DLL_NAME,
20040601, QDSCR_MINIGAME_GAME_NAME,
20021114, QDSCR_MINIGAME_CONFIG_FILE, // 85
20021114, QDSCR_MINIGAME_STATE,
20021114, QDSCR_MINIGAME_SCORE,
20040601, QDSCR_MINIGAME_CONFIG_PARAMETER,
// Animation
20021114, QDSCR_ANIMATION_FRAME,
20021114, QDSCR_ANIMATION_INFO, // 90
20021114, QDSCR_ANIMATION_FILE,
20021114, QDSCR_ANIMATION,
// AnimationSet
20021114, QDSCR_ANIMATION_SET,
20030716, QDSCR_ANIMATION_SET_START_ANGLE,
20060414, QDSCR_ANIMATION_SET_TURN, // 95
// Coords Animation
20021114, QDSCR_COORDS_ANIMATION_POINT,
20021114, QDSCR_COORDS_ANIMATION,
20021114, QDSCR_ANIMATION_PHASE,
// Game Object
20021114, QDSCR_PARALLAX_OFFSET,
// Static Object
20021114, QDSCR_STATIC_OBJECT, // 100
// Animated Object
20021114, QDSCR_ANIMATED_OBJECT,
20021114, QDSCR_OBJECT_STATE,
20021114, QDSCR_OBJECT_MOVEMENT_STATES,
20021114, QDSCR_OBJECT_MOVEMENT_STATE,
20021114, QDSCR_OBJECT_DIRECTION, // 105
20021114, QDSCR_OBJECT_DEFAULT_POS,
20021114, QDSCR_OBJECT_DEFAULT_DIRECTION,
20021114, QDSCR_OBJECT_STATE_STATIC,
20021114, QDSCR_OBJECT_STATE_WALK,
20021114, QDSCR_OBJECT_STATE_MASK, // 110
20021114, QDSCR_OBJECT_STATE_MASK_POS,
20021114, QDSCR_OBJECT_STATE_MASK_SIZE,
20021114, QDSCR_OBJECT_STATE_MASK_DATA,
20021114, QDSCR_OBJECT_STATE_MASK_PARENT,
20021114, QDSCR_OBJECT_STATE_MASK_CONTOUR, // 115
20021114, QDSCR_OBJECT_STATE_CENTER_OFFSET,
20021114, QDSCR_OBJECT_STATE_DELAY,
20030723, QDSCR_OBJECT_STATE_SOUND_DELAY,
20040123, QDSCR_OBJECT_STATE_TEXT_DELAY,
20030131, QDSCR_OBJECT_STATE_CURSOR_ID, // 120
20030716, QDSCR_OBJECT_STATE_ACCELERATION,
20031206, QDSCR_OBJECT_STATE_RND_MOVE,
20040519, QDSCR_OBJECT_STATE_WALK_SOUND_FREQUENCY,
20030416, QDSCR_STATE_CENTER_OFFSETS,
20030416, QDSCR_STATE_STATIC_CENTER_OFFSETS, // 125
20060623, QDSCR_STATE_START_CENTER_OFFSETS,
20060623, QDSCR_STATE_STOP_CENTER_OFFSETS,
// State conditions
20021114, QDSCR_CONDITION,
20021114, QDSCR_CONDITION_DATA_INT,
20021114, QDSCR_CONDITION_DATA_FLOAT, // 130
20021114, QDSCR_CONDITION_DATA_STRING,
20030203, QDSCR_CONDITION_INVERSE,
20021114, QDSCR_CONDITIONS_MODE,
20030219, QDSCR_CONDITION_GROUP,
20030226, QDSCR_CONDITION_OBJECT, // 135
// Counter
20030530, QDSCR_COUNTER,
20030530, QDSCR_COUNTER_ELEMENT,
20030530, QDSCR_COUNTER_INC_VALUE,
20030530, QDSCR_COUNTER_LIMIT,
20060420, QDSCR_COUNTER_DIGITS, // 140
20060423, QDSCR_COUNTER_NAME,
// Object Scale
20021114, QDSCR_OBJ_SCALE_INFO,
// Mouse object
20021114, QDSCR_MOUSE_OBJECT,
20030131, QDSCR_MOUSE_DEFAULT_CURSORS,
// Moving Object
20021114, QDSCR_MOVEMENT_ANIMATION_NUMBER, // 145
20021114, QDSCR_MOVEMENT_ANIMATIONS,
20021114, QDSCR_STATIC_ANIMATIONS,
20021114, QDSCR_MOVING_OBJECT,
20030704, QDSCR_COLLISION_RADIUS,
20030704, QDSCR_COLLISION_DELAY, // 150
20030704, QDSCR_COLLISION_PATH,
20040406, QDSCR_FOLLOW_MIN_RADIUS,
20040406, QDSCR_FOLLOW_MAX_RADIUS,
20040428, QDSCR_ATTACH_SHIFT,
20030704, QDSCR_PERSONAGE_CONTROL, // 155
20030716, QDSCR_PERSONAGE_MOVEMENT_TYPE,
20041201, QDSCR_ROTATION_ANGLE_PER_QUANT,
// Inventory
20021114, QDSCR_INVENTORY_CELL_TYPE,
20021114, QDSCR_INVENTORY_CELL_SET,
20021114, QDSCR_INVENTORY_CELL_SET_SIZE, // 160
20050101, QDSCR_INVENTORY_CELL_SET_ADDITIONAL_CELLS,
20021114, QDSCR_INVENTORY_CELL_SET_POS,
20021114, QDSCR_INVENTORY,
// Camera & grid
20021114, QDSCR_CAMERA,
20021114, QDSCR_CAMERA_GRID_SIZE, // 165
20021114, QDSCR_CAMERA_GRID_HEIGHT,
20021114, QDSCR_CAMERA_GRID_ATTRIBUTES,
20021114, QDSCR_CAMERA_GRID_CENTER,
20021114, QDSCR_CAMERA_CELL_SIZE,
20021114, QDSCR_CAMERA_FOCUS, // 170
20021114, QDSCR_CAMERA_ANGLES,
20021114, QDSCR_CAMERA_SCREEN_SIZE,
20021114, QDSCR_CAMERA_SCREEN_OFFSET,
20021114, QDSCR_CAMERA_SCREEN_CENTER,
20030125, QDSCR_CAMERA_MODE, // 175
20030125, QDSCR_CAMERA_SCROLLING_SPEED,
20030125, QDSCR_CAMERA_SCROLLING_DIST,
20030530, QDSCR_CAMERA_SMOOTH_SWITCH,
20040406, QDSCR_CAMERA_SCALE_POW,
20040406, QDSCR_CAMERA_SCALE_Z_OFFSET, // 180
// Game end
20030508, QDSCR_GAME_END,
20030508, QDSCR_GAME_END_SCREEN,
// Interface
20030109, QDSCR_INTERFACE,
20040506, QDSCR_INTERFACE_SCENE_REDRAW,
20030110, QDSCR_INTERFACE_MAIN_MENU, // 185
20030317, QDSCR_INTERFACE_INGAME_SCREEN0,
20030317, QDSCR_INTERFACE_INGAME_SCREEN1,
20070329, QDSCR_INTERFACE_HIGHSCORE_NAME_SCREEN,
20060129, QDSCR_INTERFACE_SAVE_PROMPT_SCREEN,
20070329, QDSCR_INTERFACE_SAVE_NAME_SCREEN, // 190
20060129, QDSCR_INTERFACE_NEED_SAVE_SCREENSHOT,
20070329, QDSCR_INTERFACE_NEED_SHOW_SAVE_NAME,
20060129, QDSCR_INTERFACE_NEED_SHOW_SAVE_TIME,
20060129, QDSCR_INTERFACE_SAVE_FONT_TYPE,
20060129, QDSCR_INTERFACE_SAVE_FONT_COLOR, // 195
20070315, QDSCR_INTERFACE_SAVE_IS_AUTOSAVE,
20030109, QDSCR_INTERFACE_SCREEN,
20030609, QDSCR_INTERFACE_SCREEN_HIDE_TIME,
20030609, QDSCR_INTERFACE_SCREEN_HIDE_OFFSET,
20030109, QDSCR_INTERFACE_ELEMENT, // 200
20021128, QDSCR_INTERFACE_ELEMENT_STATE,
20030121, QDSCR_INTERFACE_ELEMENT_STATE_MODE,
20030109, QDSCR_INTERFACE_ELEMENT_POS,
20030414, QDSCR_INTERFACE_OPTION_ID,
20030121, QDSCR_INTERFACE_EVENT, // 205
20030121, QDSCR_INTERFACE_EVENT_DATA,
20030121, QDSCR_INTERFACE_EVENT_BEFORE_ANIMATION,
20061128, QDSCR_INTERFACE_EVENT_ACTIVATION_TYPE,
20021128, QDSCR_INTERFACE_ACTION,
20021128, QDSCR_INTERFACE_ACTION_DATA, // 210
20030116, QDSCR_INTERFACE_ANIMATION_FLAGS,
20030203, QDSCR_INTERFACE_SLIDER_RECTANGLE,
20030203, QDSCR_INTERFACE_SLIDER_ORIENTATION,
20070115, QDSCR_INTERFACE_BACKGROUND_OFFSET,
20030226, QDSCR_INTERFACE_THUMBNAIL_SIZE, // 215
20060129, QDSCR_INTERFACE_TEXT_SHIFT,
20040123, QDSCR_TEXT_WINDOW_BORDER_CORNER,
20040123, QDSCR_TEXT_WINDOW_BORDER_LINE_H,
20040123, QDSCR_TEXT_WINDOW_BORDER_LINE_V,
20040123, QDSCR_TEXT_WINDOW_BORDER_BACK, // 220
20040123, QDSCR_TEXT_WINDOW_SLIDER,
20070321, QDSCR_TEXT_WINDOW_TYPE,
20070329, QDSCR_TEXT_WINDOW_MAX_STRING_LENGTH,
20070404, QDSCR_TEXT_WINDOW_INFO_TYPE,
20070404, QDSCR_TEXT_WINDOW_PLAYER_ID, // 225
// Scene
20021114, QDSCR_SCENE,
20030613, QDSCR_SCENE_SAVE_SLOT,
20030226, QDSCR_STARTUP_SCENE,
20060630, QDSCR_SCENE_RESTART_MINIGAME,
// Location
20021114, QDSCR_LOCATION, // 230
20030919, QDSCR_GAME_TITLE,
20031014, QDSCR_TEXT_DB,
20031014, QDSCR_CD_KEY,
// For qdScreenTextFormat
20040308, QDSCR_SCREEN_TEXT_FORMAT,
20040308, QDSCR_FONT_TYPE, // 235
20040517, QDSCR_DEFAULT_FONT,
20050101, QDSCR_GLOBAL_DEPEND,
20060129, QDSCR_INVERSE_DIRECTION,
20060129, QDSCR_ALPHA,
20060129, QDSCR_ENABLE_BACKGROUND, // 240
20060129, QDSCR_FADE_TIME,
20070404, QDSCR_HALL_OF_FAME_SIZE,
20060626, QDSCR_RESOURCE_COMPRESSION,
20060715, QDSCR_SCREEN_TRANSFORM,
20021114, QDSCR_MAX_KEYWORD_ID // 245
};
void cleanup_XML_Parser();
xml::parser &qdscr_XML_Parser();
const char *qdscr_XML_string(const char *p);
const char *qdscr_XML_string(const Common::String &s);
} // namespace QDEngine
#endif // QDENGINE_PARSER_QDSCR_PARSER_H

View 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 QDENGINE_PARSER_XML_FWD_H
#define QDENGINE_PARSER_XML_FWD_H
namespace QDEngine {
// forward declarations
namespace xml {
class tag;
class tag_buffer;
class parser;
} /* namespace xml */
} // namespace QDEngine
#endif // QDENGINE_PARSER_XML_FWD_H

View File

@@ -0,0 +1,115 @@
/* 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/file.h"
#include "common/textconsole.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_parser.h"
namespace QDEngine {
namespace xml {
parser::parser() : _cur_level(0), _skip_mode(false), _binary_script(false) {
_root_tag.set_data(&_data_pool);
}
parser::~parser() {
}
void parser::clear() {
_root_tag.clear();
while (!_tag_stack.empty()) _tag_stack.pop();
_cur_level = 0;
_skip_mode = false;
_data_pool.clear();
Std::vector<char>(_data_pool).swap(_data_pool);
}
bool parser::parse_file(const char *fname) {
if (is_script_binary(fname))
return read_binary_script(fname);
return false;
}
bool tag::readTag(Common::SeekableReadStream *ff, tag &tg) {
uint32 id = ff->readUint32LE();
uint32 data_format = ff->readUint32LE();
uint32 data_size = ff->readUint32LE();
uint32 data_offset = ff->readUint32LE();
tg = tag(tag(id, tag::tag_data_format(data_format), data_size, data_offset));
uint32 num_subtags = ff->readUint32LE();
for (uint32 i = 0; i < num_subtags; i++) {
tag stg;
readTag(ff, stg);
tg.add_subtag(stg);
}
return true;
}
bool parser::read_binary_script(const char *fname) {
Common::File ff;
ff.open(fname);
_binary_script = true;
/* uint32 v = */ff.readUint32LE();
uint32 size = ff.readUint32LE();
if (_data_pool.size() < size)
_data_pool.resize(size);
ff.read(&*_data_pool.begin(), size);
_root_tag.clear();
_root_tag.readTag(&ff, _root_tag);
_root_tag.set_data(&_data_pool);
ff.close();
return true;
}
bool parser::is_script_binary(const char *fname) const {
Common::File ff;
ff.open(fname);
uint32 v = ff.readUint32LE();
if (v == 8383) return true;
return false;
}
} /* namespace xml */
} // namespace QDEngine

View File

@@ -0,0 +1,100 @@
/* 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 QDENGINE_PARSER_XML_PARSER_H
#define QDENGINE_PARSER_XML_PARSER_H
#include "common/system.h"
#include "common/hashmap.h"
#include "common/stack.h"
#include "qdengine/parser/xml_tag_buffer.h"
namespace QDEngine {
namespace xml {
class parser {
public:
typedef Common::HashMap<Common::String, tag> tag_format_t;
typedef Common::Stack<tag *> tag_stack_t;
parser();
virtual ~parser();
bool parse_file(const char *fname);
bool read_binary_script(const char *fname);
bool is_script_binary(const char *fname) const;
bool is_script_binary() const {
return _binary_script;
}
const tag &root_tag() const {
return _root_tag;
}
void clear();
void resize_data_pool(uint32 pool_sz) {
_data_pool.resize(pool_sz);
}
bool register_tag_format(const char *tag_name, const tag &tg) {
tag_format_t::iterator it = _tag_format.find(tag_name);
if (it != _tag_format.end())
return false;
_tag_format[tag_name] = tg;
return true;
}
const tag *get_tag_format(const char *tag_name) const {
tag_format_t::const_iterator it = _tag_format.find(tag_name);
if (it != _tag_format.end())
return &it->_value;
return NULL;
}
int num_tag_formats() const {
return _tag_format.size();
}
private:
tag _root_tag;
Std::vector<char> _data_pool;
Common::String _data_buffer;
bool _binary_script;
tag_stack_t _tag_stack;
tag_format_t _tag_format;
int _cur_level;
bool _skip_mode;
};
} /* namespace xml */
} // namespace QDEngine
#endif // QDENGINE_PARSER_XML_PARSER_H

View File

@@ -0,0 +1,200 @@
/* 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 QDENGINE_PARSER_XML_TAG_H
#define QDENGINE_PARSER_XML_TAG_H
#include "qdengine/qdengine.h"
namespace QDEngine {
//! Парсер XML на базе expat.
namespace xml {
//! XML тег.
class tag {
public:
typedef Std::list<tag> subtags_t;
typedef subtags_t::const_iterator subtag_iterator;
//! Формат данных тега.
enum tag_data_format {
//! данные отсутствуют
TAG_DATA_VOID,
//! данные типа int16 int
TAG_DATA_SHORT,
//! данные типа uint16 int
TAG_DATA_UNSIGNED_SHORT,
//! данные типа int
TAG_DATA_INT,
//! данные типа uint32
TAG_DATA_UNSIGNED_INT,
//! данные типа float
TAG_DATA_FLOAT,
//! строковые данные
TAG_DATA_STRING
};
tag(int id = 0, tag_data_format data_fmt = TAG_DATA_VOID, int data_sz = 0, int data_offs = 0) : _ID(id), _data_format(data_fmt), _data_size(data_sz), _data_offset(data_offs), _data(NULL) { }
tag(const tag &tg) : _ID(tg._ID), _data_format(tg._data_format), _data_size(tg._data_size), _data_offset(tg._data_offset), _data(tg._data), _subtags(tg._subtags) { }
~tag() { }
bool readTag(Common::SeekableReadStream *ff, tag &tg);
tag &operator = (const tag &tg) {
if (this == &tg) return *this;
_ID = tg._ID;
_data_format = tg._data_format;
_data_size = tg._data_size;
_data_offset = tg._data_offset;
_subtags = tg._subtags;
return *this;
}
//! Возвращает идентификатор тега.
int ID() const {
return g_engine->_tagMap[_ID - 1];
}
int origID() const {
return _ID;
}
//! Возвращает формат данных тега.
tag_data_format data_format() const {
return _data_format;
}
//! Возвращает количество элеметов данных тега.
/**
Чтобы получить размер данных в байтах, надо это число
умножить на размер элемента данных в байтах - data_elemet_size().
*/
int data_size() const {
return _data_size;
}
//! Возвращает размер элемента данных тега в байтах.
int data_element_size() const {
switch (_data_format) {
case TAG_DATA_VOID:
return 0;
case TAG_DATA_SHORT:
case TAG_DATA_UNSIGNED_SHORT:
return sizeof(uint16);
case TAG_DATA_INT:
return sizeof(int32);
case TAG_DATA_UNSIGNED_INT:
return sizeof(uint32);
case TAG_DATA_FLOAT:
return sizeof(float);
case TAG_DATA_STRING:
return sizeof(byte);
}
return 0;
}
//! Устанавливает количество элементов данных тега.
void set_data_size(int sz) {
_data_size = sz;
}
//! Возвращает смещение до данных тега в данных парсера.
int data_offset() const {
return _data_offset;
}
//! Устанавливает смещение до данных тега в данных парсера.
void set_data_offset(int off) {
_data_offset = off;
}
//! Возвращает указатель на данные тега.
const char *data() const {
return &*(_data->begin() + _data_offset);
}
//! Устанавливает указатель на общие данные.
void set_data(const Std::vector<char> *p) {
_data = p;
for (subtags_t::iterator it = _subtags.begin(); it != _subtags.end(); ++it)
it->set_data(p);
}
//! Очистка вложенных тегов.
void clear() {
_subtags.clear();
}
//! Добавляет вложенный тег.
/**
Возвращает ссылку на последний вложенный тег.
*/
tag &add_subtag(const tag &tg) {
_subtags.push_back(tg);
return _subtags.back();
}
//! Возвращает true, если список вложенных тегов не пустой .
bool has_subtags() const {
return !_subtags.empty();
}
//! Возвращает количество вложенных тэгов.
int num_subtags() const {
return _subtags.size();
}
//! Возвращает итератор начала списка вложенных тегов.
subtag_iterator subtags_begin() const {
return _subtags.begin();
}
//! Возвращает итератор конца списка вложенных тегов.
subtag_iterator subtags_end() const {
return _subtags.end();
}
//! Поиск вложенного тега по его идентификатору.
const tag *search_subtag(int subtag_id) const {
for (subtag_iterator it = subtags_begin(); it != subtags_end(); ++it)
if (it->ID() == subtag_id) return &*it;
return NULL;
}
private:
//! Идентификатор (тип) тега.
int _ID;
//! Формат данных тега.
tag_data_format _data_format;
//! Количество элементов данных тега.
int _data_size;
//! Смещение до данных тега в общих данных.
int _data_offset;
//! Указатель на данные.
const Std::vector<char> *_data;
//! Список вложенных тегов.
subtags_t _subtags;
};
} /* namespace xml */
} // namespace QDEngine
#endif // QDENGINE_PARSER_XML_TAG_H

View File

@@ -0,0 +1,112 @@
/* 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 "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_tag_buffer.h"
namespace QDEngine {
namespace xml {
tag_buffer::tag_buffer(const tag &tg) : _data_size(tg.data_size() * tg.data_element_size()),
_data_offset(0),
#ifdef _DEBUG
data_format_(tg.data_format()),
#endif
_data(tg.data()) {
}
tag_buffer::tag_buffer(const char *dp, int len) : _data_size(len),
_data_offset(0),
#ifdef _DEBUG
data_format_(tag::TAG_DATA_VOID),
#endif
_data(dp) {
}
tag_buffer::tag_buffer(const tag_buffer &tb) : _data_size(tb._data_size),
_data_offset(tb._data_offset),
#ifdef _DEBUG
data_format_(tb.data_format_),
#endif
_data(tb._data) {
}
tag_buffer &tag_buffer::operator = (const tag_buffer &tb) {
if (this == &tb) return *this;
_data_size = tb._data_size;
_data_offset = tb._data_offset;
#ifdef _DEBUG
data_format_ = tb.data_format_;
#endif
_data = tb._data;
return *this;
}
tag_buffer::~tag_buffer() {
}
tag_buffer &tag_buffer::operator >= (int16 &var) {
char *p;
var = (short)strtol(_data + _data_offset, &p, 0);
_data_offset += p - (_data + _data_offset);
return *this;
}
tag_buffer &tag_buffer::operator >= (uint16 &var) {
char *p;
var = (uint16)strtoul(_data + _data_offset, &p, 0);
_data_offset += p - (_data + _data_offset);
return *this;
}
tag_buffer &tag_buffer::operator >= (int &var) {
char *p;
var = (int)strtol(_data + _data_offset, &p, 0);
_data_offset += p - (_data + _data_offset);
return *this;
}
tag_buffer &tag_buffer::operator >= (uint32 &var) {
char *p;
var = (uint32)strtoul(_data + _data_offset, &p, 0);
_data_offset += p - (_data + _data_offset);
return *this;
}
tag_buffer &tag_buffer::operator >= (float &var) {
char *p;
var = (float)strtod(_data + _data_offset, &p);
_data_offset += p - (_data + _data_offset);
return *this;
}
} /* namespace xml */
} // namespace QDEngine

View File

@@ -0,0 +1,142 @@
/* 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 QDENGINE_PARSER_XML_TAG_BUFFER_H
#define QDENGINE_PARSER_XML_TAG_BUFFER_H
#include "common/endian.h"
#include "qdengine/parser/xml_tag.h"
#ifdef _DEBUG
#define XML_ASSERT(a) assert(a)
#else
#define XML_ASSERT(a)
#endif
namespace QDEngine {
namespace xml {
class tag_buffer {
public:
tag_buffer(const tag &tg);
tag_buffer(const char *dp, int len);
tag_buffer(const tag_buffer &tb);
~tag_buffer();
tag_buffer &operator = (const tag_buffer &tb);
tag_buffer &operator >= (int16 &var);
tag_buffer &operator >= (uint16 &var);
tag_buffer &operator >= (int &var);
tag_buffer &operator >= (uint32 &var);
tag_buffer &operator >= (float &var);
tag_buffer &operator > (int16 &var) {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_SHORT);
var = (int16)READ_LE_UINT16(_data + _data_offset);
_data_offset += sizeof(int16);
return *this;
}
tag_buffer &operator > (uint16 &var) {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_UNSIGNED_SHORT);
var = READ_LE_UINT16(_data + _data_offset);
_data_offset += sizeof(uint16);
return *this;
}
tag_buffer &operator > (int &var) {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_INT);
var = (int32)READ_LE_UINT32(_data + _data_offset);
_data_offset += sizeof(int32);
return *this;
}
tag_buffer &operator > (uint32 &var) {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_UNSIGNED_INT);
var = READ_LE_UINT32(_data + _data_offset);
_data_offset += sizeof(uint32);
return *this;
}
tag_buffer &operator > (float &var) {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_FLOAT);
var = READ_LE_FLOAT32(_data + _data_offset);
_data_offset += 4;
return *this;
}
int16 get_short() {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_SHORT);
int16 v;
*this > v;
return v;
}
uint16 get_ushort() {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_UNSIGNED_SHORT);
uint16 v;
*this > v;
return v;
}
int get_int() {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_INT);
int v;
*this > v;
return v;
}
uint32 get_uint() {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_UNSIGNED_INT);
uint32 v;
*this > v;
return v;
}
float get_float() {
XML_ASSERT(data_format_ == tag::TAG_DATA_VOID || data_format_ == tag::TAG_DATA_FLOAT);
float v;
*this > v;
return v;
}
bool end_of_storage() const {
return _data_size > _data_offset;
}
void reset() {
_data_offset = 0;
}
private:
int _data_size;
int _data_offset;
#ifdef _DEBUG
tag::tag_data_format data_format_;
#endif
const char *_data;
};
} /* namespace xml */
} // namespace QDEngine
#endif // QDENGINE_PARSER_XML_TAG_BUFFER_H

101
engines/qdengine/qd_fwd.h Normal file
View File

@@ -0,0 +1,101 @@
/* 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 QDENGINE_QD_FWD_H
#define QDENGINE_QD_FWD_H
#include "common/str.h"
#include "common/std/list.h"
#include "common/std/vector.h"
namespace Common {
class SeekableReadStream;
}
namespace QDEngine {
class qdGameScene;
typedef Std::list<qdGameScene *> qdGameSceneList;
class qdGameEnd;
typedef Std::list<qdGameEnd *> qdGameEndList;
class qdVideo;
typedef Std::list<qdVideo *> qdVideoList;
class qdTriggerChain;
typedef Std::list<qdTriggerChain *> qdTriggerChainList;
class qdGameObject;
typedef Std::list<qdGameObject *> qdGameObjectList;
class qdMiniGame;
typedef Std::list<qdMiniGame *> qdMiniGameList;
class qdCounter;
typedef Std::list<qdCounter *> qdCounterList;
class qdGridZone;
typedef Std::list<qdGridZone *> qdGridZoneList;
class qdMusicTrack;
typedef Std::list<qdMusicTrack *> qdMusicTrackList;
class qdCondition;
typedef Std::list<qdCondition *> qdConditionList;
class qdSound;
typedef Std::list<qdSound *> qdSoundList;
class qdAnimation;
typedef Std::list<qdAnimation *> qdAnimationList;
class qdAnimationSet;
typedef Std::list<qdAnimationSet *> qdAnimationSetList;
class qdInventory;
typedef Std::list<qdInventory *> qdInventoryList;
class qdTriggerChain;
typedef Std::list<qdTriggerChain *> qdTriggerChainList;
class qdGameObjectState;
class qdGameObjectStateStatic;
class qdGameObjectStateWalk;
class qdGameObjectStateMask;
typedef Std::vector<qdGameObjectState *> qdGameObjectStateVector;
class qdGameObjectMouse;
class qdGameObjectMoving;
class qdNamedObject;
class qdNamedObjectReference;
class qdScaleInfo;
class qdInterfaceButton;
class qdGameDispatcher;
class qdFontInfo;
typedef Std::list<qdFontInfo *> qdFontInfoList;
} // namespace QDEngine
#endif // QDENGINE_QD_FWD_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,318 @@
/* 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 QDENGINE_QDCORE_QD_ANIMATION_H
#define QDENGINE_QDCORE_QD_ANIMATION_H
#include "qdengine/parser/xml_fwd.h"
#include "qdengine/system/graphics/gr_screen_region.h"
#include "qdengine/system/graphics/gr_tile_animation.h"
#include "qdengine/qdcore/qd_resource.h"
#include "qdengine/qdcore/qd_animation_frame.h"
#include "qdengine/qdcore/qd_named_object.h"
namespace QDEngine {
class qdAnimationInfo;
const int QD_ANIMATION_FLAG_REFERENCE = 0x01;
const int QD_ANIMATION_FLAG_LOOP = 0x04;
const int QD_ANIMATION_FLAG_FLIP_HORIZONTAL = 0x08;
const int QD_ANIMATION_FLAG_FLIP_VERTICAL = 0x10;
const int QD_ANIMATION_FLAG_BLACK_FON = 0x20;
const int QD_ANIMATION_FLAG_SUPPRESS_ALPHA = 0x40;
const int QD_ANIMATION_FLAG_CROP = 0x80;
const int QD_ANIMATION_FLAG_COMPRESS = 0x100;
const int QD_ANIMATION_FLAG_TILE_COMPRESS = 0x200;
enum qdAnimationStatus {
QD_ANIMATION_STOPPED = 0,
QD_ANIMATION_PLAYING,
QD_ANIMATION_PAUSED,
QD_ANIMATION_END_PLAYING
};
//! Анимация.
class qdAnimation : public qdNamedObject, public qdResource {
public:
qdAnimation();
qdAnimation(const qdAnimation &anm);
~qdAnimation();
qdAnimation &operator = (const qdAnimation &anm);
int named_object_type() const {
return QD_NAMED_OBJECT_ANIMATION;
}
const qdAnimationFrame *get_cur_frame() const;
const qdAnimationFrame *get_cur_frame(float &scale) const;
qdAnimationFrame *get_cur_frame();
void set_cur_frame(int number);
int get_cur_frame_number() const;
qdAnimationFrame *get_frame(int number);
const qdAnimationFrame *get_scaled_frame(int number, int scale_index) const;
int num_frames() const {
return _num_frames;
}
float length() const {
return _length;
}
float cur_time() const {
return _cur_time;
}
void set_time(float tm) {
_cur_time = tm;
}
float cur_time_rel() const {
if (_length > 0.01f)
return _cur_time / _length;
return 0.0f;
}
void set_time_rel(float tm) {
if (tm < 0.0f) tm = 0.0f;
if (tm > 0.99f) tm = 0.99f;
_cur_time = _length * tm;
}
void advance_time(float tm);
void init_size();
int size_x() const {
return _sx;
}
int size_y() const {
return _sy;
}
int picture_size_x() const;
int picture_size_y() const;
bool is_playing() const {
return (_status == QD_ANIMATION_PLAYING ||
_status == QD_ANIMATION_END_PLAYING);
}
int status() const {
return _status;
}
bool is_finished() const {
return _is_finished;
}
bool need_stop() const {
return _status == QD_ANIMATION_END_PLAYING;
}
void start() {
_status = QD_ANIMATION_PLAYING;
_is_finished = false;
_cur_time = 0.0f;
}
void stop() {
_status = QD_ANIMATION_STOPPED;
_is_finished = true;
}
void pause() {
_status = QD_ANIMATION_PAUSED;
}
void resume() {
_status = QD_ANIMATION_PLAYING;
}
void quant(float dt);
void redraw(int x, int y, int z, int mode = 0) const;
void redraw(int x, int y, int z, float scale, int mode = 0) const;
void redraw_rot(int x, int y, int z, float angle, int mode = 0) const;
void redraw_rot(int x, int y, int z, float angle, const Vect2f &scale, int mode = 0) const;
void draw_mask(int x, int y, int z, uint32 mask_color, int mask_alpha, int mode = 0) const;
void draw_mask(int x, int y, int z, uint32 mask_color, int mask_alpha, float scale, int mode = 0) const;
void draw_mask_rot(int x, int y, int z, float angle, uint32 mask_color, int mask_alpha, int mode = 0) const;
void draw_mask_rot(int x, int y, int z, float angle, uint32 mask_color, int mask_alpha, const Vect2f &scale, int mode = 0) const;
void draw_contour(int x, int y, uint32 color) const;
void draw_contour(int x, int y, uint32 color, float scale) const;
bool hit(int x, int y) const;
bool hit(int x, int y, float scale) const;
bool add_frame(qdAnimationFrame *p, qdAnimationFrame *insert_pos = 0, bool insert_after = true);
bool remove_frame(int number);
bool remove_frame_range(int number0, int number1);
bool reverse_frame_range(int number0, int number1);
void load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
const Common::Path qda_file() const {
return _qda_file;
}
void qda_set_file(const Common::Path &fname);
bool qda_load(const Common::Path &fname);
bool load_resources();
void free_resources();
bool scale(float coeff_x, float coeff_y);
bool crop();
bool undo_crop();
Vect2i remove_edges();
bool compress();
bool uncompress();
bool tileCompress(grTileCompressionMethod method = TILE_UNCOMPRESSED, int tolerance = 0);
qdAnimationFrameList &frames_list() {
return _frames;
};
void create_reference(qdAnimation *p, const qdAnimationInfo *inf = NULL) const;
bool is_reference(const qdAnimation *p) const {
if (p->check_flag(QD_ANIMATION_FLAG_REFERENCE) && p->_parent == this) return true;
return false;
}
void clear() {
stop();
_frames_ptr = &_frames;
_parent = NULL;
}
bool is_empty() const {
return (_frames_ptr->empty());
}
//! Возвращает область экрана, занимаемую анимацией.
/**
Координаты области - смещение от центра анимации.
В mode задаются повороты анимации по горизонтали и вертикали
(QD_ANIMATION_FLAG_FLIP_HORIZONTAL, QD_ANIMATION_FLAG_FLIP_VERTICAL)
*/
grScreenRegion screen_region(int mode = 0, float scale = 1.0f) const;
const qdAnimation *parent() const {
return _parent;
}
// qdResource
bool load_resource();
bool free_resource();
//! Устанавливает имя файла, в котором хранятся данные ресурса.
void set_resource_file(const Common::Path &file_name) {
qda_set_file(file_name);
}
//! Возвращает имя файла, в котором хранится анимация.
const Common::Path resource_file() const {
if (qda_file().empty()) {
if (!check_flag(QD_ANIMATION_FLAG_REFERENCE) && !_frames.empty()) {
if (_frames.front()->has_file())
return _frames.front()->file();
else
return NULL;
} else
return NULL;
} else
return qda_file();
}
#ifdef __QD_DEBUG_ENABLE__
uint32 resource_data_size() const;
#endif
//! Загрузка данных из сэйва.
bool load_data(Common::SeekableReadStream &fh, int save_version);
//! Запись данных в сэйв.
bool save_data(Common::WriteStream &fh) const;
bool add_scale(float value);
bool create_scaled_frames();
const Std::vector<float> &scales() const {
if (check_flag(QD_ANIMATION_FLAG_REFERENCE) && _parent) return _parent->_scales;
else return _scales;
}
void clear_scales() {
_scales.clear();
}
const grTileAnimation *tileAnimation() const {
if (check_flag(QD_ANIMATION_FLAG_REFERENCE) && _parent)
return _parent->_tileAnimation;
else
return _tileAnimation;
}
static Common::String flag2str(int fl, bool truncate = false, bool icon = false);
static Common::String status2str(int fl, bool truncate = false);
private:
int _sx;
int _sy;
enum {
qda_version = 104
};
float _length;
float _cur_time;
float _playback_speed;
int _num_frames;
const qdAnimationFrameList *_frames_ptr;
qdAnimationFrameList _frames;
const qdAnimationFrameList *_scaled_frames_ptr;
qdAnimationFrameList _scaled_frames;
Std::vector<float> _scales;
grTileAnimation *_tileAnimation;
int _status;
bool _is_finished;
Common::Path _qda_file;
const qdAnimation *_parent;
int get_scale_index(float &scale_value) const;
bool copy_frames(const qdAnimation &anm);
void clear_frames();
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_ANIMATION_H

View 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/>.
*
*/
#include "common/file.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_animation_frame.h"
namespace QDEngine {
qdAnimationFrame::qdAnimationFrame() : _start_time(0.0f),
_length(0.0f) {
}
qdAnimationFrame::qdAnimationFrame(const qdAnimationFrame &frm) : qdSprite(frm),
_start_time(frm._start_time),
_length(frm._length) {
}
qdAnimationFrame::~qdAnimationFrame() {
free();
}
qdAnimationFrame &qdAnimationFrame::operator = (const qdAnimationFrame &frm) {
if (this == &frm) return *this;
*static_cast<qdSprite *>(this) = frm;
_start_time = frm._start_time;
_length = frm._length;
return *this;
}
qdAnimationFrame *qdAnimationFrame::clone() const {
return new qdAnimationFrame(*this);
}
void qdAnimationFrame::qda_load(Common::SeekableReadStream *fh, int version) {
/*int32 fl = */fh->readSint32LE();
_start_time = fh->readFloatLE();
_length = fh->readFloatLE();
qdSprite::qda_load(fh, version);
}
bool qdAnimationFrame::load_resources() {
if (!load()) return false;
return true;
}
void qdAnimationFrame::free_resources() {
free();
}
} // namespace QDEngine

View 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/>.
*
*/
#ifndef QDENGINE_QDCORE_QD_ANIMATION_FRAME_H
#define QDENGINE_QDCORE_QD_ANIMATION_FRAME_H
#include "qdengine/qdcore/qd_sprite.h"
namespace QDEngine {
//! Кадр анимации.
class qdAnimationFrame : public qdSprite {
public:
qdAnimationFrame();
qdAnimationFrame(const qdAnimationFrame &frm);
~qdAnimationFrame();
qdAnimationFrame &operator = (const qdAnimationFrame &frm);
qdAnimationFrame *clone() const;
float start_time() const {
return _start_time;
}
float end_time() const {
return _start_time + _length;
}
float length() const {
return _length;
}
void set_start_time(float tm) {
_start_time = tm;
}
void set_length(float tm) {
_length = tm;
}
virtual void qda_load(class Common::SeekableReadStream *fh, int version = 100);
bool load_resources();
void free_resources();
private:
float _start_time;
float _length;
};
typedef Std::list<qdAnimationFrame *> qdAnimationFrameList;
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_ANIMATION_FRAME_H

View File

@@ -0,0 +1,128 @@
/* 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/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/xmath.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/qdcore/qd_game_scene.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
#include "qdengine/qdcore/qd_named_object.h"
#include "qdengine/qdcore/qd_animation_info.h"
#include "qdengine/qdcore/qd_animation.h"
namespace QDEngine {
qdAnimationInfo::qdAnimationInfo() : _speed(0.0f), _animation_speed(1.0f) {
}
qdAnimationInfo::qdAnimationInfo(const qdAnimationInfo &p) : qdNamedObject(p),
_speed(p._speed),
_animation_speed(p._animation_speed) {
}
qdAnimationInfo::~qdAnimationInfo() {
}
void qdAnimationInfo::load_script(const xml::tag *p) {
int fl;
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_SPEED:
xml::tag_buffer(*it) > _speed;
break;
case QDSCR_ANIMATION_SPEED:
xml::tag_buffer(*it) > _animation_speed;
break;
case QDSCR_ANIMATION:
set_animation_name(it->data());
break;
case QDSCR_FLAG:
xml::tag_buffer(*it) > fl;
set_flag(fl);
break;
}
}
}
bool qdAnimationInfo::save_script(Common::WriteStream &fh, int indent) const {
Common::String res;
if (flags()) {
if (debugChannelSet(-1, kDebugLog))
res += Common::String::format(" flags=\"%s\"", qdAnimation::flag2str(flags()).c_str());
else
res += Common::String::format(" flags=\"%d\"", flags());
}
if (_speed > 0.01f)
res += Common::String::format(" speed=\"%f\"", _speed);
if (_animation_speed != 1.0f)
res += Common::String::format(" animation_speed=\"%f\"", _animation_speed);
if (animation_name())
res += Common::String::format(" animation=\"%s\"", qdscr_XML_string(animation_name()));
if (!res.empty()) {
for (int i = 0; i < indent; i++)
fh.writeString("\t");
fh.writeString("<animation_info");
fh.writeString(res);
fh.writeString("/>\r\n");
}
return true;
}
qdAnimationInfo &qdAnimationInfo::operator = (const qdAnimationInfo &p) {
if (this == &p)
return *this;
*static_cast<qdNamedObject *>(this) = p;
_speed = p._speed;
_animation_speed = p._animation_speed;
return *this;
}
qdAnimation *qdAnimationInfo::animation() const {
if (animation_name()) {
if (qdGameScene *p = static_cast<qdGameScene *>(owner(QD_NAMED_OBJECT_SCENE))) {
if (qdAnimation *anm = p->get_animation(animation_name()))
return anm;
}
if (qdGameDispatcher *p = qd_get_game_dispatcher())
return p->get_animation(animation_name());
}
return NULL;
}
} // namespace QDEngine

View File

@@ -0,0 +1,85 @@
/* 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 QDENGINE_QDCORE_QD_ANIMATION_INFO_H
#define QDENGINE_QDCORE_QD_ANIMATION_INFO_H
#include "qdengine/parser/xml_fwd.h"
#include "qdengine/qdcore/qd_named_object.h"
namespace QDEngine {
class qdAnimation;
//! Информация об анимации.
class qdAnimationInfo : public qdNamedObject {
public:
qdAnimationInfo();
qdAnimationInfo(const qdAnimationInfo &p);
~qdAnimationInfo();
qdAnimationInfo &operator = (const qdAnimationInfo &p);
int named_object_type() const {
return QD_NAMED_OBJECT_ANIMATION_INFO;
}
float speed() const {
return _speed;
}
void set_speed(float sp) {
_speed = sp;
}
float animation_speed() const {
return _animation_speed;
}
void set_animation_speed(float sp) {
_animation_speed = sp;
}
qdAnimation *animation() const;
const char *animation_name() const {
return name();
}
void load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
void set_animation_name(const char *name) {
set_name(name);
}
void free_animation_name() {
set_name(0);
}
private:
float _speed;
float _animation_speed;
};
typedef Std::vector<qdAnimationInfo> qdAnimationInfoVector;
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_ANIMATION_INFO_H

View File

@@ -0,0 +1,451 @@
/* 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 "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/qdcore/qd_animation_set.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
namespace QDEngine {
qdAnimationSet::qdAnimationSet() {
_start_angle = 0.0f;
}
qdAnimationSet::qdAnimationSet(const qdAnimationSet &set) : qdNamedObject(set),
_start_angle(set._start_angle),
_animations(set._animations),
_walk_sound_frequency(set._walk_sound_frequency),
_static_animations(set._static_animations),
_start_animations(set._start_animations),
_stop_animations(set._stop_animations),
_turn_animation(set._turn_animation) {
_turn_animation.set_owner(this);
for (int i = 0; i < size(); i++) {
_animations[i].set_owner(this);
_static_animations[i].set_owner(this);
_static_animations[i].set_owner(this);
_stop_animations[i].set_owner(this);
}
}
qdAnimationSet::~qdAnimationSet() {
_animations.clear();
_static_animations.clear();
_start_animations.clear();
_stop_animations.clear();
}
qdAnimationSet &qdAnimationSet::operator = (const qdAnimationSet &set) {
if (this == &set) return *this;
*static_cast<qdNamedObject *>(this) = set;
_start_angle = set._start_angle;
_animations = set._animations;
_static_animations = set._static_animations;
_start_animations = set._stop_animations;
_stop_animations = set._stop_animations;
_walk_sound_frequency = set._walk_sound_frequency;
_turn_animation = set._turn_animation;
_turn_animation.set_owner(this);
for (int i = 0; i < size(); i++) {
_animations[i].set_owner(this);
_static_animations[i].set_owner(this);
_start_animations[i].set_owner(this);
_stop_animations[i].set_owner(this);
}
return *this;
}
void qdAnimationSet::resize(int sz) {
_animations.resize(sz);
_static_animations.resize(sz);
_start_animations.resize(sz);
_stop_animations.resize(sz);
_walk_sound_frequency.resize(sz, 1);
for (int i = 0; i < size(); i++) {
_animations[i].set_owner(this);
_static_animations[i].set_owner(this);
}
}
qdAnimationInfo *qdAnimationSet::get_animation_info(int index) {
if (index >= 0 && index < size())
return &_animations[index];
return 0;
}
int qdAnimationSet::get_angle_index(float direction_angle, int dir_count) {
if (direction_angle < 0.0f)
direction_angle += 2.0f * M_PI;
int index = round(direction_angle * float(dir_count) / (2.0f * M_PI));
if (index >= dir_count) index -= dir_count;
if (index < 0) index += dir_count;
return index;
}
float qdAnimationSet::get_index_angle(int index, int dir_count) {
return index * 2.f * M_PI / dir_count;
}
float qdAnimationSet::get_index_angle(int direction_index) const {
return get_index_angle(direction_index, size()) + _start_angle;
}
int qdAnimationSet::get_angle_index(float direction_angle) const {
return get_angle_index(direction_angle - _start_angle, size());
}
qdAnimationInfo *qdAnimationSet::get_animation_info(float direction_angle) {
int index = get_angle_index(direction_angle);
return get_animation_info(index);
}
qdAnimationInfo *qdAnimationSet::get_static_animation_info(int index) {
if (index >= 0 && index < size())
return &_static_animations[index];
return 0;
}
qdAnimationInfo *qdAnimationSet::get_static_animation_info(float direction_angle) {
int index = get_angle_index(direction_angle);
return get_static_animation_info(index);
}
qdAnimationInfo *qdAnimationSet::get_start_animation_info(int index) {
if (index >= 0 && index < size())
return &_start_animations[index];
return 0;
}
qdAnimationInfo *qdAnimationSet::get_start_animation_info(float direction_angle) {
int index = get_angle_index(direction_angle);
return get_start_animation_info(index);
}
qdAnimationInfo *qdAnimationSet::get_stop_animation_info(int index) {
if (index >= 0 && index < size())
return &_stop_animations[index];
return 0;
}
qdAnimationInfo *qdAnimationSet::get_stop_animation_info(float direction_angle) {
int index = get_angle_index(direction_angle);
return get_stop_animation_info(index);
}
qdAnimation *qdAnimationSet::get_turn_animation() const {
return _turn_animation.animation();
}
void qdAnimationSet::load_script(const xml::tag *p) {
int index = 0;
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_NAME:
set_name(it->data());
break;
case QDSCR_FLAG:
set_flag(xml::tag_buffer(*it).get_int());
break;
case QDSCR_SIZE:
resize(xml::tag_buffer(*it).get_int());
break;
case QDSCR_ANIMATION_INFO:
if (index < size())
_animations[index].load_script(&*it);
else if (index < size() * 2)
_static_animations[index - size()].load_script(&*it);
else if (index < size() * 3)
_start_animations[index - size() * 2].load_script(&*it);
else
_stop_animations[index - size() * 3].load_script(&*it);
index++;
break;
case QDSCR_ANIMATION_SET_TURN:
_turn_animation.set_animation_name(it->data());
break;
case QDSCR_ANIMATION_SET_START_ANGLE:
xml::tag_buffer(*it) > _start_angle;
break;
case QDSCR_OBJECT_STATE_WALK_SOUND_FREQUENCY: {
xml::tag_buffer buf(*it);
_walk_sound_frequency.resize(it->data_size());
for (int i = 0; i < it->data_size(); i++)
buf > _walk_sound_frequency[i];
}
break;
}
}
}
bool qdAnimationSet::save_script(Common::WriteStream &fh, int indent) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString(Common::String::format("<animation_set name=\"%s\"", qdscr_XML_string(name())));
if (_turn_animation.animation_name()) {
fh.writeString(Common::String::format(" animation_turn=\"%s\"", qdscr_XML_string(_turn_animation.animation_name())));
}
fh.writeString(Common::String::format(" size=\"%d\"", size()));
if (fabs(_start_angle) > FLT_EPS) {
fh.writeString(Common::String::format(" start_angle=\"%f\"", _start_angle));
}
fh.writeString(">\r\n");
for (auto &it : _animations) {
it.save_script(fh, indent + 1);
}
for (auto &it : _static_animations) {
it.save_script(fh, indent + 1);
}
for (auto &it : _start_animations) {
it.save_script(fh, indent + 1);
}
for (auto &it : _stop_animations) {
it.save_script(fh, indent + 1);
}
if (_walk_sound_frequency.size()) {
for (int i = 0; i <= indent; i++) {
fh.writeString("\t");
}
fh.writeString(Common::String::format("<walk_sound_frequency>%u", _walk_sound_frequency.size()));
for (uint i = 0; i < _walk_sound_frequency.size(); i++) {
fh.writeString(Common::String::format(" %f", _walk_sound_frequency[i]));
}
fh.writeString("</walk_sound_frequency>\r\n");
}
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString("</animation_set>\r\n");
return true;
}
bool qdAnimationSet::load_animations(const qdNamedObject *res_owner) {
if (qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher()) {
for (auto &it : _animations) {
if (qdAnimation *p = it.animation()) {
dp->load_resource(p, res_owner);
}
}
for (auto &it : _static_animations) {
if (qdAnimation *p = it.animation()) {
dp->load_resource(p, res_owner);
}
}
for (auto &it : _start_animations) {
if (qdAnimation *p = it.animation()) {
dp->load_resource(p, res_owner);
}
}
for (auto &it : _stop_animations) {
if (qdAnimation *p = it.animation()) {
dp->load_resource(p, res_owner);
}
}
if (qdAnimation *p = _turn_animation.animation())
dp->load_resource(p, res_owner);
return true;
}
return false;
}
bool qdAnimationSet::free_animations(const qdNamedObject *res_owner) {
if (qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher()) {
for (auto &it : _animations) {
if (qdAnimation *p = it.animation()) {
dp->release_resource(p, res_owner);
}
}
for (auto &it : _static_animations) {
if (qdAnimation *p = it.animation()) {
dp->release_resource(p, res_owner);
}
}
for (auto &it : _start_animations) {
if (qdAnimation *p = it.animation()) {
dp->release_resource(p, res_owner);
}
}
for (auto &it : _stop_animations) {
if (qdAnimation *p = it.animation()) {
dp->release_resource(p, res_owner);
}
}
if (qdAnimation *p = _turn_animation.animation())
dp->release_resource(p, res_owner);
return true;
}
return false;
}
bool qdAnimationSet::scale_animations(float coeff_x, float coeff_y) {
bool res = true;
for (auto &it : _animations) {
qdAnimation *p = it.animation();
if (p)
if (!p->scale(coeff_x, coeff_y)) res = false;
}
for (auto &it : _static_animations) {
qdAnimation *p = it.animation();
if (p)
if (!p->scale(coeff_x, coeff_y)) res = false;
}
for (auto &it : _start_animations) {
qdAnimation *p = it.animation();
if (p)
if (!p->scale(coeff_x, coeff_y)) res = false;
}
for (auto &it : _stop_animations) {
qdAnimation *p = it.animation();
if (p)
if (!p->scale(coeff_x, coeff_y)) res = false;
}
if (qdAnimation *p = _turn_animation.animation())
if (!p->scale(coeff_x, coeff_y)) res = false;
return res;
}
bool qdAnimationSet::register_resources(const qdNamedObject *res_owner) {
if (qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher()) {
for (auto &it : _animations) {
if (qdAnimation *p = it.animation())
dp->register_resource(p, res_owner);
}
for (auto &it : _static_animations) {
if (qdAnimation *p = it.animation())
dp->register_resource(p, res_owner);
}
for (auto &it : _start_animations) {
if (qdAnimation *p = it.animation())
dp->register_resource(p, res_owner);
}
for (auto &it : _stop_animations) {
if (qdAnimation *p = it.animation())
dp->register_resource(p, res_owner);
}
if (qdAnimation *p = _turn_animation.animation())
dp->register_resource(p, res_owner);
return true;
}
return false;
}
bool qdAnimationSet::unregister_resources(const qdNamedObject *res_owner) {
if (qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher()) {
for (auto &it : _animations) {
if (qdAnimation *p = it.animation())
dp->unregister_resource(p, res_owner);
}
for (auto &it : _static_animations) {
if (qdAnimation *p = it.animation())
dp->unregister_resource(p, res_owner);
}
for (auto &it : _start_animations) {
if (qdAnimation *p = it.animation())
dp->unregister_resource(p, res_owner);
}
for (auto &it : _stop_animations) {
if (qdAnimation *p = it.animation())
dp->unregister_resource(p, res_owner);
}
if (qdAnimation *p = _turn_animation.animation())
dp->unregister_resource(p, res_owner);
return true;
}
return false;
}
float qdAnimationSet::adjust_angle(float angle) const {
int dir = get_angle_index(angle);
if (dir == -1) return 0.0f;
return get_index_angle(dir);
}
float qdAnimationSet::walk_sound_frequency(int direction_index) const {
if (direction_index < 0 || direction_index >= (int)_walk_sound_frequency.size())
return 1;
else
return _walk_sound_frequency[direction_index];
}
float qdAnimationSet::walk_sound_frequency(float direction_angle) const {
int index = get_angle_index(direction_angle);
return walk_sound_frequency(index);
}
void qdAnimationSet::set_walk_sound_frequency(int direction_index, float freq) {
assert(direction_index >= 0);
if (direction_index >= (int)_walk_sound_frequency.size())
_walk_sound_frequency.resize(direction_index + 1, 1);
_walk_sound_frequency[direction_index] = freq;
}
} // namespace QDEngine

View File

@@ -0,0 +1,128 @@
/* 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 QDENGINE_QDCORE_QD_ANIMATION_SET_H
#define QDENGINE_QDCORE_QD_ANIMATION_SET_H
#include "qdengine/parser/xml_fwd.h"
#include "qdengine/qdcore/qd_named_object.h"
#include "qdengine/qdcore/qd_animation.h"
#include "qdengine/qdcore/qd_animation_info.h"
namespace QDEngine {
class qdAnimationSet : public qdNamedObject {
public:
qdAnimationSet();
qdAnimationSet(const qdAnimationSet &set);
~qdAnimationSet();
qdAnimationSet &operator = (const qdAnimationSet &set);
int named_object_type() const {
return QD_NAMED_OBJECT_ANIMATION_SET;
}
int size() const {
return _animations.size();
}
void resize(int sz);
//! выдает индекс походки и остановки, соответствующих углу
int get_angle_index(float direction_angle) const;
//! выдает угол походки и остановки, соответствующих индексу
float get_index_angle(int direction_index) const;
//! Возвращает ближайшее к angle направление, для которого есть анимация.
float adjust_angle(float angle) const;
qdAnimationInfo *get_animation_info(int index = 0);
qdAnimationInfo *get_animation_info(float direction_angle);
qdAnimationInfo *get_static_animation_info(int index = 0);
qdAnimationInfo *get_static_animation_info(float direction_angle);
qdAnimationInfo *get_start_animation_info(int index = 0);
qdAnimationInfo *get_start_animation_info(float direction_angle);
qdAnimationInfo *get_stop_animation_info(int index = 0);
qdAnimationInfo *get_stop_animation_info(float direction_angle);
qdAnimation *get_turn_animation() const;
qdAnimationInfo *get_turn_animation_info() {
return &_turn_animation;
}
void set_turn_animation(const char *animation_name) {
_turn_animation.set_animation_name(animation_name);
}
float walk_sound_frequency(int direction_index) const;
float walk_sound_frequency(float direction_angle) const;
void set_walk_sound_frequency(int direction_index, float freq);
bool load_animations(const qdNamedObject *res_owner);
bool free_animations(const qdNamedObject *res_owner);
//! Регистрация ресурсов набора в диспетчере ресурсов.
bool register_resources(const qdNamedObject *res_owner);
//! Отмена регистрации ресурсов набора в диспетчере ресурсов.
bool unregister_resources(const qdNamedObject *res_owner);
bool scale_animations(float coeff_x, float coeff_y);
void load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
float start_angle() const {
return _start_angle;
}
void set_start_angle(float v) {
_start_angle = v;
}
private:
//! Угол, соответствующий первому направлению в походке.
/**
Если нулевой - первое направление вправо.
*/
float _start_angle;
qdAnimationInfoVector _animations;
qdAnimationInfoVector _static_animations;
qdAnimationInfoVector _start_animations;
qdAnimationInfoVector _stop_animations;
/// анимация поворота, полный оборот начиная с направления вправо
qdAnimationInfo _turn_animation;
//! Коэффициенты для частоты звука походки.
Std::vector<float> _walk_sound_frequency;
static int get_angle_index(float direction_angle, int dir_count);
static float get_index_angle(int index, int dir_count);
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_ANIMATION_SET_H

View File

@@ -0,0 +1,42 @@
/* 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 "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_animation_set_info.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
#include "qdengine/qdcore/qd_game_scene.h"
namespace QDEngine {
qdAnimationSet *qdAnimationSetInfo::animation_set() const {
if (name()) {
if (qdGameScene *p = static_cast<qdGameScene *>(owner(QD_NAMED_OBJECT_SCENE))) {
if (qdAnimationSet *set = p->get_animation_set(name()))
return set;
}
if (qdGameDispatcher *p = qdGameDispatcher::get_dispatcher())
return p->get_animation_set(name());
}
return NULL;
}
} // namespace QDEngine

View 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 QDENGINE_QDCORE_QD_ANIMATION_SET_INFO_H
#define QDENGINE_QDCORE_QD_ANIMATION_SET_INFO_H
#include "qdengine/qdcore/qd_named_object.h"
namespace QDEngine {
class qdAnimationSet;
//! Информация о наборе анимаций.
class qdAnimationSetInfo : public qdNamedObject {
public:
qdAnimationSetInfo() { }
~qdAnimationSetInfo() { }
int named_object_type() const {
return QD_NAMED_OBJECT_ANIMATION_SET_INFO;
}
qdAnimationSet *animation_set() const;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_ANIMATION_SET_INFO_H

View File

@@ -0,0 +1,243 @@
/* 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/system.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_animation_set.h"
#include "qdengine/qdcore/qd_animation_set_preview.h"
#include "qdengine/qdcore/qd_camera.h"
namespace QDEngine {
qdAnimationSetPreview::qdAnimationSetPreview(qdAnimationSet *p) :
_graph_d(0),
_animation_set(p),
_preview_mode(VIEW_WALK_ANIMATIONS) {
_animation = new qdAnimation;
_camera = new qdCamera;
_camera->set_focus(2000.0f);
_camera_angle = 45;
_start_time = 0;
_back_color = 0x000000FF;
_grid_color = 0x00FF00FF;
set_direction(0);
_cell_size = 100;
_personage_height = float(_animation->size_y());
p->load_animations(NULL);
}
qdAnimationSetPreview::~qdAnimationSetPreview() {
_animation_set->free_animations(NULL);
delete _animation;
delete _camera;
}
void qdAnimationSetPreview::set_graph_dispatcher(grDispatcher *p) {
_graph_d = p;
set_screen(Vect2s(0, 0), Vect2s(p->get_SizeX(), p->get_SizeY()));
}
void qdAnimationSetPreview::start() {
_start_time = g_system->getMillis();
_animation->start();
_cell_offset = 0.0f;
}
void qdAnimationSetPreview::quant() {
int time = g_system->getMillis();
float tm = float(time - _start_time) / 1000.0f;
_start_time = time;
if (tm >= 0.3f) return;
quant(tm);
}
void qdAnimationSetPreview::quant(float tm) {
_animation->quant(tm);
_cell_offset -= _personage_speed * tm;
while (_cell_offset <= -float(_cell_size)) _cell_offset += float(_cell_size);
}
void qdAnimationSetPreview::redraw() {
grDispatcher *gp = grDispatcher::set_instance(_graph_d);
grDispatcher::instance()->fill(_back_color);
redraw_grid();
Vect2s v = _camera->global2scr(Vect3f(0.0f, 0.0f, _personage_height / 2.0f));
float scale = _camera->get_scale(Vect3f(0.0f, 0.0f, _personage_height / 2.0f));
_animation->redraw(v.x, v.y, scale);
Vect2s v0 = _camera->global2scr(Vect3f(0.0f, 0.0f, _personage_height));
Vect2s v1 = _camera->global2scr(Vect3f(0.0f, 0.0f, 0.0f));
const int rect_sz = 4;
grDispatcher::instance()->rectangle(v.x - rect_sz / 2, v.y - rect_sz / 2, rect_sz, rect_sz, _grid_color, _grid_color, GR_FILLED);
const int line_sz = 10;
grDispatcher::instance()->line(v0.x - line_sz, v0.y, v0.x + line_sz, v0.y, _grid_color);
grDispatcher::instance()->line(v1.x - line_sz, v1.y, v1.x + line_sz, v1.y, _grid_color);
grDispatcher::instance()->line(v0.x, v0.y, v1.x, v1.y, _grid_color);
grDispatcher::instance()->rectangle(_screen_offset.x, _screen_offset.y, _screen_size.x, _screen_size.y, _grid_color, 0, GR_OUTLINED);
grDispatcher::instance()->flush();
grDispatcher::set_instance(gp);
}
bool qdAnimationSetPreview::set_direction(int dir) {
bool result = false;
_animation->clear();
_personage_speed = 0.0f;
_direction = dir;
_cell_offset = 0.0f;
float angle = _animation_set->get_index_angle(_direction) * 180.0f / M_PI;
_camera->rotate_and_scale(_camera_angle, 0, angle, 1.0f, 1.0f, 1.0f);
qdAnimationInfo *p = NULL;
if (_preview_mode == VIEW_WALK_ANIMATIONS)
p = _animation_set->get_animation_info(dir);
else if (_preview_mode == VIEW_STATIC_ANIMATIONS)
p = _animation_set->get_static_animation_info(dir);
else if (_preview_mode == VIEW_START_ANIMATIONS)
p = _animation_set->get_start_animation_info(dir);
else if (_preview_mode == VIEW_STOP_ANIMATIONS)
p = _animation_set->get_stop_animation_info(dir);
if (p) {
qdAnimation *ap = p->animation();
if (ap) {
ap->create_reference(_animation, p);
result = true;
}
_personage_speed = p->speed();
}
_animation->start();
return result;
}
void qdAnimationSetPreview::set_cell_size(int sz) {
_cell_size = sz;
_animation->start();
_cell_offset = 0.0f;
}
void qdAnimationSetPreview::set_screen(Vect2s offs, Vect2s size) {
if (!_graph_d) return;
_screen_offset = offs;
_screen_size = size;
_camera->set_scr_size(size.x, size.y);
_camera->set_scr_center(offs.x + size.x / 2, offs.y + size.y * 3 / 4);
_graph_d->setClip(offs.x, offs.y, offs.x + size.x, offs.y + size.y);
}
void qdAnimationSetPreview::redraw_grid() {
float size = 0;
Vect2f p = _camera->scr2plane(_screen_offset);
if (fabs(p.x) > size) size = fabs(p.x);
if (fabs(p.y) > size) size = fabs(p.y);
p = _camera->scr2plane(_screen_offset + _screen_size);
if (fabs(p.x) > size) size = fabs(p.x);
if (fabs(p.y) > size) size = fabs(p.y);
p = _camera->scr2plane(Vect2s(_screen_offset.x + _screen_size.x, _screen_offset.y));
if (fabs(p.x) > size) size = fabs(p.x);
if (fabs(p.y) > size) size = fabs(p.y);
p = _camera->scr2plane(Vect2s(_screen_offset.x, _screen_offset.y + _screen_size.y));
if (fabs(p.x) > size) size = fabs(p.x);
if (fabs(p.y) > size) size = fabs(p.y);
int sz = round(size) + _cell_size;
sz -= sz % _cell_size;
for (int i = -sz; i <= sz; i += _cell_size) {
int dx = round(_cell_offset);
Vect3f v00 = _camera->global2camera_coord(Vect3f(i + dx, -sz, 0));
Vect3f v10 = _camera->global2camera_coord(Vect3f(i + dx, sz, 0));
if (_camera->line_cutting(v00, v10)) {
Vect2s v0 = _camera->camera_coord2scr(v00);
Vect2s v1 = _camera->camera_coord2scr(v10);
grDispatcher::instance()->line(v0.x, v0.y, v1.x, v1.y, _grid_color, 0);
}
v00 = _camera->global2camera_coord(Vect3f(-sz + dx, i, 0));
v10 = _camera->global2camera_coord(Vect3f(sz + dx, i, 0));
if (_camera->line_cutting(v00, v10)) {
Vect2s v0 = _camera->camera_coord2scr(v00);
Vect2s v1 = _camera->camera_coord2scr(v10);
grDispatcher::instance()->line(v0.x, v0.y, v1.x, v1.y, _grid_color, 0);
}
/*
v0 = _camera->global2scr(Vect3f(-sz + dx,i,0));
v1 = _camera->global2scr(Vect3f(sz + dx,i,0));
grDispatcher::instance()->line(v0.x,v0.y,v1.x,v1.y,_grid_color,0);
*/
}
}
void qdAnimationSetPreview::set_camera_angle(int ang) {
_camera_angle = ang;
float angle = _animation_set->get_index_angle(_direction) * 180.0f / M_PI;
_camera->rotate_and_scale(_camera_angle, 0, angle, 1.0f, 1.0f, 1.0f);
}
float qdAnimationSetPreview::camera_focus() {
return _camera->get_focus();
}
void qdAnimationSetPreview::set_camera_focus(float f) {
_camera->set_focus(f);
}
bool qdAnimationSetPreview::set_phase(float phase) {
if (!_animation->is_empty()) {
if (!_animation->is_playing())
_animation->start();
_cell_offset = 0.0f;
_animation->set_time(0.0f);
quant(_animation->length() * phase);
return true;
}
return false;
}
} // namespace QDEngine

View File

@@ -0,0 +1,150 @@
/* 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 QDENGINE_QDCORE_ANIMATION_SET_PREVIEW_H
#define QDENGINE_QDCORE_ANIMATION_SET_PREVIEW_H
#include "qdengine/system/graphics/gr_dispatcher.h"
namespace QDEngine {
class qdCamera;
class qdAnimation;
class qdAnimationSet;
//! Превью походки.
class qdAnimationSetPreview {
public:
enum preview_mode_t {
VIEW_WALK_ANIMATIONS,
VIEW_STATIC_ANIMATIONS,
VIEW_START_ANIMATIONS,
VIEW_STOP_ANIMATIONS
};
qdAnimationSetPreview(qdAnimationSet *p);
~qdAnimationSetPreview();
preview_mode_t preview_mode() const {
return _preview_mode;
}
void set_preview_mode(preview_mode_t md) {
_preview_mode = md;
}
void set_screen(Vect2s offs, Vect2s size);
uint32 back_color() const {
return _back_color;
}
void set_back_color(uint32 col) {
_back_color = col;
}
uint32 grid_color() const {
return _grid_color;
}
void set_grid_color(uint32 col) {
_grid_color = col;
}
int camera_angle() const {
return _camera_angle;
}
void set_camera_angle(int ang);
float camera_focus();
void set_camera_focus(float f);
int cell_size() const {
return _cell_size;
}
void set_cell_size(int sz);
float personage_speed() const {
return _personage_speed;
}
void set_personage_speed(float sp) {
_personage_speed = sp;
}
float personage_height() const {
return _personage_height;
}
void set_personage_height(float h) {
_personage_height = h;
}
int direction() const {
return _direction;
}
bool set_direction(int dir);
bool set_phase(float phase);
void set_graph_dispatcher(grDispatcher *p);
void start();
void quant();
void quant(float tm);
void redraw();
const qdAnimation *cur_animation() const {
return _animation;
}
private:
int _start_time;
int _direction;
//float speed_;
float _personage_speed;
float _personage_height;
qdAnimation *_animation;
qdAnimationSet *_animation_set;
qdCamera *_camera;
int _camera_angle;
grDispatcher *_graph_d;
uint32 _back_color;
uint32 _grid_color;
int _cell_size;
float _cell_offset;
Vect2s _screen_offset;
Vect2s _screen_size;
preview_mode_t _preview_mode;
void redraw_grid();
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_ANIMATION_SET_PREVIEW_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,505 @@
/* 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 QDENGINE_QDCORE_QD_CAMERA_H
#define QDENGINE_QDCORE_QD_CAMERA_H
#include "qdengine/qdcore/qd_d3dutils.h"
#include "qdengine/qdcore/qd_camera_mode.h"
namespace Common {
class WriteStream;
}
namespace QDEngine {
class sGridCell {
public:
//! Атрибуты
enum cell_attribute_t {
//! ячейка выделена
CELL_SELECTED = 0x01,
//! ячейка непроходима
CELL_IMPASSABLE = 0x02,
//! ячейка занята объектом
CELL_OCCUPIED = 0x04,
//! ячейка занята персонажем
CELL_PERSONAGE_OCCUPIED = 0x08,
//! по ячейке проходит путь персонажа
CELL_PERSONAGE_PATH = 0x10
};
sGridCell() {
_attributes = CELL_IMPASSABLE;
}
sGridCell(uint16 atr, int16 h) {
_attributes = atr;
}
~sGridCell() { }
bool is_walkable() const {
return !check_attribute(CELL_IMPASSABLE);
}
void make_impassable() {
set_attribute(CELL_IMPASSABLE);
}
void make_walkable() {
drop_attribute(CELL_IMPASSABLE);
}
void select() {
set_attribute(CELL_SELECTED);
}
void deselect() {
drop_attribute(CELL_SELECTED);
}
void toggle_select() {
toggle_attribute(CELL_SELECTED);
}
bool is_selected() const {
return check_attribute(CELL_SELECTED);
}
int16 height() const {
return 0;
}
void set_height(int16 h) { }
void set_attribute(uint32 attr) {
_attributes |= attr;
}
void toggle_attribute(uint32 attr) {
_attributes ^= attr;
}
void drop_attribute(uint32 attr) {
_attributes &= ~attr;
}
bool check_attribute(uint32 attr) const {
if (_attributes & attr) return true;
else return false;
}
uint32 attributes() const {
return _attributes;
}
void set_attributes(uint32 attr) {
_attributes = attr;
}
bool clear() {
_attributes = 0;
return true;
}
private:
byte _attributes;
};
enum qdCameraRedrawMode {
QDCAM_GRID_ABOVE,
QDCAM_GRID_ZBUFFER,
QDCAM_GRID_NONE
};
class qdCamera {
public:
qdCamera();
~qdCamera();
// Устанавливет параметры клетки с координатами cell_pos
// по параметрам клетки cell
bool set_grid_cell(const Vect2s &cell_pos, const sGridCell &cell);
bool set_grid_cell_attributes(const Vect2s &cell_pos, int attr);
//! Устанавливает атрибуты для клеток из прямоугольника на сетке с ценром center_pos и размерами size.
bool set_grid_attributes(const Vect2s &center_pos, const Vect2s &size, int attr);
//! Очищает атрибуты для клеток из прямоугольника на сетке с ценром center_pos и размерами size.
bool drop_grid_attributes(const Vect2s &center_pos, const Vect2s &size, int attr);
//! Возвращает true, если в прямоугольнике на сетке ЕСТЬ ХОТЯ БЫ ОДНА ячейка с атрибутами attr.
bool check_grid_attributes(const Vect2s &center_pos, const Vect2s &size, int attr) const;
//! Возвращает количество ячеек в заданной области, имеющих именно аттрибуты attr
int cells_num_with_exact_attributes(const Vect2s &center_pos, const Vect2s &size, int attr) const;
//! Устанавливает атрибуты для линии клеток.
bool set_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr);
//! Очищает атрибуты для линии клеток.
bool drop_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr);
//! Возвращает true, если в линии на сетке есть хотя бы одна ячейка с атрибутами attr.
bool check_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr) const;
bool is_walkable(const Vect2s &center_pos, const Vect2s &size, bool ignore_personages = false) const;
//! Устанавливает атрибуты attr для всех клеток сетки.
bool set_grid_attributes(int attr);
//! Очищает атрибуты attr для всех клеток сетки.
bool drop_grid_attributes(int attr);
sGridCell *get_cell(const Vect2s &cell_pos);
const sGridCell *get_cell(const Vect2s &cell_pos) const;
// Восстанавливает параметры клетки (сейчас - делает ее непроходимой
// с нулевой высотой)
bool restore_grid_cell(const Vect2s cell_pos);
void cycle_coords(int &x, int &y) const;
void set_redraw_mode(int md) const {
_redraw_mode = md;
}
int get_redraw_mode() const {
return _redraw_mode;
}
void set_grid_size(int xs, int ys);
void scale_grid(int sx, int sy, int csx, int csy);
void resize_grid(int sx, int sy);
int get_grid_sx() const {
return _GSX;
}
int get_grid_sy() const {
return _GSY;
}
const sGridCell *get_grid() const {
return _grid;
}
int get_cell_sx() const {
return _cellSX;
}
int get_cell_sy() const {
return _cellSY;
}
void set_cell_size(int csx, int csy) {
_cellSX = csx;
_cellSY = csy;
}
void clear_grid();
// rotateAndScaling
void rotate_and_scale(float XA, float YA, float ZA, float kX, float kY, float kZ);
float get_focus() const {
return _focus;
}
void set_focus(float focus) {
_focus = focus;
}
void set_R(const float r);
float get_R() const {
return _m_fR;
}
float get_x_angle() const {
return _xAngle;
}
float get_y_angle() const {
return _yAngle;
}
float get_z_angle() const {
return _zAngle;
}
inline void set_scr_size(int xs, int ys) {
_scrSize.x = xs;
_scrSize.y = ys;
}
const Vect2i &get_scr_size() const {
return _scrSize;
}
// getScrSizeX
int get_scr_sx() const {
return _scrSize.x;
}
// getScrSizeY
int get_scr_sy() const {
return _scrSize.y;
}
void set_scr_center(int xc, int yc) {
_scrCenter.x = xc;
_scrCenter.y = yc;
}
const Vect2i &get_scr_center() const {
return _scrCenter;
}
int get_scr_center_x() const {
return _scrCenter.x;
}
int get_scr_center_y() const {
return _scrCenter.y;
}
const Vect2i screen_center_limit_x() const;
const Vect2i screen_center_limit_y() const;
const Vect2i &get_scr_offset() const {
return _scrOffset;
}
void set_scr_offset(const Vect2i &offs) {
_scrOffset = offs;
}
const Vect2i &get_scr_center_initial() const {
return _scrCenterInitial;
}
void set_scr_center_initial(const Vect2i &v) {
_scrCenterInitial = v;
}
void move_scr_center(int dxc, int dyc);
float scrolling_phase_x() const;
float scrolling_phase_y() const;
const Vect3f scr2plane(const Vect2s &scrPoint) const;
const Vect3f rscr2plane(const Vect2s &rscrPoint) const;
const Vect3f scr2plane_camera_coord(const Vect2s &scrPoint) const;
const Vect3f rscr2plane_camera_coord(const Vect2s &scrPoint) const;
const Vect2s plane2scr(const Vect3f &plnPoint) const;
const Vect2s plane2rscr(const Vect3f &plnPoint) const;
const Vect3f rscr2camera_coord(const Vect2s &rScrPoint, float z) const;
const Vect2s camera_coord2rscr(const Vect3f &coord) const;
const Vect2s rscr2scr(const Vect2s &v) const;
const Vect2s scr2rscr(const Vect2s &v) const;
const Vect2s camera_coord2scr(const Vect3f &coord) const;
const Vect3f scr2global(const Vect2s &vScrPoint, float zInCameraCoord) const;
const Vect3f rscr2global(const Vect2s rScrPoint, const float zInCameraCoord) const;
const Vect3f global2camera_coord(const Vect3f &glCoord) const;
const Vect3f camera_coord2global(const Vect3f &v) const;
const Vect2s global2scr(const Vect3f &glCoord) const;
const Vect2s global2rscr(const Vect3f &glCoord) const;
//обрезание отрезка по плоскости отсечения камеры
//возвращает false, если отрезок вообеще невидим
bool line_cutting(Vect3f &b, Vect3f &e) const;
//! Обрезка линиии, так чтобы она за сетку не выходила.
/**
Все координаты - сеточные, т.е. индексы ячеек сетки.
*/
bool clip_grid_line(Vect2s &v0, Vect2s &v1) const;
// getKScale
float get_scale(const Vect3f &glCoord) const;
const Vect3f &get_grid_center() const {
return _gridCenter;
}
void set_grid_center(const Vect3f &v) {
_gridCenter = v;
}
const sGridCell *get_cell(float X, float Y) const;
const Vect2s get_cell_index(float X, float Y, bool grid_crop = true) const;
const Vect2s get_cell_index(const Vect3f &v, bool grid_crop = true) const;
const Vect3f get_cell_coords(int x_idx, int y_idx) const;
const Vect3f get_cell_coords(const Vect2s &idxs) const;
void reset_all_select();
//принимает глобальные координаты
bool select_cell(int x, int y);
//принимает глобальные координаты
bool deselect_cell(int x, int y);
void load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
//! Загрузка данных из сэйва.
bool load_data(Common::SeekableReadStream &fh, int save_version);
//! Запись данных в сэйв.
bool save_data(Common::WriteStream &fh) const;
//! Инициализация данных, вызывается при старте и перезапуске игры.
bool init();
bool draw_grid() const;
bool draw_cell(int x, int y, int z, int penWidth, uint32 color) const;
//! Установка текущего режима камеры.
/**
Если объект нулевой, то берется объект по-умолчанию.
*/
bool set_mode(const qdCameraMode &mode, qdGameObjectAnimated *object = NULL);
//! Возвращает true, если в данный момент можно менять режим камеры.
bool can_change_mode() const;
//! Установка объекта, за которым камера следит по умолчанию.
void set_default_object(qdGameObjectAnimated *p) {
_default_object = p;
}
//! Обсчет логики (движения камеры и т.д), параметр - время в секундах.
bool quant(float dt);
//! Возвращает false, если вся рабочая область камеры находится за пределами экрана.
/**
Параметр - дополнительное смещение центра рабочей области камеры.
*/
bool is_visible(const Vect2i &center_offs = Vect2i(0, 0)) const;
void set_cycle(bool cx, bool cy) {
_cycle_x = cx;
_cycle_y = cy;
}
void dump_grid(const char *file_name) const;
//! Параметры функции масштабирования
float scale_pow() const {
return _scale_pow;
}
void set_scale_pow(float sp) {
_scale_pow = sp;
}
float scale_z_offset() const {
return _scale_z_offset;
};
void set_scale_z_offset(float szo) {
_scale_z_offset = szo;
};
bool need_perspective_correction() const {
return (fabs(_scale_pow - 1) > 0.001 || fabs(_scale_z_offset) > 0.001);
}
//! Возвращает режим работы камеры по умолчанию.
const qdCameraMode &default_mode() const {
return _default_mode;
}
//! Установка режима работы камеры по умолчанию.
void set_default_mode(const qdCameraMode &mode) {
_default_mode = mode;
}
static qdCamera *current_camera() {
return _current_camera;
}
static void set_current_camera(qdCamera *p) {
_current_camera = p;
}
MATRIX3D const &get_view_matrix() const {
return _m_cam;
}
private:
MATRIX3D _m_cam;
float _m_fR;
float _xAngle, _yAngle, _zAngle;
int _GSX, _GSY;
sGridCell *_grid;
bool _cycle_x;
bool _cycle_y;
int _cellSX, _cellSY;
float _focus;//! расстояние до ближней плоскости отсечения
// расстояние от центра рабочей области до
// верхнего левого угла окна
Vect2i _scrCenter;
// начальное расстояние от центра рабочей области до
// верхнего левого угла окна
Vect2i _scrCenterInitial;
// размер рабочей области
Vect2i _scrSize;
// смещение рабочей области
Vect2i _scrOffset;
// Координаты центра сетки
Vect3f _gridCenter;
mutable int _redraw_mode;
//! Текущий режим работы камеры.
qdCameraMode _current_mode;
//! Время в секуднах с установки текущего режима.
float _current_mode_work_time;
bool _current_mode_switch;
//! Объект, за которым следит камера.
qdGameObjectAnimated *_current_object;
//! Объект, за которым камера следит по умолчанию.
qdGameObjectAnimated *_default_object;
//! Режим работы камеры по умолчанию.
qdCameraMode _default_mode;
//! Параметры функции ускоренного масштабирования из get_scale()
float _scale_pow;
float _scale_z_offset;
static qdCamera *_current_camera;
static const float _NEAR_PLANE; //ближная плоскость отсечения
static const float _FAR_PLANE; //дальняя
enum {
clLEFT = 1,
clRIGHT = 2,
clBOTTOM = 4,
clTOP = 8
};
inline int clip_out_code(const Vect2s &v) const {
int code = 0;
if (v.y >= _GSY)
code |= clTOP;
else if (v.y < 0)
code |= clBOTTOM;
if (v.x >= _GSX)
code |= clRIGHT;
else if (v.x < 0)
code |= clLEFT;
return code;
}
void clip_center_coords(int &x, int &y) const;
};
inline Vect3f To3D(const Vect2f &v) {
return Vect3f(v.x, v.y, 0);
}
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CAMERA_H

View File

@@ -0,0 +1,133 @@
/* 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/debug.h"
#include "common/stream.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/qdcore/qd_camera_mode.h"
namespace QDEngine {
qdCameraMode::qdCameraMode() : _camera_mode(MODE_UNASSIGNED),
_work_time(0.0f),
_scrolling_speed(100.0f),
_scrolling_distance(100),
_smooth_switch(false),
_center_offset(0, 0) {
}
bool qdCameraMode::load_script(const xml::tag *p) {
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
xml::tag_buffer buf(*it);
switch (it->ID()) {
case QDSCR_TYPE:
set_camera_mode(camera_mode_t(buf.get_int()));
break;
case QDSCR_TIME:
set_work_time(buf.get_float());
break;
case QDSCR_CAMERA_SCROLLING_SPEED:
set_scrolling_speed(buf.get_float());
break;
case QDSCR_CAMERA_SCROLLING_DIST:
set_scrolling_distance(buf.get_int());
break;
case QDSCR_CAMERA_SMOOTH_SWITCH:
_smooth_switch = (buf.get_int()) ? true : false;
break;
case QDSCR_CAMERA_SCREEN_CENTER:
buf > _center_offset.x > _center_offset.y;
break;
}
}
return true;
}
bool qdCameraMode::save_script(Common::WriteStream &fh, int indent) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString(Common::String::format("<camera_mode type=\"%d\"", (int)camera_mode()));
fh.writeString(Common::String::format(" scrolling_speed=\"%f\"", _scrolling_speed));
fh.writeString(Common::String::format(" scrolling_dist=\"%d\"", _scrolling_distance));
if (_center_offset.x || _center_offset.y) {
fh.writeString(Common::String::format(" camera_screen_center=\"%d %d\"", _center_offset.x, _center_offset.y));
}
if (has_work_time()) {
fh.writeString(Common::String::format(" time=\"%f\"", work_time()));
}
if (smooth_switch()) {
fh.writeString(" smooth_switch=\"1\"");
}
fh.writeString("/>\r\n");
return true;
}
bool qdCameraMode::load_data(Common::SeekableReadStream &fh, int save_version) {
debugC(4, kDebugSave, " qdCameraMode::load_data(): before: %d", (int)fh.pos());
/*int mode = */fh.readSint32LE();
_work_time = fh.readFloatLE();
_scrolling_speed = fh.readFloatLE();
_scrolling_distance = fh.readSint32LE();
_center_offset.x = fh.readSint32LE();
_center_offset.y = fh.readSint32LE();
char switch_flag = fh.readByte();
_smooth_switch = (switch_flag) ? true : false;
debugC(4, kDebugSave, " qdCameraMode::load_data(): after: %d", (int)fh.pos());
return true;
}
bool qdCameraMode::save_data(Common::WriteStream &fh) const {
debugC(4, kDebugSave, " qdCameraMode::save_data(): before: %d", (int)fh.pos());
fh.writeSint32LE((int)_camera_mode);
fh.writeFloatLE(_work_time);
fh.writeFloatLE(_scrolling_speed);
fh.writeSint32LE(_scrolling_distance);
fh.writeSint32LE(_center_offset.x);
fh.writeSint32LE(_center_offset.y);
if (_smooth_switch) {
fh.writeByte(1);
} else {
fh.writeByte(0);
}
debugC(4, kDebugSave, " qdCameraMode::save_data(): after: %d", (int)fh.pos());
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,152 @@
/* 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 QDENGINE_QDCORE_QD_CAMERA_MODE_H
#define QDENGINE_QDCORE_QD_CAMERA_MODE_H
#include "qdengine/xmath.h"
#include "qdengine/parser/xml_fwd.h"
namespace Common {
class SeekableReadStream;
class WriteStream;
}
namespace QDEngine {
class qdGameObjectState;
class qdGameObjectAnimated;
//! Режим работы камеры.
class qdCameraMode {
public:
qdCameraMode();
~qdCameraMode() { }
//! идентификаторы режимов камеры
enum camera_mode_t {
//! камера не выпускает объект с экрана
MODE_OBJECT_ON_SCREEN,
//! камера жестко привязана к объекту
MODE_CENTER_OBJECT,
//! камера все время центруется на объекте
MODE_FOLLOW_OBJECT,
//! когда объект подходит к краю экрана камера плавно на нем центруется
MODE_CENTER_OBJECT_WHEN_LEAVING,
//! режим не установлен
MODE_UNASSIGNED
};
void set_camera_mode(camera_mode_t mode) {
_camera_mode = mode;
}
camera_mode_t camera_mode() const {
return _camera_mode;
}
void set_work_time(float tm) {
_work_time = tm;
}
float work_time() const {
return _work_time;
}
bool has_work_time() const {
return _work_time > 0.001f;
}
void set_scrolling_speed(float v) {
_scrolling_speed = v;
}
float scrolling_speed() const {
return _scrolling_speed;
}
void set_scrolling_distance(int dist) {
_scrolling_distance = dist;
}
int scrolling_distance() const {
return _scrolling_distance;
}
bool smooth_switch() const {
return _smooth_switch;
}
void set_smooth_switch(bool v) {
_smooth_switch = v;
}
const Vect2i &center_offset() const {
return _center_offset;
}
void set_center_offset(const Vect2i &offs) {
_center_offset = offs;
}
bool load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
//! Загрузка данных из сэйва.
bool load_data(Common::SeekableReadStream &fh, int save_version);
//! Запись данных в сэйв.
bool save_data(Common::WriteStream &fh) const;
private:
//! Идентификатор режима.
camera_mode_t _camera_mode;
//! Время работы режима (в секундах).
/**
По истечении этого времени камера переключается
на активного персонажа (если он есть).
Если это время нулевое, то сменить режим можно будет
только в принудительном порядке из триггера.
*/
float _work_time;
//! Скорость, с которой камера скроллируется (в пикселах в секунду).
float _scrolling_speed;
//! Расстояние от центра объекта до края экрана, при котором включается скроллинг.
/**
В режимах, когда камера не дает объекту выйти за пределы экрана или
центруется на объекте когда он близко к краю экрана.
Задается в пикселах.
*/
int _scrolling_distance;
//! Смещение центра экрана в пикселах.
/**
Позволяет задавать режим, когда камера, центруясь на объекте,
держит его в определенной точке экрана.
*/
Vect2i _center_offset;
//! Плавное переключение в режим, если true.
bool _smooth_switch;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CAMERA_MODE_H

View File

@@ -0,0 +1,541 @@
/* 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/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/qdcore/qd_rnd.h"
#include "qdengine/qdcore/qd_condition.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
namespace Common {
class WriteStream;
}
namespace QDEngine {
bool qdCondition::_successful_click = false;
bool qdCondition::_successful_object_click = false;
qdCondition::qdCondition() : _type(CONDITION_FALSE), _is_inversed(false), _is_in_group(false) {
}
qdCondition::qdCondition(qdCondition::ConditionType tp) : _is_inversed(false), _is_in_group(false) {
set_type(tp);
}
qdCondition::qdCondition(const qdCondition &cnd) : _type(cnd._type),
_owner(cnd._owner),
_data(cnd._data),
_objects(cnd._objects),
_is_inversed(cnd._is_inversed),
_is_in_group(false) {
}
qdCondition &qdCondition::operator = (const qdCondition &cnd) {
if (this == &cnd) return *this;
_type = cnd._type;
_owner = cnd._owner;
_data = cnd._data;
_objects = cnd._objects;
_is_inversed = cnd._is_inversed;
return *this;
}
qdCondition::~qdCondition() {
}
void qdCondition::set_type(ConditionType tp) {
_type = tp;
switch (_type) {
case CONDITION_TRUE:
case CONDITION_FALSE:
break;
case CONDITION_MOUSE_CLICK:
case CONDITION_PERSONAGE_ACTIVE:
case CONDITION_MOUSE_ZONE_CLICK:
_data.resize(1);
_objects.resize(1);
init_data(0, qdConditionData::DATA_STRING);
break;
case CONDITION_MOUSE_OBJECT_CLICK:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_IN_ZONE:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_PERSONAGE_WALK_DIRECTION:
case CONDITION_PERSONAGE_STATIC_DIRECTION:
_data.resize(2);
_objects.resize(1);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_FLOAT, 1);
break;
case CONDITION_TIMER:
_data.resize(2);
init_data(0, qdConditionData::DATA_FLOAT, 2);
init_data(1, qdConditionData::DATA_INT, 2);
break;
case CONDITION_MOUSE_DIALOG_CLICK:
break;
case CONDITION_MINIGAME_STATE:
_data.resize(2);
_objects.resize(1);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_STATE:
case CONDITION_OBJECT_PREV_STATE:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_NOT_IN_STATE:
inverse();
_type = CONDITION_OBJECT_STATE;
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_MOUSE_OBJECT_ZONE_CLICK:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_STATE_WAS_ACTIVATED:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED:
inverse();
_type = CONDITION_OBJECT_STATE_WAS_ACTIVATED;
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECTS_DISTANCE:
_data.resize(3);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
init_data(2, qdConditionData::DATA_FLOAT, 1);
break;
case CONDITION_OBJECT_STATE_WAITING:
_data.resize(2);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
break;
case CONDITION_OBJECT_STATE_ANIMATION_PHASE:
_data.resize(3);
_objects.resize(2);
init_data(0, qdConditionData::DATA_STRING);
init_data(1, qdConditionData::DATA_STRING);
init_data(2, qdConditionData::DATA_FLOAT, 2);
break;
case CONDITION_STATE_TIME_GREATER_THAN_VALUE:
_data.resize(1);
_objects.resize(1);
init_data(0, qdConditionData::DATA_FLOAT, 1);
break;
case CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME:
_objects.resize(2);
break;
case CONDITION_STATE_TIME_IN_INTERVAL:
_data.resize(1);
_objects.resize(1);
init_data(0, qdConditionData::DATA_FLOAT, 2);
break;
case CONDITION_COUNTER_GREATER_THAN_VALUE:
case CONDITION_COUNTER_LESS_THAN_VALUE:
_data.resize(1);
_objects.resize(1);
init_data(0, qdConditionData::DATA_INT, 1);
break;
case CONDITION_COUNTER_GREATER_THAN_COUNTER:
_objects.resize(2);
break;
case CONDITION_COUNTER_IN_INTERVAL:
_data.resize(1);
_objects.resize(1);
init_data(0, qdConditionData::DATA_INT, 2);
break;
case CONDITION_OBJECT_ON_PERSONAGE_WAY:
_data.resize(1);
_objects.resize(2);
init_data(0, qdConditionData::DATA_FLOAT, 1);
break;
case CONDITION_KEYPRESS:
_data.resize(1);
init_data(0, qdConditionData::DATA_INT, 1);
break;
case CONDITION_ANY_PERSONAGE_IN_ZONE:
_objects.resize(1);
break;
case CONDITION_MOUSE_RIGHT_CLICK:
_objects.resize(1);
break;
case CONDITION_MOUSE_RIGHT_OBJECT_CLICK:
_objects.resize(2);
break;
case CONDITION_MOUSE_RIGHT_ZONE_CLICK:
_objects.resize(1);
break;
case CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK:
_objects.resize(2);
break;
case CONDITION_OBJECT_HIDDEN:
_objects.resize(1);
break;
case CONDITION_MOUSE_HOVER:
_objects.resize(1);
break;
case CONDITION_MOUSE_OBJECT_HOVER:
_objects.resize(2);
break;
case CONDITION_MOUSE_HOVER_ZONE:
_objects.resize(1);
break;
case CONDITION_MOUSE_OBJECT_HOVER_ZONE:
_objects.resize(2);
break;
case CONDITION_MOUSE_CLICK_FAILED:
case CONDITION_MOUSE_OBJECT_CLICK_FAILED:
case CONDITION_MOUSE_CLICK_EVENT:
case CONDITION_MOUSE_RIGHT_CLICK_EVENT:
break;
case CONDITION_MOUSE_OBJECT_CLICK_EVENT:
case CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT:
case CONDITION_MOUSE_STATE_PHRASE_CLICK:
_objects.resize(1);
break;
case CONDITION_OBJECT_IS_CLOSER:
_objects.resize(3);
break;
case CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE:
_objects.resize(1);
_data.resize(1);
init_data(0, qdConditionData::DATA_INT, 1);
break;
case CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS:
_objects.resize(2);
break;
}
}
bool qdCondition::put_value(int idx, const char *str) {
assert(idx >= 0 && idx < (int)_data.size());
return _data[idx].put_string(str);
}
bool qdCondition::put_value(int idx, int val, int val_index) {
assert(idx >= 0 && idx < (int)_data.size());
return _data[idx].put_int(val, val_index);
}
bool qdCondition::put_value(int idx, float val, int val_index) {
assert(idx >= 0 && idx < (int)_data.size());
return _data[idx].put_float(val, val_index);
}
bool qdCondition::get_value(int idx, const char *&str) const {
assert(idx >= 0 && idx < (int)_data.size());
if (_data[idx].get_string()) {
str = _data[idx].get_string();
return true;
}
return false;
}
bool qdCondition::get_value(int idx, int &val, int val_index) const {
assert(idx >= 0 && idx < (int)_data.size());
val = _data[idx].get_int(val_index);
return true;
}
bool qdCondition::get_value(int idx, float &val, int val_index) const {
assert(idx >= 0 && idx < (int)_data.size());
val = _data[idx].get_float(val_index);
return true;
}
bool qdCondition::load_script(const xml::tag *p) {
int data_idx = 0;
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_CONDITION_DATA_INT:
case QDSCR_CONDITION_DATA_FLOAT:
case QDSCR_CONDITION_DATA_STRING:
if (data_idx < (int)_data.size())
_data[data_idx++].load_script(&*it);
break;
case QDSCR_CONDITION_INVERSE:
if (xml::tag_buffer(*it).get_int())
inverse(true);
else
inverse(false);
break;
case QDSCR_CONDITION_OBJECT:
if (const xml::tag *tp = it->search_subtag(QDSCR_ID)) {
int object_idx = xml::tag_buffer(*tp).get_int();
if (object_idx >= 0 && object_idx < (int)_objects.size())
_objects[object_idx].load_script(&*it);
}
break;
}
}
return true;
}
bool qdCondition::save_script(Common::WriteStream &fh, int indent) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
if (debugChannelSet(-1, kDebugLog)) {
fh.writeString(Common::String::format("<condition type=\"%s\"", type2str(_type)));
} else {
fh.writeString(Common::String::format("<condition type=\"%d\"", _type));
}
if (is_inversed()) {
fh.writeString(" condition_inverse=\"1\"");
}
fh.writeString(">\r\n");
for (auto &it : _data) {
it.save_script(fh, indent + 1);
}
for (uint i = 0; i < _objects.size(); i++) {
if (_objects[i].object())
_objects[i].save_script(fh, indent + 1, i);
}
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString("</condition>\r\n");
return true;
}
void qdCondition::quant(float dt) {
debugC(9, kDebugQuant, "qdCondition::quant(%f)", dt);
if (_type == CONDITION_TIMER) {
float period, timer;
if (!get_value(TIMER_PERIOD, period, 0)) return;
if (!get_value(TIMER_PERIOD, timer, 1)) return;
timer += dt;
put_value(TIMER_PERIOD, timer, 1);
if (timer >= period) {
debugC(3, kDebugQuant, "qdCondition::quant() timer >= period");
timer -= period;
put_value(TIMER_PERIOD, timer, 1);
int rnd;
if (!get_value(TIMER_RND, rnd)) return;
int state = 1;
if (rnd && qd_rnd(100 - rnd))
state = 0;
put_value(TIMER_RND, state, 1);
} else
put_value(TIMER_RND, 0, 1);
}
}
bool qdCondition::load_data(Common::SeekableReadStream &fh, int save_version) {
debugC(5, kDebugSave, " qdCondition::load_data(): before: %d", (int)fh.pos());
if (_type == CONDITION_TIMER) {
int state;
float timer;
timer = fh.readFloatLE();
state = fh.readSint32LE();
if (!put_value(TIMER_PERIOD, timer, 1)) return false;
if (!put_value(TIMER_RND, state, 1)) return false;
}
debugC(5, kDebugSave, " qdCondition::load_data(): after: %d", (int)fh.pos());
return true;
}
bool qdCondition::save_data(Common::WriteStream &fh) const {
debugC(5, kDebugSave, " qdCondition::save_data(): before: %d", (int)fh.pos());
if (_type == CONDITION_TIMER) {
float timer;
if (!get_value(TIMER_PERIOD, timer, 1)) {
return false;
}
int state;
if (!get_value(TIMER_RND, state, 1)) {
return false;
}
fh.writeFloatLE(timer);
fh.writeSint32LE(state);
}
debugC(5, kDebugSave, " qdCondition::save_data(): after: %d", (int)fh.pos());
return true;
}
bool qdCondition::check() {
bool result = false;
if (qdGameDispatcher *dp = qdGameDispatcher::get_dispatcher()) {
if (dp->check_condition(this))
result = !_is_inversed;
else
result = _is_inversed;
}
if (result) {
if (is_click_condition())
_successful_click = true;
else if (is_object_click_condition())
_successful_object_click = true;
}
return result;
}
bool qdCondition::put_object(int idx, qdNamedObject *obj) {
assert(idx >= 0 && idx < (int)_objects.size());
_objects[idx].set_object(obj);
return true;
}
const qdNamedObject *qdCondition::get_object(int idx) {
if (idx >= 0 && idx < (int)_objects.size()) {
if (!_objects[idx].object())
_objects[idx].find_object();
return _objects[idx].object();
}
return NULL;
}
bool qdCondition::init() {
if (_type == CONDITION_TIMER) {
if (!put_value(TIMER_PERIOD, 0.0f, 1)) return false;
if (!put_value(TIMER_RND, 0, 1)) return false;
}
return true;
}
const char *types[] = {
"CONDITION_TRUE",
"CONDITION_FALSE",
"CONDITION_MOUSE_CLICK",
"CONDITION_MOUSE_OBJECT_CLICK",
"CONDITION_OBJECT_IN_ZONE",
"CONDITION_PERSONAGE_WALK_DIRECTION",
"CONDITION_PERSONAGE_STATIC_DIRECTION",
"CONDITION_TIMER",
"CONDITION_MOUSE_DIALOG_CLICK",
"CONDITION_MINIGAME_STATE",
"CONDITION_OBJECT_STATE",
"CONDITION_MOUSE_ZONE_CLICK",
"CONDITION_MOUSE_OBJECT_ZONE_CLICK",
"CONDITION_OBJECT_STATE_WAS_ACTIVATED",
"CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED",
"CONDITION_OBJECT_NOT_IN_STATE",
"CONDITION_OBJECTS_DISTANCE",
"CONDITION_PERSONAGE_ACTIVE",
"CONDITION_OBJECT_STATE_WAITING",
"CONDITION_OBJECT_STATE_ANIMATION_PHASE",
"CONDITION_OBJECT_PREV_STATE",
"CONDITION_STATE_TIME_GREATER_THAN_VALUE",
"CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME",
"CONDITION_STATE_TIME_IN_INTERVAL",
"CONDITION_COUNTER_GREATER_THAN_VALUE",
"CONDITION_COUNTER_LESS_THAN_VALUE",
"CONDITION_COUNTER_GREATER_THAN_COUNTER",
"CONDITION_COUNTER_IN_INTERVAL",
"CONDITION_OBJECT_ON_PERSONAGE_WAY",
"CONDITION_KEYPRESS",
"CONDITION_ANY_PERSONAGE_IN_ZONE",
"CONDITION_MOUSE_RIGHT_CLICK",
"CONDITION_MOUSE_RIGHT_OBJECT_CLICK",
"CONDITION_MOUSE_RIGHT_ZONE_CLICK",
"CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK",
"CONDITION_OBJECT_HIDDEN",
"CONDITION_MOUSE_HOVER",
"CONDITION_MOUSE_OBJECT_HOVER",
"CONDITION_MOUSE_HOVER_ZONE",
"CONDITION_MOUSE_OBJECT_HOVER_ZONE",
"CONDITION_MOUSE_CLICK_FAILED",
"CONDITION_MOUSE_OBJECT_CLICK_FAILED",
"CONDITION_MOUSE_CLICK_EVENT",
"CONDITION_MOUSE_OBJECT_CLICK_EVENT",
"CONDITION_MOUSE_RIGHT_CLICK_EVENT",
"CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT",
"CONDITION_MOUSE_STATE_PHRASE_CLICK",
"CONDITION_OBJECT_IS_CLOSER",
"CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE",
"CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS",
};
const char *qdCondition::type2str(uint type) {
if (type >= ARRAYSIZE(types))
return "???";
return types[type];
}
} // namespace QDEngine

View File

@@ -0,0 +1,598 @@
/* 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 QDENGINE_QDCORE_QD_CONDITION_H
#define QDENGINE_QDCORE_QD_CONDITION_H
#include "qdengine/parser/xml_fwd.h"
#include "qdengine/qdcore/qd_named_object.h"
#include "qdengine/qdcore/qd_condition_data.h"
#include "qdengine/qdcore/qd_condition_object_reference.h"
namespace Common {
class WriteStream;
}
namespace QDEngine {
//! Условие.
/**
Структура данных по типам условий.
Индексы для доступа к объектам (если они используются в условии)
совпадают с индексами для доступа к данным об именах объектов.
CONDITION_TRUE
CONDITION_FALSE
Данные: отсутствуют
CONDITION_MOUSE_CLICK
Данные:
string
Объекты:
qdGameObject
Индескы данных:
OBJECT_NAME
Имя объекта, по которому надо кликнуть.
Если пустое - проверяется клик по объекту, которому принадлежит
состояние, в котором выставлено это условие.
CONDITION_MOUSE_OBJECT_CLICK
Данные:
string, string
Объекты:
qdGameObject, qdGameObject
Индескы данных:
OBJECT_NAME, MOUSE_OBJECT_NAME
Имя объекта, по которому надо кликнуть
и имя объекта, который должен быть на мыши.
CONDITION_OBJECT_IN_ZONE
Данные:
string, string
Объекты:
qdGameObject, qdGridZone
Индескы данных:
OBJECT_NAME, ZONE_NAME
Имя объекта и имя зоны на сетке,
в которую он должен попасть.
CONDITION_PERSONAGE_WALK_DIRECTION
CONDITION_PERSONAGE_STATIC_DIRECTION
Данные:
string, float[1]
Объекты:
qdGameObjectMoving
Индескы данных:
PERSONAGE_NAME, DIRECTION_ANGLE
Имя персонажа и угол направления в радианах.
Угол задается так же, как и направления в походках
(т.е. от направления направо против часовой стрелки)
CONDITION_TIMER
Данные:
float[2], int[2]
Индескы данных:
TIMER_PERIOD, TIMER_RND
Период и текущее время таймера в секундах,
вероятность выполнения условия по истечении времени
таймера в процентах и текущее состояние условия.
CONDITION_MOUSE_DIALOG_CLICK
Данные: отсутствуют
CONDITION_MINIGAME_STATE
Данные:
string, string
Объекты:
qdMiniGame
Индескы данных:
MINIGAME_NAME, MINIGAME_STATE_NAME
Имя мини-игры и имя состояния, в котором она должна находиться
для выполнения условия.
CONDITION_OBJECT_STATE
Данные:
string, string
Объекты:
qdGameObjectAnimated, qdGameObjectState
Индескы данных:
OBJECT_NAME, OBJECT_STATE_NAME
Имя объекта и имя состояния, в котором он должен находиться
для выполнения условия.
CONDITION_MOUSE_ZONE_CLICK
Данные:
string
Объекты:
qdGridZone
Индескы данных:
CLICK_ZONE_NAME
Имя зоны на сетке,
в которую надо кликнуть.
CONDITION_MOUSE_OBJECT_ZONE_CLICK
Данные:
string, string
Объекты:
qdGridZone, qdGameObject
Индескы данных:
CLICK_ZONE_NAME, MOUSE_OBJECT_NAME
Имя зоны на сетке, в которую надо кликнуть
и имя объекта, который должен быть на мыши.
CONDITION_OBJECT_STATE_WAS_ACTIVATED
CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED
Данные:
string, string
Объекты:
qdGameObjectAnimated, qdGameObjectState
Индескы данных:
OBJECT_NAME, OBJECT_STATE_NAME
Имя объекта и имя состояния.
CONDITION_OBJECT_NOT_IN_STATE
см. CONDITION_OBJECT_STATE
CONDITION_OBJECTS_DISTANCE
Данные:
string, string, float
Объекты:
qdGameObject, qdGameObject
Индескы данных:
OBJECT_NAME, OBJECT2_NAME, OBJECTS_DISTANCE
Имена объектов и расстояние по сетке.
CONDITION_PERSONAGE_ACTIVE
Данные:
string
Объекты:
qdGameObjectMoving
Индескы данных:
PERSONAGE_NAME
Имя персонажа, который должен быть активным
для выполнения условия.
CONDITION_OBJECT_STATE_WAITING
Данные:
string, string
Объекты:
qdGameObjectAnimated, qdGameObjectState
Индескы данных:
OBJECT_NAME, OBJECT_STATE_NAME
Имя объекта и имя состояния.
CONDITION_OBJECT_STATE_ANIMATION_PHASE
Данные:
string, string, float[2]
Объекты:
qdGameObjectAnimated, qdGameObjectState
Индескы данных:
OBJECT_NAME, OBJECT_STATE_NAME, ANIMATION_PHASE
Имя объекта, имя состояния и диапазон фазы анимации.
CONDITION_OBJECT_PREV_STATE
Данные:
string, string
Объекты:
qdGameObjectAnimated, qdGameObjectState
Индескы данных:
OBJECT_NAME, OBJECT_STATE_NAME
Имя объекта и имя состояния.
CONDITION_STATE_TIME_GREATER_THAN_VALUE
Данные:
float
Время работы состояния.
Объекты:
qdGameObjectState
CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME
Данные: отсутствуют
Объекты:
qdGameObjectState, qdGameObjectState
Состояния, время работы которых сравнивается.
CONDITION_STATE_TIME_IN_INTERVAL
Данные:
float[2]
Интервал, в котором должно находиться ремя работы состояния.
Объекты:
qdGameObjectState
CONDITION_COUNTER_GREATER_THAN_VALUE
CONDITION_COUNTER_LESS_THAN_VALUE
Данные:
int
Число, с которым сравнивается значение счетчика.
Объекты:
qdCounter
CONDITION_COUNTER_GREATER_THAN_COUNTER
Данные: отсутствуют
Объекты:
qdCounter, qdCounter
Счетчики, значения которых сравнивается.
CONDITION_COUNTER_IN_INTERVAL
Данные:
int[2]
Интервал, в котором должно находиться значение счетчика.
Объекты:
qdCounter
CONDITION_OBJECT_ON_PERSONAGE_WAY
Данные:
float[1]
Максимальное расстояние между объектам и персонажем по сетке.
Объекты:
qdGameObjectMoving, qdGameObject
CONDITION_KEYPRESS
Данные:
int[1]
vkey кнопки.
CONDITION_ANY_PERSONAGE_IN_ZONE
Объекты:
qdGridZone
CONDITION_MOUSE_RIGHT_CLICK
Объекты:
qdGameObject
Индескы данных:
OBJECT_NAME
Объект, по которому надо кликнуть.
Если нулевой - проверяется клик по объекту, которому принадлежит
состояние, в котором выставлено это условие.
CONDITION_MOUSE_RIGHT_OBJECT_CLICK
Объекты:
qdGameObject, qdGameObject
Индескы данных:
OBJECT_NAME, MOUSE_OBJECT_NAME
Объект, по которому надо кликнуть
и объект, который должен быть на мыши.
CONDITION_MOUSE_RIGHT_ZONE_CLICK
Объекты:
qdGridZone
Индескы данных:
CLICK_ZONE_NAME
Зона на сетке,
в которую надо кликнуть.
CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK
Объекты:
qdGridZone, qdGameObject
Индескы данных:
CLICK_ZONE_NAME, MOUSE_OBJECT_NAME
Зона на сетке, в которую надо кликнуть
и объект, который должен быть на мыши.
CONDITION_OBJECT_HIDDEN
Объекты:
qdGameObject
Объект, который должен быть скрыт
CONDITION_MOUSE_HOVER
Объекты:
qdGameObject
Объект, на который наводится мышь
CONDITION_MOUSE_OBJECT_HOVER
Объекты:
qdGameObject, qdGameObject
Объект, на который наводится мышь,
объект который на мыши
CONDITION_MOUSE_HOVER_ZONE
Объекты:
qdGridZone
Зона, на которую наводится мышь
CONDITION_MOUSE_OBJECT_HOVER_ZONE
Объекты:
qdGridZone, qdGameObject
Зона, на которую наводится мышь,
объект который на мыши
CONDITION_MOUSE_CLICK_FAILED
CONDITION_MOUSE_OBJECT_CLICK_FAILED
CONDITION_MOUSE_CLICK_EVENT
//CONDITION_MOUSE_OBJECT_CLICK_EVENT
CONDITION_MOUSE_RIGHT_CLICK_EVENT
//CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT
Данных нет.
CONDITION_MOUSE_OBJECT_CLICK_EVENT
CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT
Объекты:
qdGameObject
Объект, которым надо кликнуть для выполнения условия.
Если нулевй, то достаточно клика любым объектом.
CONDITION_MOUSE_STATE_PHRASE_CLICK
Объекты:
qdGameObjecState
Состояние, по фразе которого надо кликнуть.
CONDITION_OBJECT_IS_CLOSER
Объекты:
qdGameObject, qdGameObject, qdGameObject
Расстояние от первого объекта до второго должно быть меньше,
чем расстояние от первого до третьего.
CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE
Объекты:
qdGameObjectAnimated, int
Анимированный объект, который простаивает, и порог времени,
который должен быть превышен временем ожидания заданного объекта.
CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS
Объекты:
qdGameObjectAnimated, qdGameObjectAnimated
Два объекта, баунды которых пероверяются на пересечение.
*/
class qdCondition {
public:
//! Типы условий.
enum ConditionType {
//! всегда true
CONDITION_TRUE,
//! всегда false
CONDITION_FALSE,
//! клик мышью по объекту
CONDITION_MOUSE_CLICK,
//! клик объектом на мыши по объекту
CONDITION_MOUSE_OBJECT_CLICK,
//! персонаж или объект в определенном месте сетки
CONDITION_OBJECT_IN_ZONE,
//! персонаж движется в определенном направлении
CONDITION_PERSONAGE_WALK_DIRECTION, // 5
//! персонаж стоит и ориентирован в определенном направлении
CONDITION_PERSONAGE_STATIC_DIRECTION,
//! условие выпоняется с некоторой периодичностью
CONDITION_TIMER,
//! клик мышью по фразе в диалоге
CONDITION_MOUSE_DIALOG_CLICK,
//! мини-игра находится в определенном состоянии
CONDITION_MINIGAME_STATE,
//! объект находится в определенном состоянии
CONDITION_OBJECT_STATE, // 10
//! клик мышью по зоне на сетке сцены
CONDITION_MOUSE_ZONE_CLICK,
//! клик объектом по зоне на сетке сцены
CONDITION_MOUSE_OBJECT_ZONE_CLICK,
//! состояние объекта активировалось
CONDITION_OBJECT_STATE_WAS_ACTIVATED,
//! состояние объекта не активировалось
CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED,
//! объект не находится в определенном состоянии
CONDITION_OBJECT_NOT_IN_STATE, // 15
//! расстояние по сетке между двумя объектами меньше заданного
CONDITION_OBJECTS_DISTANCE,
//! персонаж активен
CONDITION_PERSONAGE_ACTIVE,
//! состояние объекта ждет активации
CONDITION_OBJECT_STATE_WAITING,
//! состояние в определенной фазе анимации
CONDITION_OBJECT_STATE_ANIMATION_PHASE,
//! предыдущее состояние объекта
CONDITION_OBJECT_PREV_STATE, // 20
//! время работы состояния больше значения
CONDITION_STATE_TIME_GREATER_THAN_VALUE,
//! время работы одного состояния больше времени работы другого
CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME,
//! время работы состояния в интервале
CONDITION_STATE_TIME_IN_INTERVAL,
//! значние счетчика больше числа
CONDITION_COUNTER_GREATER_THAN_VALUE,
//! значние счетчика меньше числа
CONDITION_COUNTER_LESS_THAN_VALUE, // 25
//! значние счетчика больше значения другого счетчика
CONDITION_COUNTER_GREATER_THAN_COUNTER,
//! значние счетчика в интервале
CONDITION_COUNTER_IN_INTERVAL,
//! объект на пути персонажа
CONDITION_OBJECT_ON_PERSONAGE_WAY,
//! кнопка нажата
CONDITION_KEYPRESS,
//! в зоне хотя бы один персонаж
CONDITION_ANY_PERSONAGE_IN_ZONE, // 30
//! правый клик мыши по объекту
CONDITION_MOUSE_RIGHT_CLICK,
//! правый клик объектом на мыши по объекту
CONDITION_MOUSE_RIGHT_OBJECT_CLICK,
//! правый клик мышью по зоне на сетке сцены
CONDITION_MOUSE_RIGHT_ZONE_CLICK,
//! правый клик объектом по зоне на сетке сцены
CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK,
//! объект скрыт
CONDITION_OBJECT_HIDDEN, // 35
//! мышь наведена на объект
CONDITION_MOUSE_HOVER,
//! мышь наведена на объект, на мыши объект
CONDITION_MOUSE_OBJECT_HOVER,
//! мышь наведена на зону
CONDITION_MOUSE_HOVER_ZONE,
//! мышь наведена на зону, на мыши объект
CONDITION_MOUSE_OBJECT_HOVER_ZONE,
//! неудачный клик мыши
CONDITION_MOUSE_CLICK_FAILED, // 40
//! неудачный клик объектом на мыши
CONDITION_MOUSE_OBJECT_CLICK_FAILED,
//! был клик мыши
CONDITION_MOUSE_CLICK_EVENT,
//! был клик объектом на мыши
CONDITION_MOUSE_OBJECT_CLICK_EVENT,
//! был клик правой кнопкой мыши
CONDITION_MOUSE_RIGHT_CLICK_EVENT,
//! был клик правой кнопкой объектом на мыши
CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT, // 45
//! клик по фразе определённого состояния
CONDITION_MOUSE_STATE_PHRASE_CLICK,
//! расстояние до одного объекта меньше чем до другого
CONDITION_OBJECT_IS_CLOSER,
//! время простоя больше заданного порога
CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE,
//! баунды двух объектов пересекаются
CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS,
};
//! Индексы для обращения к данным в условиях.
enum ConditionDataIndex {
OBJECT_NAME = 0,
MOUSE_OBJECT_NAME = 1,
ZONE_NAME = 1,
DIRECTION_ANGLE = 1,
PERSONAGE_NAME = 0,
TIMER_PERIOD = 0,
TIMER_RND = 1,
MINIGAME_NAME = 0,
MINIGAME_STATE_NAME = 1,
OBJECT_STATE_NAME = 1,
CLICK_ZONE_NAME = 0,
OBJECT2_NAME = 1,
OBJECTS_DISTANCE = 2,
ANIMATION_PHASE = 2,
STATE_TIME = 2
};
qdCondition();
qdCondition(ConditionType tp);
qdCondition(const qdCondition &cnd);
~qdCondition();
qdCondition &operator = (const qdCondition &cnd);
ConditionType type() const {
return _type;
}
void set_type(ConditionType tp);
static const char *type2str(uint type);
bool put_value(int idx, const char *str);
bool is_click_condition() const {
return (_type == CONDITION_MOUSE_CLICK || _type == CONDITION_MOUSE_DIALOG_CLICK || _type == CONDITION_MOUSE_ZONE_CLICK);
}
bool is_object_click_condition() const {
return (_type == CONDITION_MOUSE_OBJECT_CLICK || _type == CONDITION_MOUSE_OBJECT_ZONE_CLICK);
}
// val_index - индекс, по которому пропишется значение
// в qdConditionDataInt::_data или qdConditionDataFloat::_data
bool put_value(int idx, int val, int val_index = 0);
bool put_value(int idx, float val, int val_index = 0);
bool get_value(int idx, const char *&str) const;
bool get_value(int idx, int &val, int val_index = 0) const;
bool get_value(int idx, float &val, int val_index = 0) const;
bool put_object(int idx, qdNamedObject *obj);
const qdNamedObject *get_object(int idx) ;
const qdNamedObject *owner() const {
return _owner;
}
void set_owner(const qdNamedObject *p) {
_owner = p;
}
bool load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
void quant(float dt);
//! Загрузка данных из сэйва.
bool load_data(Common::SeekableReadStream &fh, int save_version);
//! Запись данных в сэйв.
bool save_data(Common::WriteStream &fh) const;
//! Инициализация условия, вызывается при старте и перезапуске игры.
bool init();
bool is_inversed() const {
return _is_inversed;
}
void inverse(bool inverse_mode = true) {
_is_inversed = inverse_mode;
}
bool check();
bool is_in_group() const {
return _is_in_group;
}
void add_group_reference() {
_is_in_group = true;
}
void remove_group_reference() {
_is_in_group = false;
}
static bool successful_click() {
return _successful_click;
}
static bool successful_object_click() {
return _successful_object_click;
}
static void clear_successful_clicks() {
_successful_click = _successful_object_click = false;
}
private:
ConditionType _type;
const qdNamedObject *_owner = nullptr;
typedef Std::vector<qdConditionData> data_container_t;
data_container_t _data;
typedef Std::vector<qdConditionObjectReference> objects_container_t;
objects_container_t _objects;
bool _is_inversed;
bool _is_in_group;
static bool _successful_click;
static bool _successful_object_click;
bool init_data(int data_index, qdConditionData::data_t data_type, int data_size = 0) {
assert(data_index >= 0 && data_index < (int)_data.size());
_data[data_index].set_type(data_type);
if (data_size)
_data[data_index].alloc_data(data_size);
return true;
}
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CONDITION_H

View File

@@ -0,0 +1,127 @@
/* 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 "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/qdcore/qd_condition_data.h"
namespace QDEngine {
qdConditionData::qdConditionData() : _type(DATA_STRING) {
}
qdConditionData::qdConditionData(data_t data_type, int data_size) : _type(data_type) {
if (data_size)
alloc_data(data_size);
}
qdConditionData::qdConditionData(const qdConditionData &data) : _type(data._type),
_data(data._data) {
}
qdConditionData::~qdConditionData() {
}
qdConditionData &qdConditionData::operator = (const qdConditionData &data) {
if (this == &data) return *this;
_type = data._type;
_data = data._data;
return *this;
}
bool qdConditionData::alloc_data(int size) {
switch (_type) {
case DATA_INT:
size *= sizeof(int);
break;
case DATA_FLOAT:
size *= sizeof(float);
break;
case DATA_STRING:
size++;
break;
}
if ((int)_data.size() < size)
_data.resize(size);
return true;
}
bool qdConditionData::load_script(const xml::tag *p) {
switch (_type) {
case DATA_INT: {
xml::tag_buffer buf(*p);
for (int i = 0; i < p->data_size(); i++)
put_int(buf.get_int(), i);
}
break;
case DATA_FLOAT: {
xml::tag_buffer buf(*p);
for (int i = 0; i < p->data_size(); i++)
put_float(buf.get_float(), i);
}
break;
case DATA_STRING:
put_string(p->data());
break;
}
return true;
}
bool qdConditionData::save_script(Common::WriteStream &fh, int indent) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
switch (_type) {
case DATA_INT:
fh.writeString(Common::String::format("<condition_data_int>%lu", _data.size() / sizeof(int32)));
for (uint i = 0; i < _data.size() / sizeof(int32); i++) {
fh.writeString(Common::String::format(" %d", get_int(i)));
}
fh.writeString("</condition_data_int>\r\n");
break;
case DATA_FLOAT:
fh.writeString(Common::String::format("<condition_data_float>%lu", _data.size() / sizeof(float)));
for (uint i = 0; i < _data.size() / sizeof(float); i++) {
fh.writeString(Common::String::format(" %f", get_float(i)));
}
fh.writeString("</condition_data_float>\r\n");
break;
case DATA_STRING:
fh.writeString("<condition_data_string>");
if (!_data.empty()) {
fh.writeString(Common::String::format("%s", qdscr_XML_string(&*_data.begin())));
}
fh.writeString("</condition_data_string>\r\n");
break;
}
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,107 @@
/* 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 QDENGINE_QDCORE_QD_CONDITION_DATA_H
#define QDENGINE_QDCORE_QD_CONDITION_DATA_H
#include "common/std/vector.h"
#include "qdengine/parser/xml_fwd.h"
namespace QDEngine {
class qdConditionData {
public:
enum data_t {
DATA_INT,
DATA_FLOAT,
DATA_STRING
};
qdConditionData();
qdConditionData(data_t data_type, int data_size = 0);
qdConditionData(const qdConditionData &data);
~qdConditionData();
qdConditionData &operator = (const qdConditionData &data);
data_t type() const {
return _type;
}
void set_type(data_t tp) {
_type = tp;
}
int get_int(int index = 0) const {
return reinterpret_cast<const int32 *>(&*_data.begin())[index];
}
bool put_int(int value, int index = 0) {
if (static_cast<int>(_data.size()) >= static_cast<int>((index - 1) * sizeof(int32))) {
reinterpret_cast<int32 *>(&*_data.begin())[index] = value;
return true;
}
return false;
}
float get_float(int index = 0) const {
return reinterpret_cast<const float *>(&*_data.begin())[index];
}
bool put_float(float value, int index = 0) {
if (static_cast<int>(_data.size()) >=
static_cast<int>((index - 1) * sizeof(float))) {
reinterpret_cast<float *>(&*_data.begin())[index] = value;
return true;
}
return false;
}
const char *get_string() const {
if (!_data.empty())
return &*_data.begin();
else
return NULL;
}
bool put_string(const char *str) {
if (alloc_data(strlen(str) + 1)) {
Common::strlcpy(&*_data.begin(), str, _data.size());
return true;
}
return false;
}
bool load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
bool alloc_data(int size);
private:
data_t _type;
Std::vector<char> _data;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CONDITION_DATA_H

View File

@@ -0,0 +1,107 @@
/* 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/debug.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/parser/xml_tag_buffer.h"
#include "qdengine/qdcore/qd_condition_group.h"
namespace QDEngine {
qdConditionGroup::qdConditionGroup(conditions_mode_t md) : _conditions_mode(md) {
}
qdConditionGroup::qdConditionGroup(const qdConditionGroup &cg) : _conditions_mode(cg._conditions_mode), _conditions(cg._conditions) {
}
qdConditionGroup::~qdConditionGroup() {
}
qdConditionGroup &qdConditionGroup::operator = (const qdConditionGroup &cg) {
if (this == &cg) return *this;
_conditions_mode = cg._conditions_mode;
_conditions = cg._conditions;
return *this;
}
bool qdConditionGroup::add_condition(int condition_id) {
conditions_container_t::iterator it = Common::find(_conditions.begin(), _conditions.end(), condition_id);
if (it != _conditions.end())
return false;
_conditions.push_back(condition_id);
return true;
}
bool qdConditionGroup::remove_condition(int condition_id) {
for (conditions_container_t::iterator it = _conditions.begin(); it != _conditions.end(); ++it) {
if (*it > condition_id)
(*it)--;
}
conditions_container_t::iterator it1 = Common::find(_conditions.begin(), _conditions.end(), condition_id);
if (it1 != _conditions.end())
return false;
_conditions.erase(it1);
return true;
}
bool qdConditionGroup::load_script(const xml::tag *p) {
_conditions.reserve(p->data_size());
if (const xml::tag *tp = p->search_subtag(QDSCR_TYPE))
_conditions_mode = conditions_mode_t(xml::tag_buffer(*tp).get_int());
xml::tag_buffer buf(*p);
for (int i = 0; i < p->data_size(); i++)
_conditions.push_back(buf.get_int());
return true;
}
bool qdConditionGroup::save_script(Common::WriteStream &fh, int indent) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString("<condition_group");
if (debugChannelSet(-1, kDebugLog))
fh.writeString(Common::String::format(" type=\"%s\"", _conditions_mode == CONDITIONS_AND ? "CONDITIONS_AND" : "CONDITIONS_OR"));
else
fh.writeString(Common::String::format(" type=\"%d\"", (int)_conditions_mode));
fh.writeString(">");
fh.writeString(Common::String::format("%u", _conditions.size()));
for (auto &it : _conditions) {
fh.writeString(Common::String::format(" %d", it));
}
fh.writeString("</condition_group>\r\n");
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,84 @@
/* 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 QDENGINE_QDCORE_QD_CONDITION_GROUP_H
#define QDENGINE_QDCORE_QD_CONDITION_GROUP_H
#include "qdengine/parser/xml_fwd.h"
namespace QDEngine {
//! Группа условий.
class qdConditionGroup {
public:
//! Режим проверки условий.
enum conditions_mode_t {
//! "И" - должны выполниться все условия.
CONDITIONS_AND,
//! "ИЛИ" - достаточно выполнения одного из условий.
CONDITIONS_OR
};
explicit qdConditionGroup(conditions_mode_t md = CONDITIONS_AND);
qdConditionGroup(const qdConditionGroup &cg);
qdConditionGroup &operator = (const qdConditionGroup &cg);
~qdConditionGroup();
typedef Std::vector<int> conditions_container_t;
typedef conditions_container_t::const_iterator conditions_iterator_t;
conditions_iterator_t conditions_begin() const {
return _conditions.begin();
}
conditions_iterator_t conditions_end() const {
return _conditions.end();
}
int conditions_size() const {
return _conditions.size();
}
conditions_mode_t conditions_mode() const {
return _conditions_mode;
}
void set_conditions_mode(conditions_mode_t mode) {
_conditions_mode = mode;
}
bool add_condition(int condition_id);
bool remove_condition(int condition_id);
bool load_script(const xml::tag *p);
bool save_script(Common::WriteStream &fh, int indent = 0) const;
private:
conditions_mode_t _conditions_mode;
conditions_container_t _conditions;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CONDITION_GROUP_H

View 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/>.
*
*/
#include "qdengine/qd_fwd.h"
#include "qdengine/parser/xml_tag.h"
#include "qdengine/parser/qdscr_parser.h"
#include "qdengine/qdcore/qd_game_dispatcher.h"
#include "qdengine/qdcore/qd_named_object_indexer.h"
#include "qdengine/qdcore/qd_condition_object_reference.h"
namespace QDEngine {
qdConditionObjectReference::qdConditionObjectReference() : _object(NULL) {
}
qdConditionObjectReference::qdConditionObjectReference(const qdConditionObjectReference &ref) :
_object(ref._object) {
}
qdConditionObjectReference::~qdConditionObjectReference() {
}
qdConditionObjectReference &qdConditionObjectReference::operator = (const qdConditionObjectReference &ref) {
if (this == &ref) return *this;
_object = ref._object;
return *this;
}
void qdConditionObjectReference::set_object(qdNamedObject *p) {
_object = p;
}
bool qdConditionObjectReference::find_object() {
return false;
}
bool qdConditionObjectReference::load_script(const xml::tag *p) {
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_NAMED_OBJECT: {
qdNamedObjectReference &ref = qdNamedObjectIndexer::instance().add_reference((qdNamedObject *&)_object);
ref.load_script(&*it);
}
break;
}
}
return true;
}
bool qdConditionObjectReference::save_script(Common::WriteStream &fh, int indent, int id) const {
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString(Common::String::format("<condition_object ID=\"%d\">\r\n", id));
if (_object) {
qdNamedObjectReference ref(_object);
ref.save_script(fh, indent + 1);
}
for (int i = 0; i < indent; i++) {
fh.writeString("\t");
}
fh.writeString("</condition_object>\r\n");
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,66 @@
/* 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 QDENGINE_QDCORE_QD_CONDITION_OBJECT_REFERENCE_H
#define QDENGINE_QDCORE_QD_CONDITION_OBJECT_REFERENCE_H
#include "qdengine/parser/xml_fwd.h"
#include "qdengine/qdcore/qd_named_object_reference.h"
namespace QDEngine {
class qdNamedObject;
class qdConditionObjectReference {
public:
qdConditionObjectReference();
qdConditionObjectReference(const qdConditionObjectReference &ref);
~qdConditionObjectReference();
qdConditionObjectReference &operator = (const qdConditionObjectReference &ref);
void set_object(qdNamedObject *p);
bool find_object();
const qdNamedObject *object() const {
return _object;
}
bool is_empty() const {
if (_object) return true;
else return false;
}
//! Загрузка данных из скрипта.
bool load_script(const xml::tag *p);
//! Запись данных в скрипт.
bool save_script(Common::WriteStream &fh, int indent = 0, int id = 0) const;
private:
qdNamedObject *_object;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_QD_CONDITION_OBJECT_REFERENCE_H

Some files were not shown because too many files have changed in this diff Show More