Initial commit
This commit is contained in:
61
engines/ultima/shared/actions/action.cpp
Normal file
61
engines/ultima/shared/actions/action.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/actions/action.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Actions {
|
||||
|
||||
Action::Action(TreeItem *parent) : TreeItem() {
|
||||
assert(parent);
|
||||
addUnder(parent);
|
||||
}
|
||||
|
||||
Game *Action::getGame() {
|
||||
return static_cast<Game *>(TreeItem::getGame());
|
||||
}
|
||||
|
||||
Maps::Map *Action::getMap() {
|
||||
return static_cast<Maps::Map *>(getGame()->getMap());
|
||||
}
|
||||
|
||||
void Action::addInfoMsg(const Common::String &text, bool newLine, bool replaceLine) {
|
||||
CInfoMsg msg(text, newLine, replaceLine);
|
||||
msg.execute(getView());
|
||||
}
|
||||
|
||||
void Action::playFX(uint effectId) {
|
||||
getGame()->playFX(effectId);
|
||||
}
|
||||
|
||||
void Action::endOfTurn() {
|
||||
getGame()->endOfTurn();
|
||||
}
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
85
engines/ultima/shared/actions/action.h
Normal file
85
engines/ultima/shared/actions/action.h
Normal 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 ULTIMA_SHARED_ACTIONS_ACTION_H
|
||||
#define ULTIMA_SHARED_ACTIONS_ACTION_H
|
||||
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
|
||||
namespace Maps {
|
||||
class Map;
|
||||
}
|
||||
|
||||
namespace Actions {
|
||||
|
||||
/**
|
||||
* Base class for implementing the various actions the player can do, such as moving, climbing, entering, etc.
|
||||
*/
|
||||
class Action : public TreeItem {
|
||||
protected:
|
||||
/**
|
||||
* Signals the end of the turn
|
||||
*/
|
||||
void endOfTurn();
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Action(TreeItem *parent);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Action() override {}
|
||||
|
||||
/**
|
||||
* Jumps up through the parents to find the root game
|
||||
*/
|
||||
Game *getGame();
|
||||
|
||||
/**
|
||||
* Return the game's map
|
||||
*/
|
||||
Maps::Map *getMap();
|
||||
|
||||
/**
|
||||
* Adds a text string to the info area
|
||||
* @param text Text to add
|
||||
* @param newLine Whether to apply a newline at the end
|
||||
*/
|
||||
void addInfoMsg(const Common::String &text, bool newLine = true, bool replaceLine = false);
|
||||
|
||||
/**
|
||||
* Play a sound effect
|
||||
*/
|
||||
void playFX(uint effectId);
|
||||
};
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
40
engines/ultima/shared/actions/huh.cpp
Normal file
40
engines/ultima/shared/actions/huh.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/actions/huh.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Actions {
|
||||
|
||||
BEGIN_MESSAGE_MAP(Huh, Action)
|
||||
ON_MESSAGE(HuhMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
bool Huh::HuhMsg(CHuhMsg *msg) {
|
||||
addInfoMsg(_text);
|
||||
endOfTurn();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
55
engines/ultima/shared/actions/huh.h
Normal file
55
engines/ultima/shared/actions/huh.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ACTIONS_HUH_H
|
||||
#define ULTIMA_SHARED_ACTIONS_HUH_H
|
||||
|
||||
#include "ultima/shared/actions/action.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Actions {
|
||||
|
||||
class Huh : public Action {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool HuhMsg(CHuhMsg *msg);
|
||||
private:
|
||||
const char *&_text;
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Huh(TreeItem *parent, const char *&text) : Action(parent), _text(text) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Huh() override {}
|
||||
};
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
40
engines/ultima/shared/actions/pass.cpp
Normal file
40
engines/ultima/shared/actions/pass.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/actions/pass.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Actions {
|
||||
|
||||
BEGIN_MESSAGE_MAP(Pass, Action)
|
||||
ON_MESSAGE(PassMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
bool Pass::PassMsg(CPassMsg *msg) {
|
||||
addInfoMsg(_text);
|
||||
endOfTurn();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
55
engines/ultima/shared/actions/pass.h
Normal file
55
engines/ultima/shared/actions/pass.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ACTIONS_PASS_H
|
||||
#define ULTIMA_SHARED_ACTIONS_PASS_H
|
||||
|
||||
#include "ultima/shared/actions/action.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Actions {
|
||||
|
||||
class Pass : public Action {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool PassMsg(CPassMsg *msg);
|
||||
private:
|
||||
const char *&_text;
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pass(TreeItem *parent, const char *&text) : Action(parent), _text(text) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Pass() override {}
|
||||
};
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
101
engines/ultima/shared/conf/conf_serializer.h
Normal file
101
engines/ultima/shared/conf/conf_serializer.h
Normal 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 SHARED_CONF_CONF_SERIALIZER_H
|
||||
#define SHARED_CONF_CONF_SERIALIZER_H
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* A simplified serializer class for reading/writing stuff from ConfMan
|
||||
*/
|
||||
class ConfSerializer {
|
||||
private:
|
||||
bool _isSaving;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ConfSerializer(bool saving) : _isSaving(saving) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ConfSerializer() {
|
||||
if (_isSaving)
|
||||
ConfMan.flushToDisk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if saving
|
||||
*/
|
||||
bool isSaving() const {
|
||||
return _isSaving;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if loading
|
||||
*/
|
||||
bool isLoading() const {
|
||||
return !_isSaving;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs a string
|
||||
*/
|
||||
void syncAsString(const Common::String &key, Common::String &value,
|
||||
const char *defaultValue = nullptr) {
|
||||
if (_isSaving)
|
||||
ConfMan.set(key, value);
|
||||
else
|
||||
value = ConfMan.hasKey(key) ? ConfMan.get(key) : Common::String(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs a boolean
|
||||
*/
|
||||
void syncAsBool(const Common::String &key, bool &value,
|
||||
bool defaultValue = false) {
|
||||
if (_isSaving)
|
||||
ConfMan.setBool(key, value);
|
||||
else
|
||||
value = ConfMan.hasKey(key) ? ConfMan.getBool(key) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs an integer
|
||||
*/
|
||||
template<typename T>
|
||||
void syncAsInt(const Common::String &key, T &value, T defaultValue = 0) {
|
||||
if (_isSaving)
|
||||
ConfMan.setInt(key, value);
|
||||
else
|
||||
value = ConfMan.hasKey(key) ? ConfMan.getInt(key) : defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
550
engines/ultima/shared/conf/xml_node.cpp
Normal file
550
engines/ultima/shared/conf/xml_node.cpp
Normal file
@@ -0,0 +1,550 @@
|
||||
/* 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 "ultima/shared/conf/xml_node.h"
|
||||
#include "ultima/shared/conf/xml_tree.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
XMLNode::~XMLNode() {
|
||||
for (auto *node : _nodeList) {
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
const Common::String &XMLNode::reference(const Common::String &h, bool &exists) {
|
||||
if (h.find('/') == Common::String::npos) {
|
||||
// Must refer to me.
|
||||
if (_id == h) {
|
||||
exists = true;
|
||||
return _text;
|
||||
}
|
||||
} else {
|
||||
// Otherwise we want to split the Common::String at the first /
|
||||
// then locate the branch to walk, and pass the rest
|
||||
// down.
|
||||
|
||||
Common::String k;
|
||||
k = h.substr(h.find('/') + 1);
|
||||
Common::String k2 = k.substr(0, k.find('/'));
|
||||
for (auto *node : _nodeList) {
|
||||
if (node->_id == k2)
|
||||
return node->reference(k, exists);
|
||||
}
|
||||
}
|
||||
|
||||
exists = false;
|
||||
return _emptyString;
|
||||
}
|
||||
|
||||
|
||||
const XMLNode *XMLNode::subtree(const Common::String &h) const {
|
||||
if (h.find('/') == Common::String::npos) {
|
||||
// Must refer to me.
|
||||
if (_id.equalsIgnoreCase(h))
|
||||
return this;
|
||||
} else {
|
||||
// Otherwise we want to split the Common::String at the first /
|
||||
// then locate the branch to walk, and pass the rest
|
||||
// down.
|
||||
|
||||
Common::String k;
|
||||
k = h.substr(h.find('/') + 1);
|
||||
Common::String k2 = k.substr(0, k.find('/'));
|
||||
for (auto *node : _nodeList) {
|
||||
if (node->_id.equalsIgnoreCase(k2)) {
|
||||
return node->subtree(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Common::String XMLNode::dump(int depth) {
|
||||
Common::String s;
|
||||
for (int i = 0; i < depth; ++i)
|
||||
s += ' ';
|
||||
|
||||
s += "<";
|
||||
s += _id;
|
||||
s += ">";
|
||||
if (_id[_id.size() - 1] != '/') {
|
||||
if (_nodeList.empty() == false)
|
||||
s += "\n";
|
||||
for (auto *node : _nodeList) {
|
||||
s += node->dump(depth + 1);
|
||||
}
|
||||
|
||||
if (!_text.empty()) {
|
||||
//s += Common::String(depth,' ');
|
||||
s += encodeEntity(_text);
|
||||
}
|
||||
if (_id[0] == '?') {
|
||||
return s;
|
||||
}
|
||||
//if(_content.size())
|
||||
// s += "\n";
|
||||
|
||||
if (!_noClose) {
|
||||
if (_text.empty()) {
|
||||
for (int i = 0; i < depth; ++i)
|
||||
s += ' ';
|
||||
}
|
||||
|
||||
s += "</";
|
||||
s += closeTag(_id);
|
||||
s += ">\n";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void XMLNode::xmlAssign(const Common::String &key, const Common::String &value) {
|
||||
if (key.find('/') == Common::String::npos) {
|
||||
// Must refer to me.
|
||||
if (_id == key)
|
||||
_text = value;
|
||||
else
|
||||
error("Walking the XML tree failed to create a final node.");
|
||||
return;
|
||||
}
|
||||
Common::String k;
|
||||
k = key.substr(key.find('/') + 1);
|
||||
Common::String k2 = k.substr(0, k.find('/'));
|
||||
for (auto *node : _nodeList) {
|
||||
if (node->_id == k2) {
|
||||
node->xmlAssign(k, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No match, so create a new node and do recursion
|
||||
XMLNode *t = new XMLNode(_tree);
|
||||
t->_parent = this;
|
||||
t->_id = k2;
|
||||
_nodeList.push_back(t);
|
||||
(*t).xmlAssign(k, value);
|
||||
}
|
||||
|
||||
|
||||
void XMLNode::listKeys(const Common::String &key, Common::Array<Common::String> &vs,
|
||||
bool longformat) const {
|
||||
Common::String s(key);
|
||||
s += "/";
|
||||
|
||||
for (auto *node : _nodeList) {
|
||||
if (!longformat)
|
||||
vs.push_back(node->_id);
|
||||
else
|
||||
vs.push_back(s + node->_id);
|
||||
}
|
||||
}
|
||||
|
||||
Common::String XMLNode::encodeEntity(const Common::String &s) {
|
||||
Common::String ret;
|
||||
|
||||
for (const auto &c : s) {
|
||||
switch (c) {
|
||||
case '<':
|
||||
ret += "<";
|
||||
break;
|
||||
case '>':
|
||||
ret += ">";
|
||||
break;
|
||||
case '"':
|
||||
ret += """;
|
||||
break;
|
||||
case '\'':
|
||||
ret += "'";
|
||||
break;
|
||||
case '&':
|
||||
ret += "&";
|
||||
break;
|
||||
default:
|
||||
ret += c;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Common::String decode_entity(const Common::String &s, size_t &pos) {
|
||||
// size_t old_pos = pos;
|
||||
size_t entityNameLen = s.findFirstOf("; \t\r\n", pos) - pos - 1;
|
||||
|
||||
/* Call me paranoid... but I don't think having an end-of-line or similar
|
||||
inside a &...; expression is 'good', valid though it may be. */
|
||||
assert(s[pos + entityNameLen + 1] == ';');
|
||||
|
||||
Common::String entity_name = s.substr(pos + 1, entityNameLen);
|
||||
|
||||
pos += entityNameLen + 2;
|
||||
|
||||
// Std::cout << "DECODE: " << entity_name << endl;
|
||||
|
||||
if (entity_name == "amp")
|
||||
return Common::String("&");
|
||||
else if (entity_name == "apos")
|
||||
return Common::String("'");
|
||||
else if (entity_name == "quot")
|
||||
return Common::String("\"");
|
||||
else if (entity_name == "lt")
|
||||
return Common::String("<");
|
||||
else if (entity_name == "gt")
|
||||
return Common::String(">");
|
||||
else if (entity_name.hasPrefix("#")) {
|
||||
entity_name.deleteChar(0);
|
||||
|
||||
if (entity_name.hasPrefix("x")) {
|
||||
uint tmp = 0;
|
||||
int read = sscanf(entity_name.c_str() + 1, "%xh", &tmp);
|
||||
if (read < 1)
|
||||
error("strToInt failed on string \"%s\"", entity_name.c_str());
|
||||
return Common::String((char)tmp);
|
||||
} else {
|
||||
uint tmp = atol(entity_name.c_str());
|
||||
return Common::String((char)tmp);
|
||||
}
|
||||
} else {
|
||||
error("Invalid xml encoded entity - %s", entity_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode *XMLNode::xmlParseDoc(XMLTree *tree, const Common::String &s) {
|
||||
Common::String sbuf(s);
|
||||
size_t nn = 0;
|
||||
bool parsedXmlElement = false, parsedDocType = false;
|
||||
XMLNode *node = nullptr, *child = nullptr;
|
||||
|
||||
for (;;) {
|
||||
while (nn < s.size() && Common::isSpace(s[nn]))
|
||||
++nn;
|
||||
if (nn >= s.size())
|
||||
return node;
|
||||
|
||||
if (s[nn] != '<') {
|
||||
warning("expected '<' while reading config file, found %c\n", s[nn]);
|
||||
return nullptr;
|
||||
}
|
||||
++nn;
|
||||
|
||||
if (nn < s.size() && s[nn] == '?') {
|
||||
assert(!parsedXmlElement);
|
||||
parsedXmlElement = true;
|
||||
nn = s.findFirstOf('>', nn);
|
||||
} else if (nn < s.size() && s.substr(nn, 8).equalsIgnoreCase("!doctype")) {
|
||||
assert(!parsedDocType);
|
||||
parsedDocType = true;
|
||||
parseDocTypeElement(s, nn);
|
||||
} else {
|
||||
--nn;
|
||||
child = xmlParse(tree, sbuf, nn);
|
||||
if (child) {
|
||||
if (node)
|
||||
error("Invalid multiple xml nodes at same level");
|
||||
node = child;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this point was reached, we just skipped ?xml or doctype element
|
||||
++nn;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void XMLNode::parseDocTypeElement(const Common::String &s, size_t &nn) {
|
||||
nn = s.findFirstOf(">[", nn);
|
||||
if (nn == Common::String::npos)
|
||||
// No ending tag
|
||||
return;
|
||||
|
||||
if (s[nn] == '[') {
|
||||
// Square bracketed area
|
||||
nn = s.findFirstOf(']', nn) + 1;
|
||||
}
|
||||
|
||||
if (nn >= s.size() || s[nn] != '>')
|
||||
nn = Common::String::npos;
|
||||
}
|
||||
|
||||
XMLNode *XMLNode::xmlParse(XMLTree *tree, const Common::String &s, size_t &pos) {
|
||||
bool inTag = false, isSelfEnding = false;
|
||||
XMLNode *node = nullptr, *child = nullptr;
|
||||
Common::String nodeText, plainText;
|
||||
|
||||
while (pos < s.size()) {
|
||||
if (inTag && nodeText.hasPrefix("!--") && (s[pos] != '>' || !nodeText.hasSuffix("--"))) {
|
||||
// It's a > within the comment, but not the terminator
|
||||
nodeText += s[pos];
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (s[pos]) {
|
||||
case '<':
|
||||
// Start of tag
|
||||
assert(!inTag);
|
||||
|
||||
trim(plainText);
|
||||
if (!plainText.empty()) {
|
||||
// Plain text, return it
|
||||
child = new XMLNode(tree);
|
||||
child->_text = plainText;
|
||||
return child;
|
||||
}
|
||||
|
||||
// New tag?
|
||||
if (s[pos + 1] == '/') {
|
||||
// No. It's a close tag. Move beyond it
|
||||
while (s[pos] != '>')
|
||||
pos++;
|
||||
++pos;
|
||||
// Return nullptr as indication that the end was reached
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inTag = true;
|
||||
++pos;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
// End of tag
|
||||
isSelfEnding = nodeText.hasSuffix("/");
|
||||
++pos;
|
||||
|
||||
if (isSelfEnding) {
|
||||
nodeText.deleteLastChar();
|
||||
} else if (nodeText.hasPrefix("!--")) {
|
||||
// Comment element that can be ignored
|
||||
inTag = false;
|
||||
nodeText.clear();
|
||||
plainText.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a node for the tag, and parse it's attributes, if any
|
||||
node = new XMLNode(tree);
|
||||
node->parseNodeText(nodeText);
|
||||
|
||||
if (!isSelfEnding) {
|
||||
// Iterate through parsing and adding sub-elements
|
||||
while ((child = xmlParse(tree, s, pos)) != nullptr) {
|
||||
child->_parent = node;
|
||||
node->_nodeList.push_back(child);
|
||||
}
|
||||
} else if (node->_id.equalsIgnoreCase("xi:include")) {
|
||||
// Element is a placeholder for inclusion of a secondary XML file
|
||||
Common::String fname = node->_attributes["href"];
|
||||
delete node;
|
||||
node = xmlParseFile(tree, Common::Path(fname, '/'));
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
case '&':
|
||||
if (inTag)
|
||||
nodeText += decode_entity(s, pos);
|
||||
else
|
||||
plainText += decode_entity(s, pos);
|
||||
break;
|
||||
default:
|
||||
if (inTag)
|
||||
nodeText += s[pos++];
|
||||
else
|
||||
plainText += s[pos++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void XMLNode::parseNodeText(const Common::String &nodeText) {
|
||||
size_t firstSpace = nodeText.findFirstOf(' ');
|
||||
if (firstSpace == Common::String::npos) {
|
||||
// The entire text is the id
|
||||
_id = nodeText;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the Id and get out the remaining attributes section, if any
|
||||
_id = Common::String(nodeText.c_str(), firstSpace);
|
||||
Common::String attr(nodeText.c_str() + firstSpace);
|
||||
|
||||
for (;;) {
|
||||
// Skip any spaces
|
||||
while (!attr.empty() && Common::isSpace(attr[0]))
|
||||
attr.deleteChar(0);
|
||||
if (attr.empty())
|
||||
return;
|
||||
|
||||
// Find the equals after the attribute name
|
||||
size_t equalsPos = attr.findFirstOf('=');
|
||||
if (equalsPos == Common::String::npos)
|
||||
return;
|
||||
|
||||
// Get the name, and find the quotes start
|
||||
Common::String name = Common::String(attr.c_str(), equalsPos);
|
||||
++equalsPos;
|
||||
while (equalsPos < attr.size() && Common::isSpace(attr[equalsPos]))
|
||||
++equalsPos;
|
||||
|
||||
if (attr[equalsPos] == '\'' && attr[equalsPos] != '"')
|
||||
return;
|
||||
|
||||
// Find the end of the attribute
|
||||
size_t attrEnd = attr.findFirstOf(attr[equalsPos], equalsPos + 1);
|
||||
if (attrEnd == Common::String::npos)
|
||||
return;
|
||||
|
||||
// Add the parsed attribute
|
||||
_attributes[name] = Common::String(attr.c_str() + equalsPos + 1, attr.c_str() + attrEnd);
|
||||
|
||||
// Remove the parsed attribute
|
||||
attr = Common::String(attr.c_str() + attrEnd + 1);
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode *XMLNode::xmlParseFile(XMLTree *tree, const Common::Path &fname) {
|
||||
const Common::Path rootFile = tree->_filename;
|
||||
Common::Path filename = rootFile.getParent().join(fname);
|
||||
|
||||
Common::File f;
|
||||
if (!f.open(filename))
|
||||
error("Could not open xml file - %s", filename.toString().c_str());
|
||||
|
||||
// Read in the file contents
|
||||
char *buf = new char[f.size() + 1];
|
||||
f.read(buf, f.size());
|
||||
buf[f.size()] = '\0';
|
||||
Common::String text(buf, buf + f.size());
|
||||
delete[] buf;
|
||||
f.close();
|
||||
|
||||
// Parse the sub-xml
|
||||
XMLNode *result = xmlParseDoc(tree, text);
|
||||
if (!result)
|
||||
error("Error passing xml - %s", fname.toString().c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool XMLNode::searchPairs(KeyTypeList &ktl, const Common::String &basekey,
|
||||
const Common::String &currkey, const unsigned int pos) {
|
||||
/* If our 'current key' is longer then the key we're serching for
|
||||
we've obviously gone too deep in this branch, and we won't find
|
||||
it here. */
|
||||
if ((currkey.size() <= basekey.size()) && (_id[0] != '!')) {
|
||||
/* If we've found it, return every key->value pair under this key,
|
||||
then return true, since we've found the key we were looking for.*/
|
||||
if (basekey == currkey + _id) {
|
||||
for (auto *node : _nodeList) {
|
||||
if (node->_id[0] != '!')
|
||||
node->selectPairs(ktl, "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* Else, keep searching for the key under it's subnodes */
|
||||
else {
|
||||
for (auto *node : _nodeList) {
|
||||
if (node->searchPairs(ktl, basekey, currkey + _id + '/', pos))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Just adds every key->value pair under the this node to the ktl */
|
||||
void XMLNode::selectPairs(KeyTypeList &ktl, const Common::String &currkey) {
|
||||
ktl.push_back(KeyType(currkey + _id, currkey));
|
||||
|
||||
for (auto *node : _nodeList) {
|
||||
node->selectPairs(ktl, currkey + _id + '/');
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode *XMLNode::getPrior() const {
|
||||
const Common::Array<XMLNode *> &siblings = _parent->_nodeList;
|
||||
for (uint idx = 0; idx < siblings.size(); ++idx) {
|
||||
if (siblings[idx] == this)
|
||||
return (idx > 0) ? siblings[idx - 1] : nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XMLNode *XMLNode::getNext() const {
|
||||
const Common::Array<XMLNode *> &siblings = _parent->_nodeList;
|
||||
for (uint idx = 0; idx < siblings.size(); ++idx) {
|
||||
if (siblings[idx] == this)
|
||||
return (idx < (siblings.size() - 1)) ? siblings[idx + 1] : nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void XMLNode::freeDoc() {
|
||||
delete _tree;
|
||||
}
|
||||
|
||||
void XMLNode::trim(Common::String &s) {
|
||||
// Convert any CRLF to just LF
|
||||
size_t pos;
|
||||
while ((pos = s.find("\r\n")) != Common::String::npos)
|
||||
s.deleteChar(pos);
|
||||
|
||||
// Then check if the string is entirely whitespace
|
||||
bool hasContent = false;
|
||||
for (uint idx = 0; idx < s.size() && !hasContent; ++idx)
|
||||
hasContent = !Common::isSpace(s[idx]);
|
||||
|
||||
if (!hasContent) {
|
||||
s = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any spaces from the very start of the string and following
|
||||
// any linefeeds. This handles any indented text within the xml
|
||||
for (size_t startPos = 0; startPos != Common::String::npos;
|
||||
startPos = s.findFirstOf('\n', startPos + 1)) {
|
||||
pos = (startPos == 0) ? 0 : startPos + 1;
|
||||
while (pos < s.size() && s[pos] == ' ')
|
||||
s.deleteChar(pos);
|
||||
}
|
||||
}
|
||||
|
||||
Common::String XMLNode::closeTag(const Common::String &s) {
|
||||
if (s.find(" ") == Common::String::npos)
|
||||
return s;
|
||||
|
||||
return s.substr(0, s.find(" "));
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
166
engines/ultima/shared/conf/xml_node.h
Normal file
166
engines/ultima/shared/conf/xml_node.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/* 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 SHARED_CONF_XML_NODE_H
|
||||
#define SHARED_CONF_XML_NODE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/path.h"
|
||||
#include "common/str.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class XMLTree;
|
||||
|
||||
class XMLNode {
|
||||
private:
|
||||
XMLTree *_tree;
|
||||
XMLNode *_parent;
|
||||
Common::String _id;
|
||||
Common::String _text;
|
||||
Common::Array<XMLNode *> _nodeList;
|
||||
Common::StringMap _attributes;
|
||||
bool _noClose;
|
||||
Common::String _emptyString;
|
||||
private:
|
||||
static void parseDocTypeElement(const Common::String &s, size_t &nn);
|
||||
|
||||
void parseNodeText(const Common::String &nodeText);
|
||||
|
||||
/**
|
||||
* Trim down any whitespaces in the passed text
|
||||
*/
|
||||
static void trim(Common::String &s);
|
||||
|
||||
/**
|
||||
* Parses a specified file and returns the root node for it
|
||||
*/
|
||||
static XMLNode *xmlParseFile(XMLTree *tree, const Common::Path &fname);
|
||||
|
||||
static Common::String closeTag(const Common::String &s);
|
||||
static Common::String encodeEntity(const Common::String &s);
|
||||
public:
|
||||
XMLNode(XMLTree *tree, XMLNode *parent = nullptr) : _tree(tree), _parent(parent), _noClose(false) {}
|
||||
XMLNode(const XMLNode &n) : _tree(n._tree), _parent(n._parent), _id(n._id),
|
||||
_text(n._text), _nodeList(n._nodeList), _noClose(false) {}
|
||||
~XMLNode();
|
||||
|
||||
XMLNode &operator=(const XMLNode &n) {
|
||||
_id = n._id;
|
||||
_text = n._text;
|
||||
_nodeList = n._nodeList;
|
||||
_noClose = n._noClose;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Common::String &reference(const Common::String &, bool &);
|
||||
const XMLNode *subtree(const Common::String &) const;
|
||||
|
||||
const Common::String &id() const {
|
||||
return _id;
|
||||
}
|
||||
const Common::String &text(void) const {
|
||||
return _text;
|
||||
}
|
||||
bool nodeIsText() const {
|
||||
return !_text.empty();
|
||||
}
|
||||
XMLNode *getParent() const {
|
||||
return _parent;
|
||||
}
|
||||
bool hasChildren() const {
|
||||
return !_nodeList.empty();
|
||||
}
|
||||
XMLNode *firstChild() const {
|
||||
return _nodeList.empty() ? nullptr : _nodeList[0];
|
||||
}
|
||||
const Common::StringMap &attributes() const {
|
||||
return _attributes;
|
||||
}
|
||||
bool hasProperty(const Common::String &attrName) const {
|
||||
return _attributes.contains(attrName);
|
||||
}
|
||||
Common::String getProperty(const Common::String &attrName) const {
|
||||
return _attributes.contains(attrName) ? _attributes[attrName] : "";
|
||||
}
|
||||
int getPropertyInt(const Common::String &attrName) const {
|
||||
return _attributes.contains(attrName) ? atol(_attributes[attrName].c_str()) : 0;
|
||||
}
|
||||
bool getPropertyBool(const Common::String &attrName) const {
|
||||
if (_attributes.contains(attrName)) {
|
||||
Common::String str = _attributes[attrName];
|
||||
return toupper(str[0]) == 'T' || str == "1";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Common::String operator[](const Common::String &attrName) const {
|
||||
return getProperty(attrName);
|
||||
}
|
||||
|
||||
const Common::Array<XMLNode *> &children() const {
|
||||
return _nodeList;
|
||||
}
|
||||
|
||||
typedef Common::Pair<Common::String, Common::String> KeyType;
|
||||
typedef Common::Array<KeyType> KeyTypeList;
|
||||
|
||||
/**
|
||||
* Returns a list of key->value pairs that are found under the provided 'basekey'.
|
||||
* Ignores comments (<!-- ... --> and doesn't return them.
|
||||
* Returns true if search is 'finished'
|
||||
*/
|
||||
bool searchPairs(KeyTypeList &ktl, const Common::String &basekey,
|
||||
const Common::String &currkey, const unsigned int pos);
|
||||
void selectPairs(KeyTypeList &ktl, const Common::String &currkey);
|
||||
|
||||
Common::String dump(int depth = 0);
|
||||
|
||||
void xmlAssign(const Common::String &key, const Common::String &value);
|
||||
static XMLNode *xmlParseDoc(XMLTree *tree, const Common::String &s);
|
||||
static XMLNode *xmlParse(XMLTree *tree, const Common::String &s, size_t &pos);
|
||||
|
||||
void listKeys(const Common::String &, Common::Array<Common::String> &,
|
||||
bool longformat = true) const;
|
||||
|
||||
/**
|
||||
* Deletes the entire tree this node belongs to, including itself
|
||||
*/
|
||||
void freeDoc();
|
||||
|
||||
/**
|
||||
* Gets the prior sibling to this one
|
||||
*/
|
||||
XMLNode *getPrior() const;
|
||||
|
||||
/**
|
||||
* Gets the following sibling to this one
|
||||
*/
|
||||
XMLNode *getNext() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
196
engines/ultima/shared/conf/xml_tree.cpp
Normal file
196
engines/ultima/shared/conf/xml_tree.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
/* 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 "ultima/shared/conf/xml_tree.h"
|
||||
#include "ultima/shared/conf/xml_node.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
XMLTree::XMLTree() : _tree(nullptr), _isFile(false),
|
||||
_readOnly(false) {
|
||||
}
|
||||
|
||||
XMLTree::XMLTree(const Common::Path &fname) : _tree(nullptr), _isFile(true),
|
||||
_readOnly(false) {
|
||||
readConfigFile(fname);
|
||||
}
|
||||
|
||||
XMLTree::XMLTree(Common::SeekableReadStream *stream)
|
||||
: _tree(nullptr), _isFile(true), _readOnly(false) {
|
||||
readConfigStream(stream);
|
||||
}
|
||||
|
||||
XMLTree::~XMLTree() {
|
||||
delete _tree;
|
||||
}
|
||||
|
||||
void XMLTree::clear() {
|
||||
delete _tree;
|
||||
_tree = nullptr;
|
||||
_isFile = false;
|
||||
_readOnly = false;
|
||||
}
|
||||
|
||||
bool XMLTree::readConfigFile(const Common::Path &fname) {
|
||||
Common::File f;
|
||||
_filename = fname;
|
||||
|
||||
if (!f.open(fname)) {
|
||||
warning("Error opening config file");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = readConfigStream(&f);
|
||||
|
||||
f.close();
|
||||
|
||||
_filename = fname;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool XMLTree::readConfigStream(Common::SeekableReadStream *stream) {
|
||||
// Read in the stream contents
|
||||
char *buf = new char[stream->size() + 1];
|
||||
stream->read(buf, stream->size());
|
||||
buf[stream->size()] = '\0';
|
||||
Common::String text(buf, buf + stream->size());
|
||||
|
||||
if (!readConfigString(buf))
|
||||
return false;
|
||||
|
||||
delete[] buf;
|
||||
_isFile = true; // readConfigString sets _isFile = false
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XMLTree::readConfigString(const Common::String &s) {
|
||||
_tree = _tree->xmlParseDoc(this, s);
|
||||
|
||||
_isFile = false;
|
||||
_filename.clear();
|
||||
|
||||
return _tree != nullptr;
|
||||
}
|
||||
|
||||
Common::String XMLTree::dump() {
|
||||
return _tree->dump();
|
||||
}
|
||||
|
||||
void XMLTree::write() {
|
||||
if (!_isFile || _readOnly)
|
||||
return;
|
||||
|
||||
Common::DumpFile df;
|
||||
|
||||
if (df.open(_filename)) {
|
||||
Common::String content = dump();
|
||||
df.write(content.c_str(), content.size());
|
||||
df.close();
|
||||
}
|
||||
}
|
||||
|
||||
const XMLNode *XMLTree::getNode(const Common::String &key) const {
|
||||
return _tree->subtree(key);
|
||||
}
|
||||
|
||||
bool XMLTree::hasNode(const Common::String &key) const {
|
||||
const XMLNode *sub = _tree->subtree(key);
|
||||
if (sub)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLTree::checkRoot(const Common::String &key) const {
|
||||
Common::String k = key.substr(0, key.find('/'));
|
||||
return _tree && k == _tree->id();
|
||||
}
|
||||
|
||||
void XMLTree::value(const Common::String &key, Common::String &ret,
|
||||
const char *defaultvalue) const {
|
||||
const XMLNode *sub = _tree->subtree(key);
|
||||
if (sub) {
|
||||
ret = sub->text();
|
||||
if (ret.empty())
|
||||
if (sub->firstChild())
|
||||
ret = sub->firstChild()->text();
|
||||
}
|
||||
else
|
||||
ret = defaultvalue;
|
||||
}
|
||||
|
||||
void XMLTree::value(const Common::String &key, int &ret,
|
||||
int defaultvalue) const {
|
||||
const XMLNode *sub = _tree->subtree(key);
|
||||
if (sub)
|
||||
ret = strtol(sub->text().c_str(), 0, 0);
|
||||
else
|
||||
ret = defaultvalue;
|
||||
}
|
||||
|
||||
void XMLTree::value(const Common::String &key, bool &ret,
|
||||
bool defaultvalue) const {
|
||||
const XMLNode *sub = _tree->subtree(key);
|
||||
if (sub)
|
||||
ret = sub->text().equalsIgnoreCase("YES");
|
||||
else
|
||||
ret = defaultvalue;
|
||||
}
|
||||
|
||||
void XMLTree::set(const Common::String &key, const Common::String &value) {
|
||||
_tree->xmlAssign(key, value);
|
||||
}
|
||||
|
||||
void XMLTree::set(const Common::String &key, const char *value) {
|
||||
_tree->xmlAssign(key, value);
|
||||
}
|
||||
|
||||
void XMLTree::set(const Common::String &key, int value) {
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "%d", value);
|
||||
set(key, buf);
|
||||
}
|
||||
|
||||
void XMLTree::set(const Common::String &key, bool value) {
|
||||
if (value)
|
||||
set(key, "yes");
|
||||
else
|
||||
set(key, "no");
|
||||
}
|
||||
|
||||
Common::Array<Common::String> XMLTree::listKeys(const Common::String &key, bool longformat) {
|
||||
Common::Array<Common::String> keys;
|
||||
const XMLNode *sub = _tree->subtree(key);
|
||||
if (sub)
|
||||
sub->listKeys(key, keys, longformat);
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
void XMLTree::getSubkeys(KeyTypeList &ktl, const Common::String &basekey) {
|
||||
_tree->searchPairs(ktl, basekey, Common::String(), 0);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
95
engines/ultima/shared/conf/xml_tree.h
Normal file
95
engines/ultima/shared/conf/xml_tree.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 SHARED_CONF_XML_TREE_H
|
||||
#define SHARED_CONF_XML_TREE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/path.h"
|
||||
#include "common/str.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class XMLNode;
|
||||
|
||||
class XMLTree {
|
||||
friend class XMLNode;
|
||||
private:
|
||||
XMLNode *_tree;
|
||||
Common::Path _filename;
|
||||
bool _isFile;
|
||||
bool _readOnly;
|
||||
public:
|
||||
XMLTree();
|
||||
XMLTree(const Common::Path &fname);
|
||||
XMLTree(Common::SeekableReadStream *stream);
|
||||
~XMLTree();
|
||||
|
||||
bool readConfigFile(const Common::Path &fname);
|
||||
bool readConfigStream(Common::SeekableReadStream *stream);
|
||||
bool readConfigString(const Common::String &s);
|
||||
|
||||
void clear();
|
||||
|
||||
Common::String dump();
|
||||
void write();
|
||||
|
||||
void setReadonly() {
|
||||
_readOnly = true;
|
||||
}
|
||||
bool isReadonly() const {
|
||||
return _readOnly;
|
||||
}
|
||||
XMLNode *getTree() const {
|
||||
return _tree;
|
||||
}
|
||||
|
||||
const XMLNode *getNode(const Common::String &key) const;
|
||||
bool hasNode(const Common::String &key) const;
|
||||
bool checkRoot(const Common::String &key) const;
|
||||
|
||||
// get value
|
||||
void value(const Common::String &key, Common::String &ret,
|
||||
const char *defaultvalue = "") const;
|
||||
void value(const Common::String &key, int &ret, int defaultvalue = 0) const;
|
||||
void value(const Common::String &key, bool &ret, bool defaultvalue = false) const;
|
||||
|
||||
// set value
|
||||
void set(const Common::String &key, const Common::String &value);
|
||||
void set(const Common::String &key, const char *value);
|
||||
void set(const Common::String &key, int value);
|
||||
void set(const Common::String &key, bool value);
|
||||
|
||||
Common::Array<Common::String> listKeys(const Common::String &key, bool longformat = false);
|
||||
|
||||
typedef Common::Pair<Common::String, Common::String> KeyType;
|
||||
typedef Common::Array<KeyType> KeyTypeList;
|
||||
|
||||
void getSubkeys(KeyTypeList &ktl, const Common::String &basekey);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
48
engines/ultima/shared/core/base_object.cpp
Normal file
48
engines/ultima/shared/core/base_object.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/core/base_object.h"
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
#include "ultima/shared/core/named_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
ClassDef BaseObject::type() {
|
||||
return ClassDef("BaseObject", nullptr);
|
||||
}
|
||||
|
||||
bool BaseObject::isInstanceOf(const ClassDef &classDef) const {
|
||||
ClassDef def = getType();
|
||||
for (;;) {
|
||||
if (def == classDef)
|
||||
return true;
|
||||
|
||||
if (!def.hasParent())
|
||||
break;
|
||||
def = def.parent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
88
engines/ultima/shared/core/base_object.h
Normal file
88
engines/ultima/shared/core/base_object.h
Normal 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 ULTIMA_SHARED_CORE_BASE_OBJECT_H
|
||||
#define ULTIMA_SHARED_CORE_BASE_OBJECT_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/list.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class BaseObject;
|
||||
|
||||
class ClassDef;
|
||||
typedef ClassDef(*ClassDefFn)();
|
||||
|
||||
/**
|
||||
* Encapsulation of a class definition. Used as part of the message dispatch system
|
||||
* to identify classes that implement particular messages
|
||||
*/
|
||||
class ClassDef {
|
||||
private:
|
||||
ClassDefFn _parentFn;
|
||||
public:
|
||||
const char *_className;
|
||||
public:
|
||||
ClassDef(const char *className, const ClassDefFn parentFn) :
|
||||
_className(className), _parentFn(parentFn) {
|
||||
}
|
||||
|
||||
bool hasParent() const {
|
||||
return _parentFn != nullptr;
|
||||
}
|
||||
ClassDef parent() const {
|
||||
return (*_parentFn)();
|
||||
}
|
||||
bool operator==(const ClassDef &right) const {
|
||||
return !strcmp(_className, right._className);
|
||||
}
|
||||
};
|
||||
|
||||
#define CLASSDEF \
|
||||
static ::Ultima::Shared::ClassDef type(); \
|
||||
::Ultima::Shared::ClassDef getType() const override { return type(); }
|
||||
|
||||
/**
|
||||
* Defines the most basic root of the engine's object hierarchy.
|
||||
*/
|
||||
class BaseObject {
|
||||
public:
|
||||
static ::Ultima::Shared::ClassDef type();
|
||||
virtual ::Ultima::Shared::ClassDef getType() const { return type(); }
|
||||
virtual ~BaseObject() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given object is of the type defined by the class definition,
|
||||
* or one of it's descendants
|
||||
*/
|
||||
bool isInstanceOf(const ClassDef &classDef) const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
63
engines/ultima/shared/core/character.cpp
Normal file
63
engines/ultima/shared/core/character.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/core/party.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
template<typename T>
|
||||
void syncArray(Common::Array<T *> &items, Common::Serializer &s) {
|
||||
uint count = items.size();
|
||||
s.syncAsByte(count);
|
||||
if (s.isLoading())
|
||||
assert(count == items.size());
|
||||
|
||||
for (uint idx = 0; idx < items.size(); ++idx)
|
||||
items[idx]->synchronize(s);
|
||||
}
|
||||
|
||||
void Character::synchronize(Common::Serializer &s) {
|
||||
s.syncString(_name);
|
||||
s.syncAsByte(_race);
|
||||
s.syncAsByte(_sex);
|
||||
s.syncAsByte(_class);
|
||||
s.syncAsUint16LE(_strength);
|
||||
s.syncAsUint16LE(_agility);
|
||||
s.syncAsUint16LE(_stamina);
|
||||
s.syncAsUint16LE(_charisma);
|
||||
s.syncAsUint16LE(_wisdom);
|
||||
s.syncAsUint16LE(_intelligence);
|
||||
s.syncAsUint32LE(_hitPoints);
|
||||
s.syncAsUint32LE(_experience);
|
||||
s.syncAsUint32LE(_food);
|
||||
s.syncAsUint32LE(_coins);
|
||||
s.syncAsSByte(_equippedWeapon);
|
||||
s.syncAsSByte(_equippedArmour);
|
||||
s.syncAsSByte(_equippedSpell);
|
||||
|
||||
syncArray<Weapon>(_weapons, s);
|
||||
syncArray<Armour>(_armour, s);
|
||||
syncArray<Spell>(_spells, s);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
231
engines/ultima/shared/core/character.h
Normal file
231
engines/ultima/shared/core/character.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/* 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 ULTIMA_SHARED_CORE_CHARACTER_H
|
||||
#define ULTIMA_SHARED_CORE_CHARACTER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/named_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
enum Sex { SEX_MALE = 0, SEX_FEMALE = 1, SEX_OTHER = 2, SEX_YES_PLEASE = 2 };
|
||||
|
||||
/**
|
||||
* Base class for class types that have a quantity
|
||||
*/
|
||||
class Itemized {
|
||||
public:
|
||||
uint _quantity;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Itemized() : _quantity(0) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Itemized() {}
|
||||
|
||||
/**
|
||||
* Synchronize data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_quantity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the quantity by a given amount
|
||||
*/
|
||||
virtual void changeQuantity(int delta) {
|
||||
_quantity = (uint)CLIP((int)_quantity + delta, 0, 9999);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the quantity by 1
|
||||
*/
|
||||
void incrQuantity() { changeQuantity(1); }
|
||||
|
||||
/**
|
||||
* Returns if the itemized is empty
|
||||
*/
|
||||
bool empty() const { return _quantity == 0; }
|
||||
|
||||
/**
|
||||
* Decrease the quantity by 1
|
||||
*/
|
||||
bool decrQuantity() {
|
||||
changeQuantity(-1);
|
||||
return empty();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Weapon entry
|
||||
*/
|
||||
class Weapon : public Itemized {
|
||||
public:
|
||||
Common::String _shortName, _longName;
|
||||
uint _distance;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Weapon() : Itemized(), _distance(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Armour entry
|
||||
*/
|
||||
class Armour : public Itemized {
|
||||
public:
|
||||
Common::String _name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Spell entry
|
||||
*/
|
||||
class Spell : public Itemized, public NamedItem {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ItemArray : public Common::Array<T> {
|
||||
public:
|
||||
/**
|
||||
* Returns the number of distinct types of items in the array, not counting
|
||||
* the slot 0 "nothing" slot
|
||||
*/
|
||||
size_t itemsCount() const {
|
||||
uint total = 0;
|
||||
for (uint idx = 1; idx < this->size(); ++idx) {
|
||||
if (!(*this)[idx]->empty())
|
||||
++total;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the character has no items
|
||||
*/
|
||||
bool hasNothing() const {
|
||||
return itemsCount() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the data for a playable character within the game
|
||||
*/
|
||||
class Character {
|
||||
public:
|
||||
Common::String _name;
|
||||
uint _race;
|
||||
Sex _sex;
|
||||
uint _class;
|
||||
|
||||
uint _strength;
|
||||
uint _agility;
|
||||
uint _stamina;
|
||||
uint _charisma;
|
||||
uint _wisdom;
|
||||
uint _intelligence;
|
||||
uint _hitPoints;
|
||||
uint _experience;
|
||||
uint _food;
|
||||
uint _coins;
|
||||
int _equippedWeapon;
|
||||
int _equippedArmour;
|
||||
int _equippedSpell;
|
||||
ItemArray<Weapon *> _weapons;
|
||||
ItemArray<Armour *> _armour;
|
||||
ItemArray<Spell *> _spells;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Character() : _strength(0), _agility(0), _stamina(0), _charisma(0), _wisdom(0), _intelligence(0),
|
||||
_hitPoints(0), _experience(0), _food(0), _coins(0), _equippedWeapon(0), _equippedArmour(0), _equippedSpell(0),
|
||||
_race(0), _sex(SEX_MALE), _class(0) {}
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Returns true if a weapon is equipped
|
||||
*/
|
||||
bool isWeaponEquipped() const { return _equippedWeapon != 0; }
|
||||
|
||||
/**
|
||||
* Returns true if armor is equipped
|
||||
*/
|
||||
bool isArmourEquipped() const { return _equippedArmour != 0; }
|
||||
|
||||
/**
|
||||
* Returns true if a spell is equipped
|
||||
*/
|
||||
bool isSpellEquipped() const { return _equippedSpell != 0; }
|
||||
|
||||
/**
|
||||
* Return the equipped weapon
|
||||
*/
|
||||
Weapon *equippedWeapon() const { return _weapons[_equippedWeapon]; }
|
||||
|
||||
/**
|
||||
* Return the equipped armor
|
||||
*/
|
||||
Armour *equippedArmour() const { return _armour[_equippedArmour]; }
|
||||
|
||||
/**
|
||||
* Return the equipped spell
|
||||
*/
|
||||
Spell *equippedSpell() const { return _spells[_equippedSpell]; }
|
||||
|
||||
/**
|
||||
* Removes any equipped weapon
|
||||
*/
|
||||
void removeWeapon() { _equippedWeapon = 0; }
|
||||
|
||||
/**
|
||||
* Removes any eqipped armor
|
||||
*/
|
||||
void removeArmour() { _equippedArmour = 0; }
|
||||
|
||||
/**
|
||||
* Remove any equipped spell
|
||||
*/
|
||||
void removeSpell() { _equippedSpell = 0; }
|
||||
|
||||
/**
|
||||
* Gets the character's experience level
|
||||
*/
|
||||
uint getLevel() const { return (_experience / 1000) + 1; }
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
85
engines/ultima/shared/core/file.cpp
Normal file
85
engines/ultima/shared/core/file.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/util.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define ERROR error("Could not open file - %s", name.c_str())
|
||||
#define PATH_ERROR error("Could not open file - %s", name.toString(Common::Path::kNativeSeparator).c_str())
|
||||
|
||||
File::File(const Common::Path &name) : Common::File(), _filesize(-1) {
|
||||
close();
|
||||
|
||||
if (!Common::File::open(name))
|
||||
PATH_ERROR;
|
||||
}
|
||||
|
||||
bool File::open(const Common::Path &name) {
|
||||
close();
|
||||
|
||||
if (!Common::File::open(name))
|
||||
PATH_ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::open(const Common::Path &name, Common::Archive &archive) {
|
||||
close();
|
||||
|
||||
if (!Common::File::open(name, archive))
|
||||
PATH_ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::open(const Common::FSNode &node) {
|
||||
close();
|
||||
|
||||
Common::String name = node.getName();
|
||||
if (!Common::File::open(node))
|
||||
ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::open(SeekableReadStream *stream, const Common::String &name) {
|
||||
close();
|
||||
|
||||
if (!Common::File::open(stream, name))
|
||||
ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
void File::close() {
|
||||
_filesize = -1;
|
||||
Common::File::close();
|
||||
}
|
||||
|
||||
bool File::eof() {
|
||||
if (_filesize == -1)
|
||||
_filesize = size();
|
||||
|
||||
return pos() >= _filesize;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
81
engines/ultima/shared/core/file.h
Normal file
81
engines/ultima/shared/core/file.h
Normal 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 ULTIMA_SHARED_CORE_FILE_H
|
||||
#define ULTIMA_SHARED_CORE_FILE_H
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* Simple ScummVM File descendent that throws a wobbly if the file it tries to open isn't present
|
||||
*/
|
||||
class File : public Common::File {
|
||||
private:
|
||||
int32 _filesize;
|
||||
public:
|
||||
File() : Common::File(), _filesize(-1) {}
|
||||
File(const Common::Path &name);
|
||||
|
||||
/**
|
||||
* Open the file with the given filename, by searching SearchMan.
|
||||
* @param name the name of the file to open
|
||||
*/
|
||||
bool open(const Common::Path &name) override;
|
||||
|
||||
/**
|
||||
* Open the file with the given filename from within the given archive.
|
||||
* @param name the name of the file to open
|
||||
* @param archive the archive in which to search for the file
|
||||
*/
|
||||
bool open(const Common::Path &name, Common::Archive &archive) override;
|
||||
|
||||
/**
|
||||
* Open the file corresponding to the give node.
|
||||
* @param node the node to consider.
|
||||
*/
|
||||
bool open(const Common::FSNode &node) override;
|
||||
|
||||
/**
|
||||
* 'Open' the given stream. That is, we just wrap around it
|
||||
* @param stream a pointer to a SeekableReadStream, or 0
|
||||
* @param name a string describing the 'file' corresponding to stream
|
||||
*/
|
||||
bool open(SeekableReadStream *stream, const Common::String &name) override;
|
||||
|
||||
/**
|
||||
* Close the currently open file
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
/**
|
||||
* Differing eof that returns true when pos == size as well as beyond
|
||||
*/
|
||||
bool eof();
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
112
engines/ultima/shared/core/game_state.h
Normal file
112
engines/ultima/shared/core/game_state.h
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_GAME_STATE_H
|
||||
#define ULTIMA_SHARED_CORE_GAME_STATE_H
|
||||
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/core/character.h"
|
||||
#include "ultima/shared/core/map.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
|
||||
enum VideoMode {
|
||||
UNSET = -1, CGA = 0, EGA = 1, TGA = 2, VGA_ENHANCED = 3
|
||||
};
|
||||
|
||||
class GameState {
|
||||
protected:
|
||||
Game *_game;
|
||||
public:
|
||||
/**
|
||||
* Position in the world map. This is stored separately from the map so that the same point can
|
||||
* be returned to when leaving locations
|
||||
*/
|
||||
Point _worldMapPos;
|
||||
|
||||
/**
|
||||
* Characters in the party. In the earlier Ultima games, this is a single character
|
||||
*/
|
||||
CharacterArray _characters;
|
||||
|
||||
/**
|
||||
* Currently active character. In earlier Ultima games, this is the single party member
|
||||
*/
|
||||
Character *_currentCharacter;
|
||||
|
||||
/**
|
||||
* Pointer to the map manager for the game
|
||||
*/
|
||||
Map *_map;
|
||||
|
||||
/**
|
||||
* Game type Id
|
||||
*/
|
||||
uint _gameId;
|
||||
|
||||
/**
|
||||
* Video mode
|
||||
*/
|
||||
VideoMode _videoMode;
|
||||
|
||||
/**
|
||||
* The number of hit points to generate when a dungeon is left
|
||||
*/
|
||||
uint _dungeonExitHitPoints;
|
||||
|
||||
/**
|
||||
* Stores the base random seed used for generating deterministic dungeon levels
|
||||
*/
|
||||
uint32 _randomSeed;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
GameState(Game *game);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~GameState();
|
||||
|
||||
/**
|
||||
* Setup the initial game state
|
||||
*/
|
||||
virtual void setup() {}
|
||||
|
||||
/**
|
||||
* Returns true if the party is dead
|
||||
*/
|
||||
bool isPartyDead() const;
|
||||
|
||||
/**
|
||||
* Returns true if the party has no food
|
||||
*/
|
||||
bool isPartyFoodless() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
135
engines/ultima/shared/core/lzw.cpp
Normal file
135
engines/ultima/shared/core/lzw.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/* 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/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "ultima/shared/core/lzw.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
void LZW::decompress(Common::ReadStream *source, Common::WriteStream *dest) {
|
||||
int32 destSize = source->readUint32LE();
|
||||
_source = source;
|
||||
_currentByte = source->readByte();
|
||||
|
||||
byte litByte = 0;
|
||||
uint16 oldCode = 0;
|
||||
uint16 copyLength, maxCodeValue, code, nextCode, lastCode;
|
||||
|
||||
byte *copyBuf = new byte[8192];
|
||||
|
||||
struct {
|
||||
uint16 code; byte value;
|
||||
} codeTable[8192];
|
||||
memset(codeTable, 0, sizeof(codeTable));
|
||||
|
||||
_codeLength = 9;
|
||||
nextCode = 258;
|
||||
maxCodeValue = 512;
|
||||
|
||||
copyLength = 0;
|
||||
_sourceBitsLeft = 8;
|
||||
|
||||
for (;;) {
|
||||
code = getCode();
|
||||
|
||||
if (code == 257)
|
||||
break;
|
||||
|
||||
if (code == 256) {
|
||||
_codeLength = 9;
|
||||
nextCode = 258;
|
||||
maxCodeValue = 512;
|
||||
lastCode = getCode();
|
||||
oldCode = lastCode;
|
||||
litByte = lastCode;
|
||||
dest->writeByte(litByte);
|
||||
} else {
|
||||
lastCode = code;
|
||||
if (code >= nextCode) {
|
||||
lastCode = oldCode;
|
||||
copyBuf[copyLength++] = litByte;
|
||||
}
|
||||
while (lastCode > 255) {
|
||||
copyBuf[copyLength++] = codeTable[lastCode].value;
|
||||
lastCode = codeTable[lastCode].code;
|
||||
}
|
||||
litByte = lastCode;
|
||||
copyBuf[copyLength++] = lastCode;
|
||||
while (copyLength > 0)
|
||||
dest->writeByte(copyBuf[--copyLength]);
|
||||
codeTable[nextCode].value = lastCode;
|
||||
codeTable[nextCode].code = oldCode;
|
||||
nextCode++;
|
||||
oldCode = code;
|
||||
if (nextCode >= maxCodeValue && _codeLength <= 12) {
|
||||
_codeLength++;
|
||||
maxCodeValue <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] copyBuf;
|
||||
assert(dest->pos() == destSize);
|
||||
}
|
||||
|
||||
uint16 LZW::getCode() {
|
||||
const byte bitMasks[9] = {
|
||||
0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x0FF
|
||||
};
|
||||
|
||||
byte resultBitsLeft = _codeLength;
|
||||
byte resultBitsPos = 0;
|
||||
uint16 result = 0;
|
||||
byte currentByte = _currentByte;
|
||||
byte currentBits = 0;
|
||||
|
||||
// Get bits of current byte
|
||||
while (resultBitsLeft) {
|
||||
if (resultBitsLeft < _sourceBitsLeft) {
|
||||
// we need less than we have left
|
||||
currentBits = (currentByte >> (8 - _sourceBitsLeft)) &bitMasks[resultBitsLeft];
|
||||
result |= (currentBits << resultBitsPos);
|
||||
_sourceBitsLeft -= resultBitsLeft;
|
||||
resultBitsLeft = 0;
|
||||
|
||||
} else {
|
||||
// we need as much as we have left or more
|
||||
resultBitsLeft -= _sourceBitsLeft;
|
||||
currentBits = currentByte >> (8 - _sourceBitsLeft);
|
||||
result |= (currentBits << resultBitsPos);
|
||||
resultBitsPos += _sourceBitsLeft;
|
||||
|
||||
// Go to next byte
|
||||
_currentByte = _source->readByte();
|
||||
|
||||
_sourceBitsLeft = 8;
|
||||
if (resultBitsLeft) {
|
||||
currentByte = _currentByte;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
49
engines/ultima/shared/core/lzw.h
Normal file
49
engines/ultima/shared/core/lzw.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_LZW_H
|
||||
#define ULTIMA_LZW_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class LZW {
|
||||
private:
|
||||
Common::ReadStream *_source;
|
||||
byte _sourceBitsLeft;
|
||||
byte _codeLength;
|
||||
byte _currentByte;
|
||||
private:
|
||||
uint16 getCode();
|
||||
public:
|
||||
/**
|
||||
* Decompresses data
|
||||
*/
|
||||
void decompress(Common::ReadStream *source, Common::WriteStream *dest);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
295
engines/ultima/shared/core/map.cpp
Normal file
295
engines/ultima/shared/core/map.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
/* 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 "ultima/shared/core/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
void MapTile::clear() {
|
||||
_tileId = _tileNum = -1;
|
||||
_widgetNum = -1;
|
||||
_widget = nullptr;
|
||||
_itemNum = -1;
|
||||
_isDoor = _isSecretDoor = false;
|
||||
_isLadderUp = _isLadderDown = false;
|
||||
_isWall = _isHallway = _isBeams = false;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void Map::MapBase::clear() {
|
||||
_mapId = 0;
|
||||
_data.clear();
|
||||
_widgets.clear();
|
||||
}
|
||||
|
||||
void Map::MapBase::load(MapId mapId) {
|
||||
_mapId = mapId;
|
||||
}
|
||||
|
||||
void Map::MapBase::synchronize(Common::Serializer &s) {
|
||||
_viewportPos.synchronize(s);
|
||||
uint size;
|
||||
int transportIndex = -1;
|
||||
Common::String name;
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Save widgets
|
||||
size = 0;
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
if (_widgets[idx]->getClassName())
|
||||
++size;
|
||||
if (_playerWidget == _widgets[idx].get())
|
||||
transportIndex = (int)idx;
|
||||
}
|
||||
assert(transportIndex >= 0);
|
||||
|
||||
s.syncAsUint16LE(size);
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
name = _widgets[idx]->getClassName();
|
||||
if (!name.empty()) {
|
||||
s.syncString(name);
|
||||
_widgets[idx]->synchronize(s);
|
||||
}
|
||||
}
|
||||
s.syncAsUint16LE(transportIndex);
|
||||
|
||||
} else {
|
||||
// Load widgets
|
||||
s.syncAsUint16LE(size);
|
||||
_widgets.clear();
|
||||
for (uint idx = 0; idx < size; ++idx) {
|
||||
s.syncString(name);
|
||||
|
||||
MapWidget *w = _map->createWidget(this, name);
|
||||
w->synchronize(s);
|
||||
addWidget(w);
|
||||
}
|
||||
|
||||
s.syncAsUint16LE(transportIndex);
|
||||
_playerWidget = _widgets[transportIndex].get();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::MapBase::setDimensions(const Point &size) {
|
||||
_data.resize(size.y);
|
||||
for (int y = 0; y < size.y; ++y)
|
||||
_data[y]._data.resize(size.x);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
Point Map::MapBase::getDirectionDelta() const {
|
||||
switch (_playerWidget->_direction) {
|
||||
case DIR_LEFT:
|
||||
return Point(-1, 0);
|
||||
case DIR_RIGHT:
|
||||
return Point(1, 0);
|
||||
case DIR_UP:
|
||||
return Point(0, -1);
|
||||
default:
|
||||
return Point(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Point Map::MapBase::getDeltaPosition(const Point &delta) {
|
||||
return _playerWidget->_position + delta;
|
||||
}
|
||||
|
||||
void Map::MapBase::resetViewport() {
|
||||
// Reset the viewport, so it's position will get recalculated
|
||||
_viewportPos.reset();
|
||||
}
|
||||
|
||||
Point Map::MapBase::getViewportPosition(const Point &viewportSize) {
|
||||
Point &topLeft = _viewportPos._topLeft;
|
||||
|
||||
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
|
||||
// Calculate the new position
|
||||
topLeft.x = _playerWidget->_position.x - (viewportSize.x - 1) / 2;
|
||||
topLeft.y = _playerWidget->_position.y - (viewportSize.y - 1) / 2;
|
||||
|
||||
// Fixed maps, so constrain top left corner so the map fills the viewport.
|
||||
// This will accommodate future renderings with more tiles, or greater tile size
|
||||
topLeft.x = CLIP((int)topLeft.x, 0, (int)(width() - viewportSize.x));
|
||||
topLeft.y = CLIP((int)topLeft.y, 0, (int)(height() - viewportSize.y));
|
||||
}
|
||||
|
||||
return topLeft;
|
||||
}
|
||||
|
||||
void Map::MapBase::shiftViewport(const Point &delta) {
|
||||
Point &topLeft = _viewportPos._topLeft;
|
||||
topLeft += delta;
|
||||
|
||||
// Shift the viewport, but constraining the map to fill up the screen
|
||||
topLeft.x = CLIP(topLeft.x, (int16)0, (int16)(width() - _viewportPos._size.x));
|
||||
topLeft.y = CLIP(topLeft.y, (int16)0, (int16)(height() - _viewportPos._size.y));
|
||||
}
|
||||
|
||||
void Map::MapBase::addWidget(MapWidget *widget) {
|
||||
_widgets.push_back(MapWidgetPtr(widget));
|
||||
}
|
||||
|
||||
void Map::MapBase::removeWidget(MapWidget *widget) {
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
if (_widgets[idx].get() == widget) {
|
||||
_widgets.remove_at(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::MapBase::getTileAt(const Point &pt, MapTile *tile) {
|
||||
tile->clear();
|
||||
|
||||
// Get the base tile
|
||||
tile->_tileNum = tile->_tileId = _data[pt.y][pt.x];
|
||||
|
||||
// Check for any widget on that map tile
|
||||
for (int idx = (int)_widgets.size() - 1; idx >= 0; --idx) {
|
||||
MapWidget *widget = _widgets[idx].get();
|
||||
if (widget->_position == pt) {
|
||||
tile->_widgetNum = idx;
|
||||
tile->_widget = widget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::MapBase::update() {
|
||||
// Call the update method of each widget, to allow for things like npc movement, etc.
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx)
|
||||
_widgets[idx].get()->update(true);
|
||||
|
||||
// Call the update method of each widget, to allow for things like npc movement, etc.
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx)
|
||||
_widgets[idx].get()->update(false);
|
||||
}
|
||||
|
||||
Point Map::MapBase::getPosition() const {
|
||||
return _playerWidget->_position;
|
||||
}
|
||||
|
||||
void Map::MapBase::setPosition(const Point &pt) {
|
||||
_playerWidget->_position = pt;
|
||||
}
|
||||
|
||||
Direction Map::MapBase::getDirection() const {
|
||||
return _playerWidget->_direction;
|
||||
}
|
||||
|
||||
void Map::MapBase::setDirection(Direction dir) {
|
||||
_playerWidget->_direction = dir;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void MapWidget::synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_position.x);
|
||||
s.syncAsSint16LE(_position.y);
|
||||
s.syncAsByte(_direction);
|
||||
s.syncString(_name);
|
||||
}
|
||||
|
||||
void MapWidget::addInfoMsg(const Common::String &text, bool newLine) {
|
||||
CInfoMsg msg(text, newLine);
|
||||
msg.execute(_game->getView());
|
||||
}
|
||||
|
||||
MapWidget::CanMove MapWidget::canMoveTo(const Point &destPos) {
|
||||
if (destPos.x < 0 || destPos.y < 0 || destPos.x >= (int)_map->width() || destPos.y >= (int)_map->height()) {
|
||||
// If the map is fixed, allow moving beyond it's edges so it can be left
|
||||
if (!_map->isMapWrapped())
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Get the details of the position
|
||||
MapTile destTile;
|
||||
_map->getTileAt(destPos, &destTile);
|
||||
|
||||
// If there's a widget blocking the tile, return false
|
||||
if (destTile._widget && destTile._widget->isBlocking())
|
||||
return NO;
|
||||
|
||||
return UNSET;
|
||||
}
|
||||
|
||||
void MapWidget::moveTo(const Point &destPos, Direction dir) {
|
||||
// If no direction is specified, we'll need to figure it out relative to the old position
|
||||
if (dir == DIR_NONE) {
|
||||
Point delta = destPos - _position;
|
||||
if (ABS(delta.x) > ABS(delta.y))
|
||||
_direction = delta.x > 0 ? DIR_EAST : DIR_WEST;
|
||||
else if (delta.y != 0)
|
||||
_direction = delta.y > 0 ? DIR_SOUTH : DIR_NORTH;
|
||||
} else {
|
||||
_direction = dir;
|
||||
}
|
||||
|
||||
// Set new location
|
||||
_position = destPos;
|
||||
|
||||
// Handle wrap around if need be on maps that wrap
|
||||
if (_map->isMapWrapped()) {
|
||||
if (_position.x < 0)
|
||||
_position.x += _map->width();
|
||||
else if (_position.x >= (int)_map->width())
|
||||
_position.x -= _map->width();
|
||||
if (_position.y < 0)
|
||||
_position.y += _map->height();
|
||||
else if (_position.y >= (int)_map->height())
|
||||
_position.y -= _map->height();
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void Map::clear() {
|
||||
if (_mapArea)
|
||||
_mapArea->clear();
|
||||
_mapArea = nullptr;
|
||||
}
|
||||
|
||||
void Map::load(MapId mapId) {
|
||||
_mapArea = nullptr;
|
||||
}
|
||||
|
||||
void Map::synchronize(Common::Serializer &s) {
|
||||
int mapId;
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Saving
|
||||
mapId = _mapArea->getMapId();
|
||||
s.syncAsUint16LE(mapId);
|
||||
} else {
|
||||
// Loading
|
||||
s.syncAsUint16LE(mapId);
|
||||
load(mapId);
|
||||
}
|
||||
|
||||
_mapArea->synchronize(s);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
562
engines/ultima/shared/core/map.h
Normal file
562
engines/ultima/shared/core/map.h
Normal file
@@ -0,0 +1,562 @@
|
||||
/* 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 ULTIMA_SHARED_CORE_MAP_H
|
||||
#define ULTIMA_SHARED_CORE_MAP_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/ptr.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/gfx/dungeon_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define REGISTER_WIDGET(NAME) if (name == #NAME) return new Widgets::NAME(_game, (Ultima1Map::MapBase *)map)
|
||||
#define DECLARE_WIDGET(NAME) const char *getClassName() const override { return #NAME; }
|
||||
|
||||
enum Direction {
|
||||
DIR_NONE = 0,
|
||||
DIR_LEFT = 1, DIR_RIGHT = 2, DIR_UP = 3, DIR_DOWN = 4,
|
||||
DIR_WEST = 1, DIR_EAST = 2, DIR_NORTH = 3, DIR_SOUTH = 4
|
||||
};
|
||||
|
||||
typedef byte MapCell;
|
||||
typedef int MapId;
|
||||
|
||||
class Game;
|
||||
class MapWidget;
|
||||
|
||||
typedef Common::SharedPtr<MapWidget> MapWidgetPtr;
|
||||
|
||||
/**
|
||||
* Contains data about a given position within the map
|
||||
*/
|
||||
class MapTile {
|
||||
public:
|
||||
int _tileId; // Tile Id
|
||||
int _tileNum; // Tile number to display. Normally equals Tile Id, but can differ in rare cases
|
||||
int _widgetNum; // Widget number, if any
|
||||
MapWidget *_widget; // Widget pointer
|
||||
int _itemNum; // Item number, if any
|
||||
// Dungeon tile flags
|
||||
bool _isDoor, _isSecretDoor;
|
||||
bool _isLadderUp, _isLadderDown;
|
||||
bool _isWall, _isHallway, _isBeams;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MapTile() : _tileNum(-1), _tileId(-1), _widgetNum(-1), _widget(nullptr), _itemNum(-1),
|
||||
_isDoor(false), _isSecretDoor(false), _isLadderUp(false), _isLadderDown(false), _isWall(false),
|
||||
_isHallway(false), _isBeams(false) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MapTile() {}
|
||||
|
||||
/**
|
||||
* Clears the map tile information
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Returns true if the tile is a door in a dungeon
|
||||
*/
|
||||
bool isDoor() const { return _isDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if the tile is a wall or secret door in a dungeon
|
||||
*/
|
||||
bool isWallOrSecretDoor() const { return _isWall || _isSecretDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if the tile in a dungeon is a type that has walls on it: walls, doors, or secret doors
|
||||
*/
|
||||
bool isWallOrDoorway() const { return _isWall || _isDoor || _isSecretDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if a tile is a solid type within a dungeon
|
||||
*/
|
||||
bool isSolid() const { return !(_isHallway || _isLadderUp || _isLadderDown || _isBeams); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for managing maps within the game
|
||||
*/
|
||||
class Map {
|
||||
/**
|
||||
* Stores state about the current viewport being displayed. It's kept as part of the Map class
|
||||
* as a convenience to be alongside the current party position
|
||||
*/
|
||||
struct ViewportPosition {
|
||||
Point _topLeft; // Top, left tile position for viewport
|
||||
Point _size; // Size of the viewport. Just in case we ever allow it to change
|
||||
MapId _mapId; // Maze the viewport is for. Used to detect when the map changes
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ViewportPosition() : _topLeft(-1, -1), _mapId(-1) {}
|
||||
|
||||
/**
|
||||
* Returns true if the viewport is in a valid state
|
||||
*/
|
||||
bool isValid() const { return _mapId != -1; }
|
||||
|
||||
/**
|
||||
* Handles loading and saving viewport
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_topLeft.x);
|
||||
s.syncAsUint16LE(_topLeft.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the viewport position, so it'll get recalculated the next call to getViewportPosition
|
||||
*/
|
||||
void reset() { _mapId = -1; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal class used for storing the data for a row
|
||||
*/
|
||||
struct MapCellsRow {
|
||||
public:
|
||||
Common::Array<MapCell> _data;
|
||||
public:
|
||||
byte &operator[](int idx) { return _data[idx]; }
|
||||
byte operator[](int idx) const { return _data[idx]; }
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* Base class for specific map types
|
||||
*/
|
||||
class MapBase {
|
||||
private:
|
||||
Map *_map; // Map manager reference
|
||||
protected:
|
||||
MapId _mapId; // The map Id
|
||||
uint _mapIndex; // Index of map within the group of same maps
|
||||
uint _mapStyle; // Map style category for towns & castles
|
||||
ViewportPosition _viewportPos; // Viewport position
|
||||
protected:
|
||||
/**
|
||||
* Set the size of the map
|
||||
*/
|
||||
void setDimensions(const Point &size);
|
||||
public:
|
||||
Point _size; // X, Y size of the map
|
||||
Point _tilesPerOrigTile; // For enhanced modes, number of tiles per original game tile
|
||||
Common::String _name; // Name of map, if applicable
|
||||
MapWidget *_playerWidget; // Current means of transport, even if on foot
|
||||
Common::Array<MapWidgetPtr> _widgets; // Party, monsteres, transports, etc.
|
||||
Common::Array<MapCellsRow> _data; // Data for the map
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MapBase(Game *game, Map *map) : _map(map), _playerWidget(nullptr), _mapId(0), _mapIndex(0),
|
||||
_mapStyle(0) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MapBase() {}
|
||||
|
||||
/**
|
||||
* Handles loading and saving the map's data
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Adds a widget to the map
|
||||
*/
|
||||
void addWidget(MapWidget *widget);
|
||||
|
||||
/**
|
||||
* Removes a widget from the map
|
||||
*/
|
||||
void removeWidget(MapWidget *widget);
|
||||
|
||||
/**
|
||||
* Clears all map data
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Gets a tile at a given position
|
||||
*/
|
||||
virtual void getTileAt(const Point &pt, MapTile *tile);
|
||||
|
||||
/**
|
||||
* Resets the viewport when the viewport changes
|
||||
*/
|
||||
void resetViewport();
|
||||
|
||||
/**
|
||||
* Get the viewport position
|
||||
*/
|
||||
virtual Point getViewportPosition(const Point &viewportSize);
|
||||
|
||||
/**
|
||||
* Load the map
|
||||
*/
|
||||
virtual void load(MapId mapId);
|
||||
|
||||
/**
|
||||
* Changes the level. Only applicable to dungeon maps which have levels
|
||||
* @param delta Delta to change dungeon level by
|
||||
* @returns False if dungeon left, true if still within dungeon
|
||||
*/
|
||||
virtual bool changeLevel(int delta) { return true; }
|
||||
|
||||
/**
|
||||
* Get the current map level
|
||||
*/
|
||||
virtual uint getLevel() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns whether the map wraps around to the other side at it's edges (i.e. the overworld)
|
||||
*/
|
||||
virtual bool isMapWrapped() const { return false; }
|
||||
|
||||
/**
|
||||
* Returns the width of the map
|
||||
*/
|
||||
size_t width() const { return _size.x; }
|
||||
|
||||
/**
|
||||
* Returns the height of the map
|
||||
*/
|
||||
size_t height() const { return _size.y; }
|
||||
|
||||
/**
|
||||
* Get the current position
|
||||
*/
|
||||
Point getPosition() const;
|
||||
|
||||
/**
|
||||
* Set the current position
|
||||
*/
|
||||
void setPosition(const Point &pt);
|
||||
|
||||
/**
|
||||
* Get the current direction
|
||||
*/
|
||||
Direction getDirection() const;
|
||||
|
||||
/**
|
||||
* Set the current direction
|
||||
*/
|
||||
void setDirection(Direction dir);
|
||||
|
||||
/**
|
||||
* Returns a delta for the cell in front of the player based on the direction they're facing
|
||||
*/
|
||||
Point getDirectionDelta() const;
|
||||
|
||||
/**
|
||||
* Gets a point relative to the current position
|
||||
*/
|
||||
virtual Point getDeltaPosition(const Point &delta);
|
||||
|
||||
/**
|
||||
* Returns the map Id
|
||||
*/
|
||||
MapId getMapId() const { return _mapId; }
|
||||
|
||||
/**
|
||||
* Gets the map Index
|
||||
*/
|
||||
uint getMapIndex() const { return _mapIndex; }
|
||||
|
||||
/**
|
||||
* Shifts the viewport by a given delta
|
||||
*/
|
||||
virtual void shiftViewport(const Point &delta);
|
||||
|
||||
/**
|
||||
* Updates the map at the end of a turn
|
||||
*/
|
||||
virtual void update();
|
||||
};
|
||||
protected:
|
||||
MapBase *_mapArea;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Map() : _mapArea(nullptr) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Map() {}
|
||||
|
||||
/**
|
||||
* Load a given map
|
||||
*/
|
||||
virtual void load(MapId mapId);
|
||||
|
||||
/**
|
||||
* Clears all map data
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Handles loading and saving the map's data
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Instantiates a widget type by name
|
||||
*/
|
||||
virtual MapWidget *createWidget(Map::MapBase *map, const Common::String &name) = 0;
|
||||
|
||||
/**
|
||||
* Gets a tile at a given position
|
||||
*/
|
||||
void getTileAt(const Point &pt, MapTile *tile) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getTileAt(pt, tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the viewport position
|
||||
*/
|
||||
Point getViewportPosition(const Point &viewportSize) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getViewportPosition(viewportSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the map
|
||||
*/
|
||||
size_t width() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->width();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the map
|
||||
*/
|
||||
size_t height() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->height();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current position
|
||||
*/
|
||||
Point getPosition() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position
|
||||
*/
|
||||
void setPosition(const Point &pt) {
|
||||
assert(_mapArea);
|
||||
_mapArea->setPosition(pt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current direction
|
||||
*/
|
||||
Direction getDirection() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current direction
|
||||
*/
|
||||
void setDirection(Direction dir) {
|
||||
assert(_mapArea);
|
||||
_mapArea->setDirection(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a delta for the cell in front of the player based on the direction they're facing
|
||||
*/
|
||||
Point getDirectionDelta() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDirectionDelta();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a point relative to the current position
|
||||
*/
|
||||
Point getDeltaPosition(const Point &delta) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDeltaPosition(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts the viewport by a given delta
|
||||
*/
|
||||
void shiftViewport(const Point &delta) {
|
||||
assert(_mapArea);
|
||||
_mapArea->shiftViewport(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the map there are for each tile in the original game.
|
||||
* This allows for more detailed maps in the enhanced game modes
|
||||
*/
|
||||
Point getTilesPerOrigTile() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_tilesPerOrigTile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the map
|
||||
*/
|
||||
Common::String getName() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active widget that the player is controlling
|
||||
*/
|
||||
MapWidget *getPlayerWidget() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_playerWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param delta Delta to change dungeon level by
|
||||
* @returns False if dungeon left, true if still within dungeon
|
||||
*/
|
||||
bool changeLevel(int delta) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->changeLevel(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current map level
|
||||
*/
|
||||
uint getLevel() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the map wraps around to the other side at it's edges (i.e. the overworld)
|
||||
*/
|
||||
bool isMapWrapped() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->isMapWrapped();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the map at the end of a turn
|
||||
*/
|
||||
void update() {
|
||||
assert(_mapArea);
|
||||
return _mapArea->update();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for things that appear within a map, such as monsters, transports, or people
|
||||
*/
|
||||
class MapWidget {
|
||||
protected:
|
||||
Game *_game; // Game reference
|
||||
Map::MapBase *_map; // Map reference
|
||||
public:
|
||||
Point _position; // Position within the map
|
||||
Direction _direction; // Direction
|
||||
Common::String _name; // Name of widget
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MapWidget(Game *game, Map::MapBase *map) : _game(game), _map(map) {}
|
||||
MapWidget(Game *game, Map::MapBase *map, const Point &pt, Direction dir = DIR_NONE) : _game(game), _map(map), _position(pt), _direction(dir) {}
|
||||
MapWidget(Game *game, Map::MapBase *map, const Common::String &name, const Point &pt, Direction dir = DIR_NONE) :
|
||||
_game(game), _map(map), _name(name), _position(pt), _direction(dir) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MapWidget() {}
|
||||
|
||||
/**
|
||||
* Return a name for a widget class if it can be synchronized to savegames
|
||||
*/
|
||||
virtual const char *getClassName() const { return nullptr; }
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Adds a text string to the info area
|
||||
* @param text Text to add
|
||||
* @param newLine Whether to apply a newline at the end
|
||||
*/
|
||||
void addInfoMsg(const Common::String &text, bool newLine = true);
|
||||
|
||||
/**
|
||||
* Get the tile for the widget
|
||||
*/
|
||||
virtual uint getTileNum() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns true if the player can move onto a tile the widget occupies
|
||||
*/
|
||||
virtual bool isBlocking() const { return false; }
|
||||
|
||||
/**
|
||||
* Called to update the widget at the end of a turn
|
||||
* @param isPreUpdate Update is called twice in succession during the end of turn update.
|
||||
* Once with true for all widgets, then with it false
|
||||
*/
|
||||
virtual void update(bool isPreUpdate) {}
|
||||
|
||||
enum CanMove { UNSET = 0, YES = 1, NO = 2 };
|
||||
|
||||
/**
|
||||
* Returns true if the given widget can move to a given position on the map
|
||||
*/
|
||||
virtual CanMove canMoveTo(const Point &destPos);
|
||||
|
||||
/**
|
||||
* Moves the widget to a given position
|
||||
* @param destPos Specified new position
|
||||
* @param dir Optional explicit direction to set. If not specified,
|
||||
* the direction will be set relative to the position moved from
|
||||
*/
|
||||
virtual void moveTo(const Point &destPos, Direction dir = DIR_NONE);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
45
engines/ultima/shared/core/message_target.cpp
Normal file
45
engines/ultima/shared/core/message_target.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/core/message_target.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
ClassDef MessageTarget::type() {
|
||||
return ClassDef("MessageTarget", &BaseObject::type);
|
||||
}
|
||||
|
||||
const MSGMAP *MessageTarget::getMessageMap() const {
|
||||
return getThisMessageMap();
|
||||
}
|
||||
|
||||
const MSGMAP *MessageTarget::getThisMessageMap() {
|
||||
static const MSGMAP_ENTRY _messageEntries[] = {
|
||||
{ (PMSG)nullptr, nullptr }
|
||||
};
|
||||
|
||||
static const MSGMAP messageMap = { nullptr, &_messageEntries[0] };
|
||||
return &messageMap;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
106
engines/ultima/shared/core/message_target.h
Normal file
106
engines/ultima/shared/core/message_target.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_MESSAGE_TARGET_H
|
||||
#define ULTIMA_SHARED_CORE_MESSAGE_TARGET_H
|
||||
|
||||
#include "ultima/shared/core/base_object.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class MessageTarget;
|
||||
class CMessage;
|
||||
|
||||
typedef bool (MessageTarget:: *PMSG)(CMessage *msg);
|
||||
|
||||
struct MSGMAP_ENTRY {
|
||||
PMSG _fn;
|
||||
ClassDefFn _classDef;
|
||||
};
|
||||
|
||||
struct MSGMAP {
|
||||
const MSGMAP *(*pFnGetBaseMap)();
|
||||
const MSGMAP_ENTRY *lpEntries;
|
||||
};
|
||||
|
||||
#define DECLARE_MESSAGE_MAP \
|
||||
protected: \
|
||||
static const Ultima::Shared::MSGMAP *getThisMessageMap(); \
|
||||
const Ultima::Shared::MSGMAP *getMessageMap() const override
|
||||
|
||||
#define DECLARE_MESSAGE_MAP_BASE \
|
||||
protected: \
|
||||
static const Ultima::Shared::MSGMAP *getThisMessageMap(); \
|
||||
virtual const Ultima::Shared::MSGMAP *getMessageMap() const
|
||||
|
||||
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
|
||||
Ultima::Shared::ClassDef theClass::type() { return Ultima::Shared::ClassDef(#theClass, &baseClass::type); } \
|
||||
const Ultima::Shared::MSGMAP *theClass::getMessageMap() const \
|
||||
{ return getThisMessageMap(); } \
|
||||
const Ultima::Shared::MSGMAP *theClass::getThisMessageMap() \
|
||||
{ \
|
||||
typedef theClass ThisClass; \
|
||||
typedef baseClass TheBaseClass; \
|
||||
typedef bool (theClass::*FNPTR)(Ultima::Shared::CMessage *msg); \
|
||||
static const Ultima::Shared::MSGMAP_ENTRY _messageEntries[] = {
|
||||
|
||||
#define ON_MESSAGE(msgClass) \
|
||||
{ static_cast<Ultima::Shared::PMSG>((FNPTR)&ThisClass::msgClass), &C##msgClass::type },
|
||||
|
||||
#define END_MESSAGE_MAP() \
|
||||
{ (Ultima::Shared::PMSG)nullptr, nullptr } \
|
||||
}; \
|
||||
static const Ultima::Shared::MSGMAP messageMap = \
|
||||
{ &TheBaseClass::getThisMessageMap, &_messageEntries[0] }; \
|
||||
return &messageMap; \
|
||||
}
|
||||
|
||||
#define EMPTY_MESSAGE_MAP(theClass, baseClass) \
|
||||
Ultima::Shared::ClassDef theClass::type() { return Ultima::Shared::ClassDef(#theClass, &baseClass::type); } \
|
||||
const Ultima::Shared::MSGMAP *theClass::getMessageMap() const \
|
||||
{ return getThisMessageMap(); } \
|
||||
const Ultima::Shared::MSGMAP *theClass::getThisMessageMap() \
|
||||
{ \
|
||||
typedef baseClass TheBaseClass; \
|
||||
static const Ultima::Shared::MSGMAP_ENTRY _messageEntries[] = { \
|
||||
{ (Ultima::Shared::PMSG)nullptr, nullptr } \
|
||||
}; \
|
||||
static const Ultima::Shared::MSGMAP messageMap = \
|
||||
{ &TheBaseClass::getThisMessageMap, &_messageEntries[0] }; \
|
||||
return &messageMap; \
|
||||
} \
|
||||
enum { DUMMY##theClass }
|
||||
|
||||
/**
|
||||
* The immediate descendant of the base object, this implements the base class for objects
|
||||
* that can receive messages
|
||||
*/
|
||||
class MessageTarget: public BaseObject {
|
||||
DECLARE_MESSAGE_MAP_BASE;
|
||||
public:
|
||||
CLASSDEF;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
107
engines/ultima/shared/core/mouse_cursor.cpp
Normal file
107
engines/ultima/shared/core/mouse_cursor.cpp
Normal 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 "graphics/cursorman.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "ultima/shared/core/mouse_cursor.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
void MouseCursor::MouseCursorData::load(Common::SeekableReadStream &s) {
|
||||
_hotspot.x = s.readSint16LE();
|
||||
_hotspot.y = s.readSint16LE();
|
||||
for (int idx = 0; idx < 16; ++idx)
|
||||
_pixels[idx] = s.readUint16LE();
|
||||
for (int idx = 0; idx < 16; ++idx)
|
||||
_mask[idx] = s.readUint16LE();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
MouseCursor::MouseCursor() : _cursorId(-1) {
|
||||
/*
|
||||
loadCursors();
|
||||
_cursorId = -1;
|
||||
setCursor(0);
|
||||
*/
|
||||
}
|
||||
|
||||
void MouseCursor::loadCursors() {
|
||||
_cursors.clear();
|
||||
|
||||
File f("TODO");
|
||||
while (f.pos() < f.size()) {
|
||||
_cursors.push_back(MouseCursorData());
|
||||
MouseCursorData &mc = _cursors.back();
|
||||
|
||||
mc._hotspot.x = f.readSint16LE();
|
||||
mc._hotspot.y = f.readSint16LE();
|
||||
for (int idx = 0; idx < 16; ++idx)
|
||||
mc._mask[idx] = f.readUint16LE();
|
||||
for (int idx = 0; idx < 16; ++idx)
|
||||
mc._pixels[idx] = f.readUint16LE();
|
||||
}
|
||||
}
|
||||
|
||||
void MouseCursor::setCursor(int cursorId) {
|
||||
// No need to do anything if we're already showing the desired cursor
|
||||
if (cursorId == _cursorId)
|
||||
return;
|
||||
_cursorId = cursorId;
|
||||
|
||||
// Set up a temporary surface for rendering the cursor onto
|
||||
Graphics::ManagedSurface s(16, 16);
|
||||
s.fillRect(s.getBounds(), 0xff);
|
||||
|
||||
const MouseCursorData &data = _cursors[cursorId];
|
||||
const uint16 *pixelsP = data._pixels, *maskP = data._mask;
|
||||
|
||||
// Iterate trhough the lines to build up the cursor
|
||||
for (int y = 0; y < CURSOR_HEIGHT; ++y) {
|
||||
uint16 pixVal = *pixelsP++, maskVal = *maskP++;
|
||||
int bitMask = 0x8000;
|
||||
byte *destP = (byte *)s.getBasePtr(0, y);
|
||||
|
||||
for (int x = 0; x < CURSOR_WIDTH; ++x, ++destP, bitMask >>= 1) {
|
||||
if (pixVal & bitMask)
|
||||
*destP = 15;
|
||||
else if (!(maskVal & bitMask))
|
||||
*destP = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the generated surface onto the ScummVM cursor manager
|
||||
CursorMan.replaceCursor(s, data._hotspot.x, data._hotspot.y, 0xff);
|
||||
}
|
||||
|
||||
void MouseCursor::show() {
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void MouseCursor::hide() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
103
engines/ultima/shared/core/mouse_cursor.h
Normal file
103
engines/ultima/shared/core/mouse_cursor.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_MOUSE_CURSOR_H
|
||||
#define ULTIMA_SHARED_CORE_MOUSE_CURSOR_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define CURSOR_WIDTH 16
|
||||
#define CURSOR_HEIGHT 16
|
||||
/*
|
||||
namespace Early {
|
||||
|
||||
enum CursorId {
|
||||
CURSOR_ARROW = 0
|
||||
};
|
||||
|
||||
} // End of namespace Early
|
||||
|
||||
namespace Later {
|
||||
namespace Xanth {
|
||||
|
||||
enum CursorId {
|
||||
CURSOR_BIG_ARROW = 0,
|
||||
CURSOR_SMALL_ARROW = 1,
|
||||
CURSOR_TICK = 2,
|
||||
CURSOR_HOURGLASS = 3
|
||||
};
|
||||
|
||||
} // End of namespace Xanth
|
||||
} // End of namespace Later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles the dislay and management of the on-screen mouse cursor
|
||||
*/
|
||||
class MouseCursor {
|
||||
struct MouseCursorData {
|
||||
Point _hotspot;
|
||||
uint16 _pixels[16];
|
||||
uint16 _mask[16];
|
||||
|
||||
void load(Common::SeekableReadStream &s);
|
||||
};
|
||||
private:
|
||||
Common::Array<MouseCursorData> _cursors;
|
||||
int _cursorId;
|
||||
private:
|
||||
/**
|
||||
* Loads the mouse cursors
|
||||
*/
|
||||
void loadCursors();
|
||||
public:
|
||||
MouseCursor();
|
||||
|
||||
/**
|
||||
* Sets the active cursor
|
||||
*/
|
||||
void setCursor(int cursorId);
|
||||
|
||||
/**
|
||||
* Returns the curent cursor
|
||||
*/
|
||||
int getCursor() const { return _cursorId; }
|
||||
|
||||
/**
|
||||
* Make the mouse cursor visible
|
||||
*/
|
||||
void show();
|
||||
|
||||
/**
|
||||
* Hide the mouse cursor
|
||||
*/
|
||||
void hide();
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
30
engines/ultima/shared/core/named_item.cpp
Normal file
30
engines/ultima/shared/core/named_item.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/* 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 "ultima/shared/core/named_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EMPTY_MESSAGE_MAP(NamedItem, TreeItem);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
51
engines/ultima/shared/core/named_item.h
Normal file
51
engines/ultima/shared/core/named_item.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_NAMED_ITEM_H
|
||||
#define ULTIMA_SHARED_CORE_NAMED_ITEM_H
|
||||
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* Derived tree item class that adds a name that can be used to direct messages to later
|
||||
*/
|
||||
class NamedItem: public TreeItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
public:
|
||||
Common::String _name;
|
||||
public:
|
||||
CLASSDEF;
|
||||
NamedItem() {}
|
||||
NamedItem(const Common::String &name) : _name(name) {}
|
||||
|
||||
/**
|
||||
* Gets the name of the item, if any
|
||||
*/
|
||||
const Common::String getName() const override { return _name; }
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
67
engines/ultima/shared/core/party.cpp
Normal file
67
engines/ultima/shared/core/party.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 "ultima/shared/core/party.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
Party::~Party() {
|
||||
for (uint idx = 0; idx < _characters.size(); ++idx)
|
||||
delete _characters[idx];
|
||||
}
|
||||
|
||||
void Party::add(Character *c) {
|
||||
_characters.push_back(c);
|
||||
}
|
||||
|
||||
void Party::synchronize(Common::Serializer &s) {
|
||||
uint partyCount = _characters.size();
|
||||
s.syncAsByte(partyCount);
|
||||
if (s.isLoading())
|
||||
assert(partyCount == _characters.size());
|
||||
|
||||
// Iterate through the characters of the party
|
||||
for (uint idx = 0; idx < _characters.size(); ++idx)
|
||||
_characters[idx]->synchronize(s);
|
||||
}
|
||||
|
||||
|
||||
bool Party::isDead() const {
|
||||
for (uint idx = 0; idx < _characters.size(); ++idx) {
|
||||
if ((*this)[idx]._hitPoints > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Party::isFoodless() const {
|
||||
for (uint idx = 0; idx < _characters.size(); ++idx) {
|
||||
if ((*this)[idx]._food > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
76
engines/ultima/shared/core/party.h
Normal file
76
engines/ultima/shared/core/party.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_PARTY_H
|
||||
#define ULTIMA_SHARED_CORE_PARTY_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/character.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* Base class for the player's party
|
||||
*/
|
||||
class Party {
|
||||
protected:
|
||||
Common::Array<Character *> _characters;
|
||||
public:
|
||||
~Party();
|
||||
|
||||
/**
|
||||
* Add a character to the party
|
||||
*/
|
||||
void add(Character *c);
|
||||
|
||||
/**
|
||||
* Casting operator for convenient access to the first character
|
||||
*/
|
||||
operator Character &() const { return *_characters.front(); }
|
||||
|
||||
/**
|
||||
* Casting operator for convenient access to the first character
|
||||
*/
|
||||
operator Character *() const { return _characters.front(); }
|
||||
|
||||
/**
|
||||
* Synchronize data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Returns true if the party is dead
|
||||
*/
|
||||
bool isDead() const;
|
||||
|
||||
/**
|
||||
* Returns true if the party has no food
|
||||
*/
|
||||
bool isFoodless() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
63
engines/ultima/shared/core/rect.h
Normal file
63
engines/ultima/shared/core/rect.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_CORE_RECT_H
|
||||
#define ULTIMA_SHARED_CORE_RECT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class TextPoint;
|
||||
|
||||
typedef Common::Rect Rect;
|
||||
|
||||
typedef Common::Point Point;
|
||||
|
||||
/**
|
||||
* Simple derived point class that converts text coordinates to graphic screen coordinates
|
||||
*/
|
||||
class TextPoint : public Common::Point {
|
||||
public:
|
||||
TextPoint() : Common::Point() {}
|
||||
TextPoint(int16 x1, int16 y1) : Common::Point(x1 * 8, y1 * 8) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple derived rect class that converts text coordinates to graphic screen coordinates
|
||||
*/
|
||||
class TextRect : public Common::Rect {
|
||||
public:
|
||||
TextRect() : Common::Rect() {}
|
||||
TextRect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1 * 8, y1 * 8, (x2 + 1) * 8, (y2 + 1) * 8) {}
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
|
||||
using Shared::Rect;
|
||||
using Shared::Point;
|
||||
using Shared::TextPoint;
|
||||
using Shared::TextRect;
|
||||
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
66
engines/ultima/shared/core/str.cpp
Normal file
66
engines/ultima/shared/core/str.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/core/str.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
int String::indexOf(char c) const {
|
||||
const char *s = strchr(c_str(), c);
|
||||
return s ? s - c_str() : -1;
|
||||
}
|
||||
|
||||
int String::indexOf(const String &chars) const {
|
||||
uint minIndex = size();
|
||||
|
||||
for (uint idx = 0; idx < chars.size(); ++idx) {
|
||||
int charIndex = indexOf(chars[idx]);
|
||||
if (charIndex != -1 && charIndex < (int)minIndex)
|
||||
minIndex = charIndex;
|
||||
}
|
||||
|
||||
return minIndex == size() ? -1 : minIndex;
|
||||
}
|
||||
|
||||
StringArray String::split(char c) const {
|
||||
return split(String(c));
|
||||
}
|
||||
|
||||
StringArray String::split(const String &chars) const {
|
||||
StringArray results;
|
||||
String temp = *this;
|
||||
int idx;
|
||||
|
||||
// Iterate through the text
|
||||
while ((idx = temp.indexOf(chars)) != -1) {
|
||||
results.push_back(String(temp.c_str(), temp.c_str() + idx));
|
||||
temp = String(temp.c_str() + idx + 1);
|
||||
}
|
||||
|
||||
if (!empty() && !temp.empty())
|
||||
results.push_back(temp);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
76
engines/ultima/shared/core/str.h
Normal file
76
engines/ultima/shared/core/str.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_STR_H
|
||||
#define ULTIMA_STR_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class String;
|
||||
|
||||
typedef Common::Array<String> StringArray;
|
||||
|
||||
/**
|
||||
* Derived string class
|
||||
*/
|
||||
class String : public Common::String {
|
||||
public:
|
||||
String() : Common::String() {}
|
||||
String(const char *str) : Common::String(str) {}
|
||||
String(const char *str, uint32 len) : Common::String(str, len) {}
|
||||
String(const char *beginP, const char *endP) : Common::String(beginP, endP) {}
|
||||
String(const String &str) : Common::String(str) {}
|
||||
String(const Common::String &str) : Common::String(str) {}
|
||||
explicit String(char c) : Common::String(c) {}
|
||||
String& operator=(const String &str) { this->Common::String::operator=(str); return *this; }
|
||||
|
||||
/**
|
||||
* Returns the index of a given character, or -1 if not present
|
||||
*/
|
||||
int indexOf(char c) const;
|
||||
|
||||
/**
|
||||
* Returns the earliest index of any character in a passed set of characters, or -1 if not present
|
||||
*/
|
||||
int indexOf(const String &chars) const;
|
||||
|
||||
/**
|
||||
* Splits up a text string by a given character
|
||||
*/
|
||||
StringArray split(char c) const;
|
||||
|
||||
/**
|
||||
* Splits up a text string by any of the characters in the passed string
|
||||
*/
|
||||
StringArray split(const String &chars) const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
|
||||
using Shared::String;
|
||||
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
221
engines/ultima/shared/core/tree_item.cpp
Normal file
221
engines/ultima/shared/core/tree_item.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/* 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 "ultima/shared/core/tree_item.h"
|
||||
#include "ultima/shared/core/named_item.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EMPTY_MESSAGE_MAP(TreeItem, MessageTarget);
|
||||
|
||||
TreeItem::TreeItem() : _parent(nullptr), _firstChild(nullptr),
|
||||
_nextSibling(nullptr), _priorSibling(nullptr),
|
||||
_disposeAfterUse(DisposeAfterUse::NO) {
|
||||
}
|
||||
|
||||
Game *TreeItem::getGame() {
|
||||
TreeItem *treeItem = this;
|
||||
|
||||
while (treeItem->getParent()) {
|
||||
treeItem = treeItem->getParent();
|
||||
}
|
||||
|
||||
return dynamic_cast<Game *>(treeItem);
|
||||
}
|
||||
|
||||
const Game *TreeItem::getGame() const {
|
||||
const TreeItem *treeItem = this;
|
||||
|
||||
while (treeItem->getParent()) {
|
||||
treeItem = treeItem->getParent();
|
||||
}
|
||||
|
||||
return dynamic_cast<const Game *>(treeItem);
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::getLastSibling() {
|
||||
TreeItem *item = this;
|
||||
while (item->getNextSibling())
|
||||
item = item->getNextSibling();
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
Gfx::VisualItem *TreeItem::getView() {
|
||||
return getGame()->getView();
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::getLastChild() const {
|
||||
if (!_firstChild)
|
||||
return nullptr;
|
||||
return _firstChild->getLastSibling();
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::scan(TreeItem *item) const {
|
||||
if (_firstChild)
|
||||
return _firstChild;
|
||||
|
||||
const TreeItem *treeItem = this;
|
||||
while (treeItem != item) {
|
||||
if (treeItem->_nextSibling)
|
||||
return treeItem->_nextSibling;
|
||||
|
||||
treeItem = treeItem->_parent;
|
||||
if (!treeItem)
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::findChildInstanceOf(const ClassDef &classDef) const {
|
||||
for (TreeItem *treeItem = _firstChild; treeItem; treeItem = treeItem->getNextSibling()) {
|
||||
if (treeItem->isInstanceOf(classDef))
|
||||
return treeItem;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::findNextInstanceOf(const ClassDef &classDef, TreeItem *startItem) const {
|
||||
TreeItem *treeItem = startItem ? startItem->getNextSibling() : getFirstChild();
|
||||
|
||||
for (; treeItem; treeItem = treeItem->getNextSibling()) {
|
||||
if (treeItem->isInstanceOf(classDef))
|
||||
return treeItem;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TreeItem::addUnder(TreeItem *newParent) {
|
||||
if (newParent->_firstChild)
|
||||
addSibling(newParent->_firstChild->getLastSibling());
|
||||
else
|
||||
setParent(newParent);
|
||||
}
|
||||
|
||||
void TreeItem::addChild(TreeItem *child) {
|
||||
child->addUnder(this);
|
||||
}
|
||||
|
||||
void TreeItem::setParent(TreeItem *newParent) {
|
||||
_parent = newParent;
|
||||
_priorSibling = nullptr;
|
||||
_nextSibling = newParent->_firstChild;
|
||||
|
||||
if (newParent->_firstChild)
|
||||
newParent->_firstChild->_priorSibling = this;
|
||||
newParent->_firstChild = this;
|
||||
}
|
||||
|
||||
void TreeItem::addSibling(TreeItem *item) {
|
||||
_priorSibling = item;
|
||||
_nextSibling = item->_nextSibling;
|
||||
_parent = item->_parent;
|
||||
|
||||
if (item->_nextSibling)
|
||||
item->_nextSibling->_priorSibling = this;
|
||||
item->_nextSibling = this;
|
||||
}
|
||||
|
||||
void TreeItem::moveUnder(TreeItem *newParent) {
|
||||
if (newParent) {
|
||||
detach();
|
||||
addUnder(newParent);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeItem::destroyAll() {
|
||||
destroyChildren();
|
||||
detach();
|
||||
if (_disposeAfterUse == DisposeAfterUse::YES)
|
||||
delete this;
|
||||
}
|
||||
|
||||
int TreeItem::destroyChildren() {
|
||||
if (!_firstChild)
|
||||
return 0;
|
||||
|
||||
TreeItem *item = _firstChild, *child, *nextSibling;
|
||||
int total = 0;
|
||||
|
||||
do {
|
||||
child = item->_firstChild;
|
||||
nextSibling = item->_nextSibling;
|
||||
|
||||
if (child)
|
||||
total += item->destroyChildren();
|
||||
item->detach();
|
||||
if (item->_disposeAfterUse == DisposeAfterUse::YES)
|
||||
delete item;
|
||||
++total;
|
||||
} while ((item = nextSibling) != nullptr);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void TreeItem::detach() {
|
||||
// Delink this item from any prior and/or next siblings
|
||||
if (_priorSibling)
|
||||
_priorSibling->_nextSibling = _nextSibling;
|
||||
if (_nextSibling)
|
||||
_nextSibling->_priorSibling = _priorSibling;
|
||||
|
||||
if (_parent && _parent->_firstChild == this)
|
||||
_parent->_firstChild = _nextSibling;
|
||||
|
||||
_priorSibling = _nextSibling = _parent = nullptr;
|
||||
}
|
||||
|
||||
void TreeItem::attach(TreeItem *item) {
|
||||
_nextSibling = item;
|
||||
_priorSibling = item->_priorSibling;
|
||||
_parent = item->_parent;
|
||||
|
||||
if (item->_priorSibling)
|
||||
item->_priorSibling->_nextSibling = this;
|
||||
|
||||
item->_priorSibling = this;
|
||||
if (item->_parent && !item->_parent->_firstChild)
|
||||
item->_parent->_firstChild = this;
|
||||
}
|
||||
|
||||
NamedItem *TreeItem::findByName(const Common::String &name) {
|
||||
Common::String nameLower = name;
|
||||
nameLower.toLowercase();
|
||||
|
||||
for (TreeItem *treeItem = this; treeItem; treeItem = treeItem->scan(this)) {
|
||||
Common::String itemName = treeItem->getName();
|
||||
itemName.toLowercase();
|
||||
|
||||
if (!itemName.compareTo(nameLower))
|
||||
return dynamic_cast<NamedItem *>(treeItem);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
215
engines/ultima/shared/core/tree_item.h
Normal file
215
engines/ultima/shared/core/tree_item.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/* 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 ULTIMA_SHARED_CORE_TREE_ITEM_H
|
||||
#define ULTIMA_SHARED_CORE_TREE_ITEM_H
|
||||
|
||||
#include "ultima/shared/core/message_target.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
namespace Gfx {
|
||||
class VisualItem;
|
||||
} // End of namespace Gfx
|
||||
|
||||
namespace Maps {
|
||||
class Map;
|
||||
} // End of namespace Maps
|
||||
|
||||
class Game;
|
||||
class GameManager;
|
||||
class GameState;
|
||||
class Events;
|
||||
class Map;
|
||||
class NamedItem;
|
||||
class CMessage;
|
||||
|
||||
/**
|
||||
* This implements the base for objects can form a class hierarchy, with parents, children, and siblings
|
||||
* that messages can be passed around.
|
||||
*/
|
||||
class TreeItem: public MessageTarget {
|
||||
friend class CMessage;
|
||||
DECLARE_MESSAGE_MAP;
|
||||
private:
|
||||
TreeItem *_parent;
|
||||
TreeItem *_nextSibling;
|
||||
TreeItem *_priorSibling;
|
||||
TreeItem *_firstChild;
|
||||
DisposeAfterUse::Flag _disposeAfterUse;
|
||||
public:
|
||||
CLASSDEF;
|
||||
TreeItem();
|
||||
|
||||
/**
|
||||
* Gets the name of the item, if any
|
||||
*/
|
||||
virtual const Common::String getName() const {
|
||||
return Common::String();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the item's name matches a passed name
|
||||
*/
|
||||
virtual bool isEquals(const Common::String &name, int maxLen = 0) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the name of the item to a passed name
|
||||
*/
|
||||
virtual int compareTo(const Common::String &name, int maxLen = 0) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the view changes
|
||||
*/
|
||||
virtual void viewChange() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent for the given item
|
||||
*/
|
||||
TreeItem *getParent() const {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jumps up through the parents to find the root game
|
||||
*/
|
||||
Game *getGame();
|
||||
|
||||
/**
|
||||
* Jumps up through the parents to find the root game
|
||||
*/
|
||||
const Game *getGame() const;
|
||||
|
||||
/**
|
||||
* Returns the currently active game view
|
||||
*/
|
||||
Gfx::VisualItem *getView();
|
||||
|
||||
/**
|
||||
* Get the next sibling
|
||||
*/
|
||||
TreeItem *getNextSibling() const {
|
||||
return _nextSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the prior sibling
|
||||
*/
|
||||
TreeItem *getPriorSibling() const {
|
||||
return _priorSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last sibling of this sibling
|
||||
*/
|
||||
TreeItem *getLastSibling();
|
||||
|
||||
/**
|
||||
* Get the first child of the item, if any
|
||||
*/
|
||||
TreeItem *getFirstChild() const {
|
||||
return _firstChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last child of the item, if any
|
||||
*/
|
||||
TreeItem *getLastChild() const;
|
||||
|
||||
/**
|
||||
* Given all the recursive children of the tree item, gives the next
|
||||
* item in sequence to the passed starting item
|
||||
*/
|
||||
TreeItem *scan(TreeItem *item) const;
|
||||
|
||||
/**
|
||||
* Find the first child item that is of a given type
|
||||
*/
|
||||
TreeItem *findChildInstanceOf(const ClassDef &classDef) const;
|
||||
|
||||
/**
|
||||
* Find the next sibling item that is of the given type
|
||||
*/
|
||||
TreeItem *findNextInstanceOf(const ClassDef &classDef, TreeItem *startItem) const;
|
||||
|
||||
/**
|
||||
* Adds the item under another tree item
|
||||
*/
|
||||
void addUnder(TreeItem *newParent);
|
||||
|
||||
/**
|
||||
* Adds a new child under this one
|
||||
*/
|
||||
void addChild(TreeItem *child);
|
||||
|
||||
/**
|
||||
* Sets the parent for the item
|
||||
*/
|
||||
void setParent(TreeItem *newParent);
|
||||
|
||||
/**
|
||||
* Adds the item as a sibling of another item
|
||||
*/
|
||||
void addSibling(TreeItem *item);
|
||||
|
||||
/**
|
||||
* Moves the tree item to be under another parent
|
||||
*/
|
||||
void moveUnder(TreeItem *newParent);
|
||||
|
||||
/**
|
||||
* Destroys both the item as well as any of it's children
|
||||
*/
|
||||
void destroyAll();
|
||||
|
||||
/**
|
||||
* Destroys all child tree items under this one.
|
||||
* @returns Total number of tree items recursively removed
|
||||
*/
|
||||
int destroyChildren();
|
||||
|
||||
/**
|
||||
* Detach the tree item from any other associated tree items
|
||||
*/
|
||||
void detach();
|
||||
|
||||
/**
|
||||
* Attaches a tree item to a new node
|
||||
*/
|
||||
void attach(TreeItem *item);
|
||||
|
||||
/**
|
||||
* Finds a tree item by name
|
||||
* @param name Name to find
|
||||
*/
|
||||
NamedItem *findByName(const Common::String &name);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
42
engines/ultima/shared/core/utils.cpp
Normal file
42
engines/ultima/shared/core/utils.cpp
Normal 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 "ultima/shared/core/utils.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
bool isVowel(char c) {
|
||||
switch (toupper(c)) {
|
||||
case 'A':
|
||||
case 'E':
|
||||
case 'I':
|
||||
case 'O':
|
||||
case 'U':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
35
engines/ultima/shared/core/utils.h
Normal file
35
engines/ultima/shared/core/utils.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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 ULTIMA_UTILS_H
|
||||
#define ULTIMA_UTILS_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define SGN(v) ((v) > 0 ? 1 : -1)
|
||||
|
||||
extern bool isVowel(char c);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
44
engines/ultima/shared/core/widgets.cpp
Normal file
44
engines/ultima/shared/core/widgets.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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 "ultima/shared/core/widgets.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
void Creature::synchronize(Common::Serializer &s) {
|
||||
StandardWidget::synchronize(s);
|
||||
s.syncAsSint16LE(_hitPoints);
|
||||
}
|
||||
|
||||
void Creature::update(bool isPreUpdate) {
|
||||
if (isPreUpdate) {
|
||||
// Check whether creature can attack
|
||||
movement();
|
||||
_isAttacking = attackDistance() != 0;
|
||||
} else if (_isAttacking && !_game->_party->isDead()) {
|
||||
attack();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima1
|
||||
} // End of namespace Ultima
|
||||
147
engines/ultima/shared/core/widgets.h
Normal file
147
engines/ultima/shared/core/widgets.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/* 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 ULTIMA_SHARED_CORE_WIDGETS_H
|
||||
#define ULTIMA_SHARED_CORE_WIDGETS_H
|
||||
|
||||
#include "ultima/shared/core/map.h"
|
||||
#include "ultima/shared/gfx/dungeon_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* Base class for widgets on maps other than the dungeons
|
||||
*/
|
||||
class StandardWidget : public MapWidget {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
StandardWidget(Game *game, Map::MapBase *map) : MapWidget(game, map) {}
|
||||
StandardWidget(Game *game, Map::MapBase *map, const Point &pt, Direction dir = DIR_NONE) : MapWidget(game, map, pt, dir) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~StandardWidget() override {}
|
||||
};
|
||||
|
||||
class Creature : public StandardWidget {
|
||||
protected:
|
||||
int _hitPoints;
|
||||
bool _isAttacking;
|
||||
protected:
|
||||
/**
|
||||
* Returns either the maximum attack distance for a monster, or 0 if the monster is beyond
|
||||
* that distance from the player
|
||||
*/
|
||||
virtual uint attackDistance() const { return 0; }
|
||||
|
||||
/**
|
||||
* Handles moving creatures
|
||||
*/
|
||||
virtual void movement() {}
|
||||
|
||||
/**
|
||||
* Handles attacks
|
||||
*/
|
||||
virtual void attack() {}
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Creature(Game *game, Map::MapBase *map) : StandardWidget(game, map), _hitPoints(0), _isAttacking(false) {}
|
||||
Creature(Game *game, Map::MapBase *map, int hitPoints) : StandardWidget(game, map),
|
||||
_hitPoints(hitPoints), _isAttacking(false) {}
|
||||
Creature(Game *game, Map::MapBase *map, int hitPoints, const Point &pt, Direction dir = DIR_NONE) :
|
||||
StandardWidget(game, map, pt, dir), _hitPoints(hitPoints), _isAttacking(false) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Creature() override {}
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) override;
|
||||
|
||||
/**
|
||||
* Called to update the widget at the end of a turn
|
||||
* @param isPreUpdate Update is called twice in succession during the end of turn update.
|
||||
* Once with true for all widgets, then with it false
|
||||
*/
|
||||
void update(bool isPreUpdate) override;
|
||||
|
||||
/**
|
||||
* True true if the creature is dead
|
||||
*/
|
||||
bool isDead() const { return _hitPoints <= 0; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class for things that appear within the dungeons
|
||||
*/
|
||||
class DungeonWidget : public MapWidget {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
DungeonWidget(Game *game, Map::MapBase *map) : MapWidget(game, map) {}
|
||||
DungeonWidget(Game *game, Map::MapBase *map, const Point &pt, Direction dir = DIR_NONE) : MapWidget(game, map, pt, dir) {}
|
||||
DungeonWidget(Game *game, Map::MapBase *map, const Common::String &name, const Point &pt, Direction dir = DIR_NONE) :
|
||||
MapWidget(game, map, name, pt, dir) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~DungeonWidget() override {}
|
||||
|
||||
/**
|
||||
* Draws an item
|
||||
*/
|
||||
virtual void draw(DungeonSurface &s, uint distance) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stub class for dungeon creatures
|
||||
*/
|
||||
class DungeonCreature {
|
||||
public:
|
||||
virtual ~DungeonCreature() {}
|
||||
|
||||
/**
|
||||
* Returns true if a monster blocks the background behind him
|
||||
*/
|
||||
virtual bool isBlockingView() const = 0;
|
||||
|
||||
/**
|
||||
* Draw a monster
|
||||
*/
|
||||
virtual void draw(DungeonSurface &s, uint distance) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
313
engines/ultima/shared/early/font_resources.cpp
Normal file
313
engines/ultima/shared/early/font_resources.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/* 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 "ultima/shared/early/font_resources.h"
|
||||
#include "common/algorithm.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
// 8x8 font copied from DosBox
|
||||
static const byte INT10_FONT_08[256][8] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e },
|
||||
{ 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e },
|
||||
{ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00 },
|
||||
{ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 },
|
||||
{ 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c },
|
||||
{ 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c },
|
||||
{ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 },
|
||||
{ 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff },
|
||||
{ 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00 },
|
||||
{ 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff },
|
||||
{ 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78 },
|
||||
{ 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18 },
|
||||
{ 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0 },
|
||||
{ 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0 },
|
||||
{ 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99 },
|
||||
{ 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00 },
|
||||
{ 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00 },
|
||||
{ 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18 },
|
||||
{ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00 },
|
||||
{ 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00 },
|
||||
{ 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00 },
|
||||
{ 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff },
|
||||
{ 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00 },
|
||||
{ 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00 },
|
||||
{ 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00 },
|
||||
{ 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00 },
|
||||
{ 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00 },
|
||||
{ 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00 },
|
||||
{ 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00 },
|
||||
{ 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00 },
|
||||
{ 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00 },
|
||||
{ 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00 },
|
||||
{ 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00 },
|
||||
{ 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00 },
|
||||
{ 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00 },
|
||||
{ 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60 },
|
||||
{ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00 },
|
||||
{ 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00 },
|
||||
{ 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00 },
|
||||
{ 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00 },
|
||||
{ 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00 },
|
||||
{ 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00 },
|
||||
{ 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00 },
|
||||
{ 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00 },
|
||||
{ 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00 },
|
||||
{ 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00 },
|
||||
{ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00 },
|
||||
{ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60 },
|
||||
{ 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00 },
|
||||
{ 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00 },
|
||||
{ 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00 },
|
||||
{ 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00 },
|
||||
{ 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00 },
|
||||
{ 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00 },
|
||||
{ 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00 },
|
||||
{ 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00 },
|
||||
{ 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00 },
|
||||
{ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00 },
|
||||
{ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00 },
|
||||
{ 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00 },
|
||||
{ 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00 },
|
||||
{ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00 },
|
||||
{ 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00 },
|
||||
{ 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00 },
|
||||
{ 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00 },
|
||||
{ 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 },
|
||||
{ 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00 },
|
||||
{ 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00 },
|
||||
{ 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00 },
|
||||
{ 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00 },
|
||||
{ 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00 },
|
||||
{ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00 },
|
||||
{ 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00 },
|
||||
{ 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00 },
|
||||
{ 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00 },
|
||||
{ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00 },
|
||||
{ 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00 },
|
||||
{ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00 },
|
||||
{ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
|
||||
{ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00 },
|
||||
{ 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00 },
|
||||
{ 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00 },
|
||||
{ 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00 },
|
||||
{ 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00 },
|
||||
{ 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00 },
|
||||
{ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8 },
|
||||
{ 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00 },
|
||||
{ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78 },
|
||||
{ 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00 },
|
||||
{ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00 },
|
||||
{ 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00 },
|
||||
{ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0 },
|
||||
{ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e },
|
||||
{ 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00 },
|
||||
{ 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00 },
|
||||
{ 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00 },
|
||||
{ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00 },
|
||||
{ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00 },
|
||||
{ 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00 },
|
||||
{ 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00 },
|
||||
{ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8 },
|
||||
{ 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00 },
|
||||
{ 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00 },
|
||||
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 },
|
||||
{ 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00 },
|
||||
{ 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00 },
|
||||
{ 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78 },
|
||||
{ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00 },
|
||||
{ 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00 },
|
||||
{ 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00 },
|
||||
{ 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38 },
|
||||
{ 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00 },
|
||||
{ 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00 },
|
||||
{ 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00 },
|
||||
{ 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00 },
|
||||
{ 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00 },
|
||||
{ 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00 },
|
||||
{ 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00 },
|
||||
{ 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00 },
|
||||
{ 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00 },
|
||||
{ 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8 },
|
||||
{ 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00 },
|
||||
{ 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18 },
|
||||
{ 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00 },
|
||||
{ 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30 },
|
||||
{ 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7 },
|
||||
{ 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70 },
|
||||
{ 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 },
|
||||
{ 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00 },
|
||||
{ 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00 },
|
||||
{ 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00 },
|
||||
{ 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00 },
|
||||
{ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00 },
|
||||
{ 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00 },
|
||||
{ 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f },
|
||||
{ 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03 },
|
||||
{ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00 },
|
||||
{ 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00 },
|
||||
{ 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00 },
|
||||
{ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 },
|
||||
{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
|
||||
{ 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36 },
|
||||
{ 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18 },
|
||||
{ 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 },
|
||||
{ 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00 },
|
||||
{ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36 },
|
||||
{ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36 },
|
||||
{ 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00 },
|
||||
{ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36 },
|
||||
{ 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36 },
|
||||
{ 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18 },
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
|
||||
{ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 },
|
||||
{ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f },
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00 },
|
||||
{ 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0 },
|
||||
{ 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00 },
|
||||
{ 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00 },
|
||||
{ 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00 },
|
||||
{ 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00 },
|
||||
{ 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0 },
|
||||
{ 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00 },
|
||||
{ 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc },
|
||||
{ 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00 },
|
||||
{ 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00 },
|
||||
{ 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00 },
|
||||
{ 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00 },
|
||||
{ 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0 },
|
||||
{ 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00 },
|
||||
{ 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00 },
|
||||
{ 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00 },
|
||||
{ 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00 },
|
||||
{ 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00 },
|
||||
{ 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00 },
|
||||
{ 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18 },
|
||||
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70 },
|
||||
{ 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00 },
|
||||
{ 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00 },
|
||||
{ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00 },
|
||||
{ 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c },
|
||||
{ 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00 },
|
||||
{ 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
FontResources::FontResources() : LocalResourceFile("COMMON/FONTS") {
|
||||
}
|
||||
|
||||
FontResources::FontResources(Resources *resManager) : LocalResourceFile(resManager, "COMMON/FONTS") {
|
||||
Common::copy((const byte *)INT10_FONT_08, (const byte *)INT10_FONT_08 + 256 * 8, (byte *)_font8x8);
|
||||
}
|
||||
|
||||
void FontResources::synchronize() {
|
||||
syncBytes2D((byte *)_font8x8, 256, 8);
|
||||
|
||||
// Load in the Ultima VI font if present
|
||||
Common::File f;
|
||||
if (f.exists("u6.ch")) {
|
||||
f.open("u6.ch");
|
||||
for (int idx = 0; idx < 256; ++idx)
|
||||
f.read(&_fontU6[idx][0], 8);
|
||||
} else {
|
||||
for (int idx = 0; idx < 256; ++idx)
|
||||
Common::fill(&_fontU6[idx][0], &_fontU6[idx][8], 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
49
engines/ultima/shared/early/font_resources.h
Normal file
49
engines/ultima/shared/early/font_resources.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_EARLY_FONT_RESOURCES_H
|
||||
#define ULTIMA_SHARED_EARLY_FONT_RESOURCES_H
|
||||
|
||||
#include "ultima/shared/engine/resources.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class FontResources : public LocalResourceFile {
|
||||
protected:
|
||||
/**
|
||||
* Synchronize resource data
|
||||
*/
|
||||
void synchronize() override;
|
||||
public:
|
||||
byte _font8x8[256][8];
|
||||
byte _fontU6[256][8];
|
||||
public:
|
||||
FontResources();
|
||||
FontResources(Resources *resManager);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
141
engines/ultima/shared/early/game.cpp
Normal file
141
engines/ultima/shared/early/game.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/early/font_resources.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/gfx/font.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
#include "graphics/palette.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
BEGIN_MESSAGE_MAP(Game, GameBase)
|
||||
ON_MESSAGE(EndOfTurnMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
Game::Game() : GameBase(), _randomSeed(0), _gameView(nullptr), _map(nullptr), _party(nullptr),
|
||||
_edgeColor(0), _borderColor(0), _highlightColor(0), _textColor(0), _color1(0), _bgColor(0), _whiteColor(0) {
|
||||
_fontResources = new FontResources();
|
||||
_fontResources->load();
|
||||
setFont(new Gfx::Font((const byte *)&_fontResources->_font8x8[0][0]));
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
delete _fontResources;
|
||||
}
|
||||
|
||||
void Game::setCGAPalette() {
|
||||
static const byte PALETTE[4][3] = { { 0, 0, 0 },{ 0xAA, 0xAA, 0 },{ 0xAA, 0, 0xAA },{ 0xAA, 0xAA, 0xAA } };
|
||||
g_vm->_screen->setPalette(&PALETTE[0][0], 0, 4);
|
||||
|
||||
_edgeColor = 3;
|
||||
_borderColor = 3;
|
||||
_highlightColor = 1;
|
||||
_textColor = 3;
|
||||
_color1 = 6;
|
||||
_whiteColor = 3;
|
||||
}
|
||||
|
||||
void Game::setEGAPalette() {
|
||||
static const byte PALETTE[16][3] = {
|
||||
{ 0, 0, 0 },{ 0x00, 0x00, 0x80 },{ 0x00, 0x80, 0x00 },{ 0x00, 0x80, 0x80 },
|
||||
{ 0x80, 0x00, 0x00 },{ 0x80, 0x00, 0x80 },{ 0x80, 0x80, 0x00 },{ 0xC0, 0xC0, 0xC0 },
|
||||
{ 0x80, 0x80, 0x80 },{ 0x00, 0x00, 0xFF },{ 0x00, 0xFF, 0x00 },{ 0x00, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x40, 0x40 },{ 0xFF, 0x00, 0xFF },{ 0xFF, 0xFF, 0x00 },{ 0xFF, 0xFF, 0xFF }
|
||||
};
|
||||
g_vm->_screen->setPalette(&PALETTE[0][0], 0, 16);
|
||||
|
||||
_edgeColor = 15;
|
||||
_borderColor = 1;
|
||||
_highlightColor = 12;
|
||||
_textColor = 11;
|
||||
_color1 = 7;
|
||||
_bgColor = 0;
|
||||
_whiteColor = 15;
|
||||
}
|
||||
|
||||
void Game::setEGAPalette(const byte *palette) {
|
||||
// Build up the EGA palette
|
||||
byte egaPalette[64 * 3];
|
||||
|
||||
byte *p = &egaPalette[0];
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
*p++ = (i >> 2 & 1) * 0xaa + (i >> 5 & 1) * 0x55;
|
||||
*p++ = (i >> 1 & 1) * 0xaa + (i >> 4 & 1) * 0x55;
|
||||
*p++ = (i & 1) * 0xaa + (i >> 3 & 1) * 0x55;
|
||||
}
|
||||
|
||||
// Loop through setting palette colors based on the passed indexes
|
||||
for (int idx = 0; idx < 16; ++idx) {
|
||||
int palIndex = palette[idx];
|
||||
assert(palIndex < 64);
|
||||
|
||||
const byte *pRgb = (const byte *)&egaPalette[palIndex * 3];
|
||||
g_vm->_screen->setPalette(pRgb, idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::loadU6Palette() {
|
||||
// Read in the palette
|
||||
File f("u6pal");
|
||||
byte palette[Graphics::PALETTE_SIZE];
|
||||
f.read(palette, Graphics::PALETTE_SIZE);
|
||||
f.close();
|
||||
|
||||
// Adjust the palette values from 0-63 to 0-255, and set the palette
|
||||
for (int idx = 0; idx < Graphics::PALETTE_SIZE; ++idx)
|
||||
palette[idx] = PALETTE_6BIT_TO_8BIT(palette[idx]);
|
||||
g_vm->_screen->setPalette(&palette[0], 0, Graphics::PALETTE_COUNT);
|
||||
|
||||
// TODO: Set appropriate indexes
|
||||
_edgeColor = 15;
|
||||
_borderColor = 1;
|
||||
_highlightColor = 12;
|
||||
_textColor = 72;
|
||||
_color1 = 7;
|
||||
_bgColor = 49;
|
||||
}
|
||||
|
||||
void Game::playFX(uint effectId) {
|
||||
warning("TODO: playFX");
|
||||
}
|
||||
|
||||
void Game::synchronize(Common::Serializer &s) {
|
||||
_party->synchronize(s);
|
||||
_map->synchronize(s);
|
||||
}
|
||||
|
||||
bool Game::EndOfTurnMsg(CEndOfTurnMsg *msg) {
|
||||
// Update things on the map
|
||||
_map->update();
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::endOfTurn() {
|
||||
CEndOfTurnMsg turnMsg;
|
||||
turnMsg.execute(this);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
129
engines/ultima/shared/early/game.h
Normal file
129
engines/ultima/shared/early/game.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/* 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 ULTIMA_SHARED_EARLY_GAME_H
|
||||
#define ULTIMA_SHARED_EARLY_GAME_H
|
||||
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/core/party.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class GameView;
|
||||
class GameState;
|
||||
class FontResources;
|
||||
|
||||
namespace Maps {
|
||||
class Map;
|
||||
}
|
||||
|
||||
/**
|
||||
* More specialized base class for earlier Ultima games
|
||||
*/
|
||||
class Game : public GameBase {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool EndOfTurnMsg(CEndOfTurnMsg *msg);
|
||||
protected:
|
||||
GameView *_gameView;
|
||||
FontResources *_fontResources;
|
||||
protected:
|
||||
/**
|
||||
* Sets up EGA palette
|
||||
*/
|
||||
void setEGAPalette();
|
||||
|
||||
/**
|
||||
* Loads the Ultima 6 palette
|
||||
*/
|
||||
void loadU6Palette();
|
||||
public:
|
||||
byte _edgeColor;
|
||||
byte _borderColor;
|
||||
byte _highlightColor;
|
||||
byte _textColor;
|
||||
byte _color1;
|
||||
byte _bgColor;
|
||||
byte _whiteColor;
|
||||
|
||||
/**
|
||||
* Player party. In the earlier Ultima games, this is a single character
|
||||
*/
|
||||
Party *_party;
|
||||
|
||||
/**
|
||||
* Pointer to the map manager for the game
|
||||
*/
|
||||
Maps::Map *_map;
|
||||
|
||||
/**
|
||||
* Stores the base random seed used for generating deterministic dungeon levels
|
||||
*/
|
||||
uint32 _randomSeed;
|
||||
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Game();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Game() override;
|
||||
|
||||
/**
|
||||
* Play a sound effect
|
||||
*/
|
||||
void playFX(uint effectId);
|
||||
|
||||
/**
|
||||
* Sets an EGA palette based on a 16-byte EGA RGB indexes
|
||||
*/
|
||||
void setEGAPalette(const byte *palette);
|
||||
|
||||
/**
|
||||
* Sets up a CGA palette
|
||||
*/
|
||||
void setCGAPalette();
|
||||
|
||||
/**
|
||||
* Returns the map
|
||||
*/
|
||||
Maps::Map *getMap() const override { return _map; }
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) override;
|
||||
|
||||
/**
|
||||
* Signal an end of turn
|
||||
*/
|
||||
void endOfTurn();
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
262
engines/ultima/shared/early/game_base.cpp
Normal file
262
engines/ultima/shared/early/game_base.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
/* 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/config-manager.h"
|
||||
#include "common/system.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/core/mouse_cursor.h"
|
||||
#include "ultima/shared/gfx/font.h"
|
||||
#include "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/gfx/text_input.h"
|
||||
#include "ultima/shared/gfx/visual_container.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
GameBase::GameBase(): _currentView(nullptr), _pendingPopup(nullptr), _font(nullptr), _priorLeftDownTime(0),
|
||||
_priorMiddleDownTime(0), _priorRightDownTime(0), _inputHandler(this), _inputTranslator(&_inputHandler),
|
||||
_videoMode(0), _textCursor(nullptr) {
|
||||
}
|
||||
|
||||
GameBase::~GameBase() {
|
||||
delete _font;
|
||||
delete _textCursor;
|
||||
}
|
||||
|
||||
int GameBase::getSavegameSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameBase::mouseChanged() {
|
||||
|
||||
}
|
||||
|
||||
void GameBase::onIdle() {
|
||||
// Handle any drawing updates
|
||||
update();
|
||||
}
|
||||
|
||||
#define HANDLE_MESSAGE(METHOD) \
|
||||
_inputTranslator.METHOD(g_vm->_events->getSpecialButtons(), mousePos); \
|
||||
mouseChanged()
|
||||
|
||||
|
||||
void GameBase::mouseMove(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(mouseMove);
|
||||
}
|
||||
|
||||
void GameBase::leftButtonDown(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
if ((g_vm->_events->getTicksCount() - _priorLeftDownTime) < DOUBLE_CLICK_TIME) {
|
||||
_priorLeftDownTime = 0;
|
||||
leftButtonDoubleClick(mousePos);
|
||||
} else {
|
||||
_priorLeftDownTime = g_vm->_events->getTicksCount();
|
||||
HANDLE_MESSAGE(leftButtonDown);
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::leftButtonUp(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(leftButtonUp);
|
||||
}
|
||||
|
||||
void GameBase::leftButtonDoubleClick(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(leftButtonDoubleClick);
|
||||
}
|
||||
|
||||
void GameBase::middleButtonDown(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
if ((g_vm->_events->getTicksCount() - _priorMiddleDownTime) < DOUBLE_CLICK_TIME) {
|
||||
_priorMiddleDownTime = 0;
|
||||
middleButtonDoubleClick(mousePos);
|
||||
} else {
|
||||
_priorMiddleDownTime = g_vm->_events->getTicksCount();
|
||||
HANDLE_MESSAGE(middleButtonDown);
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::middleButtonUp(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(middleButtonUp);
|
||||
}
|
||||
|
||||
void GameBase::middleButtonDoubleClick(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(middleButtonDoubleClick);
|
||||
}
|
||||
|
||||
void GameBase::rightButtonDown(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
if ((g_vm->_events->getTicksCount() - _priorRightDownTime) < DOUBLE_CLICK_TIME) {
|
||||
_priorRightDownTime = 0;
|
||||
rightButtonDoubleClick(mousePos);
|
||||
} else {
|
||||
_priorRightDownTime = g_vm->_events->getTicksCount();
|
||||
HANDLE_MESSAGE(rightButtonDown);
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::rightButtonUp(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(rightButtonUp);
|
||||
}
|
||||
|
||||
void GameBase::mouseWheel(const Point &mousePos, bool wheelUp) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
_inputTranslator.mouseWheel(wheelUp, mousePos);
|
||||
mouseChanged();
|
||||
}
|
||||
|
||||
void GameBase::rightButtonDoubleClick(const Point &mousePos) {
|
||||
if (!isMouseControlEnabled())
|
||||
return;
|
||||
|
||||
HANDLE_MESSAGE(rightButtonDoubleClick);
|
||||
}
|
||||
|
||||
void GameBase::keyDown(Common::KeyState keyState) {
|
||||
_inputTranslator.keyDown(keyState);
|
||||
}
|
||||
|
||||
void GameBase::setView(Gfx::VisualItem *view) {
|
||||
_currentView = view;
|
||||
}
|
||||
|
||||
void GameBase::setView(const Common::String &viewName) {
|
||||
Gfx::VisualItem *view = dynamic_cast<Gfx::VisualItem *>(findByName(viewName));
|
||||
|
||||
if (view != _currentView) {
|
||||
_currentView = view;
|
||||
assert(_currentView);
|
||||
|
||||
// Signal the view that it's now active
|
||||
CShowMsg showMsg;
|
||||
showMsg.execute(_currentView);
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::setPopup(Gfx::Popup *popup) {
|
||||
assert(!_pendingPopup);
|
||||
_pendingPopup = popup;
|
||||
}
|
||||
|
||||
void GameBase::update() {
|
||||
if (_currentView) {
|
||||
// Signal the next frame
|
||||
CFrameMsg frameMsg(g_vm->_events->getTicksCount());
|
||||
frameMsg.execute(_currentView);
|
||||
|
||||
// Draw the view
|
||||
if (_currentView->isDirty()) {
|
||||
_currentView->draw();
|
||||
_currentView->clearDirty();
|
||||
} else if (_pendingPopup) {
|
||||
// There's a pending popup to display, so make it active
|
||||
_currentView = _pendingPopup;
|
||||
_pendingPopup = nullptr;
|
||||
|
||||
CShowMsg showMsg;
|
||||
showMsg.execute(_currentView);
|
||||
}
|
||||
|
||||
// Allow the text cursor to update
|
||||
_textCursor->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::changeView(const Common::String &name) {
|
||||
Gfx::VisualItem *newView = dynamic_cast<Gfx::VisualItem *>(findByName(name));
|
||||
assert(newView);
|
||||
|
||||
// Hide the current view
|
||||
CHideMsg hideMsg(_currentView, true);
|
||||
hideMsg.execute(_currentView, nullptr, MSGFLAG_SCAN);
|
||||
|
||||
if (hideMsg._fadeOut) {
|
||||
// TODO: Fade out
|
||||
}
|
||||
|
||||
// Show the new view
|
||||
_currentView = newView;
|
||||
CShowMsg showMsg(_currentView, true);
|
||||
showMsg.execute(_currentView, nullptr, MSGFLAG_SCAN);
|
||||
|
||||
_currentView->draw();
|
||||
|
||||
if (showMsg._fadeIn) {
|
||||
// TODO: Fade in
|
||||
}
|
||||
}
|
||||
|
||||
void GameBase::setFont(Gfx::Font *font) {
|
||||
delete _font;
|
||||
_font = font;
|
||||
}
|
||||
|
||||
uint GameBase::getRandomNumber(uint max) {
|
||||
return g_vm->getRandomNumber(max);
|
||||
}
|
||||
|
||||
uint GameBase::getRandomNumber(uint min, uint max) {
|
||||
return g_vm->getRandomNumber(min, max);
|
||||
}
|
||||
|
||||
void GameBase::sleep(uint time) {
|
||||
g_vm->_events->sleep(time);
|
||||
}
|
||||
|
||||
uint32 GameBase::getMillis() const {
|
||||
return g_system->getMillis();
|
||||
}
|
||||
|
||||
void GameBase::synchronize(Common::Serializer &s) {
|
||||
_priorLeftDownTime = 0;
|
||||
_priorMiddleDownTime = 0;
|
||||
_priorRightDownTime = 0;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
203
engines/ultima/shared/early/game_base.h
Normal file
203
engines/ultima/shared/early/game_base.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* 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 ULTIMA_SHARED_EARLY_GAME_BASE_H
|
||||
#define ULTIMA_SHARED_EARLY_GAME_BASE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/engine/input_handler.h"
|
||||
#include "ultima/shared/engine/input_translator.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class UltimaEngine;
|
||||
class GameState;
|
||||
|
||||
namespace Gfx {
|
||||
class Font;
|
||||
class Popup;
|
||||
class TextCursor;
|
||||
class TextInput;
|
||||
class VisualItem;
|
||||
} // End of namespace Gfx
|
||||
|
||||
namespace Maps {
|
||||
class Map;
|
||||
} // End of namespace Maps
|
||||
|
||||
/**
|
||||
* Base class for the game implementations
|
||||
*/
|
||||
class GameBase : public TreeItem, public EventTarget {
|
||||
private:
|
||||
/**
|
||||
* Checks for the presence of any savegames and, if present,
|
||||
* lets the user pick one to resume
|
||||
*/
|
||||
int getSavegameSlot();
|
||||
|
||||
void leftButtonDoubleClick(const Point &mousePos) override;
|
||||
void middleButtonDoubleClick(const Point &mousePos) override;
|
||||
void rightButtonDoubleClick(const Point &mousePos);
|
||||
|
||||
/**
|
||||
* Returns true if the player can control the mouse
|
||||
*/
|
||||
bool isMouseControlEnabled() const { return true; }
|
||||
|
||||
void changeView(const Common::String &name);
|
||||
protected:
|
||||
uint32 _priorLeftDownTime;
|
||||
uint32 _priorMiddleDownTime;
|
||||
uint32 _priorRightDownTime;
|
||||
Gfx::VisualItem *_currentView;
|
||||
Gfx::Popup *_pendingPopup;
|
||||
InputHandler _inputHandler;
|
||||
InputTranslator _inputTranslator;
|
||||
Gfx::Font *_font;
|
||||
public:
|
||||
Gfx::TextCursor *_textCursor;
|
||||
uint _videoMode;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
GameBase();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~GameBase() override;
|
||||
|
||||
/**
|
||||
* Called to handle any regular updates the game requires
|
||||
*/
|
||||
void onIdle() override;
|
||||
|
||||
void mouseMove(const Point &mousePos) override;
|
||||
void leftButtonDown(const Point &mousePos) override;
|
||||
void leftButtonUp(const Point &mousePos) override;
|
||||
void middleButtonDown(const Point &mousePos) override;
|
||||
void middleButtonUp(const Point &mousePos) override;
|
||||
void rightButtonDown(const Point &mousePos) override;
|
||||
void rightButtonUp(const Point &mousePos) override;
|
||||
void mouseWheel(const Point &mousePos, bool wheelUp) override;
|
||||
void keyDown(Common::KeyState keyState) override;
|
||||
|
||||
/**
|
||||
* Called when the game starts
|
||||
*/
|
||||
virtual void starting(bool isLoading) {}
|
||||
|
||||
/**
|
||||
* Returns true if the current video mode is VGA
|
||||
*/
|
||||
virtual bool isVGA() const { return false; }
|
||||
|
||||
/**
|
||||
* Called once every frame to update the game and render the view
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* Called by the event handler when a mouse event has been generated
|
||||
*/
|
||||
void mouseChanged();
|
||||
|
||||
/**
|
||||
* Set the currently active view to display
|
||||
*/
|
||||
void setView(Gfx::VisualItem *view);
|
||||
|
||||
/**
|
||||
* Set the currently active view to display
|
||||
*/
|
||||
void setView(const Common::String &viewName);
|
||||
|
||||
/**
|
||||
* Sets a popup to be shown
|
||||
*/
|
||||
void setPopup(Gfx::Popup *popup);
|
||||
|
||||
/**
|
||||
* Returns the current view
|
||||
*/
|
||||
Gfx::VisualItem *getView() const { return _currentView; }
|
||||
|
||||
/**
|
||||
* Set a font to use
|
||||
*/
|
||||
void setFont(Gfx::Font *font);
|
||||
|
||||
/**
|
||||
* Returns the current font
|
||||
*/
|
||||
Gfx::Font *getFont() const { return _font; }
|
||||
|
||||
/**
|
||||
* Returns the map
|
||||
*/
|
||||
virtual Maps::Map *getMap() const { return nullptr; }
|
||||
|
||||
/**
|
||||
* Gets a random number
|
||||
*/
|
||||
uint getRandomNumber(uint max);
|
||||
|
||||
/**
|
||||
* Gets a random number
|
||||
*/
|
||||
uint getRandomNumber(uint min, uint max);
|
||||
|
||||
/**
|
||||
* Wait for a given period of time
|
||||
*/
|
||||
void sleep(uint time);
|
||||
|
||||
/**
|
||||
* Return the current time
|
||||
*/
|
||||
uint32 getMillis() const;
|
||||
|
||||
/**
|
||||
* Returns true if a savegame can currently be loaded
|
||||
*/
|
||||
virtual bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) { return true; }
|
||||
|
||||
/**
|
||||
* Returns true if the game can currently be saved
|
||||
*/
|
||||
virtual bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) { return false; }
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
164
engines/ultima/shared/early/ultima_early.cpp
Normal file
164
engines/ultima/shared/early/ultima_early.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/system.h"
|
||||
#include "common/translation.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "graphics/scaler.h"
|
||||
#include "gui/saveload.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/engine/resources.h"
|
||||
#include "ultima/shared/core/mouse_cursor.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
#include "ultima/ultima1/game.h"
|
||||
#endif
|
||||
|
||||
namespace Ultima {
|
||||
|
||||
Shared::UltimaEarlyEngine *g_vm;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
UltimaEarlyEngine::UltimaEarlyEngine(OSystem *syst, const UltimaGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _game(nullptr), _randomSource("Ultima") {
|
||||
g_vm = this;
|
||||
_mouseCursor = nullptr;
|
||||
_screen = nullptr;
|
||||
}
|
||||
|
||||
UltimaEarlyEngine::~UltimaEarlyEngine() {
|
||||
delete _events;
|
||||
delete _game;
|
||||
delete _mouseCursor;
|
||||
delete _screen;
|
||||
}
|
||||
|
||||
bool UltimaEarlyEngine::initialize() {
|
||||
// Call syncSoundSettings to get default volumes set
|
||||
syncSoundSettings();
|
||||
|
||||
// Set up the resources datafile
|
||||
Resources *res = new Resources();
|
||||
if (!res->open()) {
|
||||
GUIErrorMessage(_("Could not find correct ultima.dat datafile"));
|
||||
return false;
|
||||
}
|
||||
SearchMan.add("ultima", res);
|
||||
|
||||
_events = new EventsManager(this);
|
||||
_screen = new Gfx::Screen();
|
||||
|
||||
// Create the game, and signal to it that the game is starting
|
||||
_game = createGame();
|
||||
_events->addTarget(_game);
|
||||
_game->starting(false);
|
||||
|
||||
// Load cursors
|
||||
_mouseCursor = new MouseCursor();
|
||||
|
||||
// If requested, load a savegame instead of showing the intro
|
||||
if (ConfMan.hasKey("save_slot")) {
|
||||
int saveSlot = ConfMan.getInt("save_slot");
|
||||
if (saveSlot >= 0 && saveSlot <= 999)
|
||||
loadGameState(saveSlot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Error UltimaEarlyEngine::run() {
|
||||
// Initialize the engine and play the game
|
||||
if (initialize())
|
||||
playGame();
|
||||
|
||||
// Deinitialize and free the engine
|
||||
deinitialize();
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool UltimaEarlyEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsChangingOptionsDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
void UltimaEarlyEngine::playGame() {
|
||||
while (!shouldQuit()) {
|
||||
_events->pollEventsAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Screen *UltimaEarlyEngine::getScreen() const {
|
||||
return _screen;
|
||||
}
|
||||
|
||||
GameId UltimaEarlyEngine::getGameId() const {
|
||||
return _gameDescription->gameId;
|
||||
}
|
||||
|
||||
bool UltimaEarlyEngine::isEnhanced() const {
|
||||
return _gameDescription->features & GF_VGA_ENHANCED;
|
||||
}
|
||||
|
||||
Game *UltimaEarlyEngine::createGame() const {
|
||||
switch (getGameId()) {
|
||||
#ifndef RELEASE_BUILD
|
||||
case GAME_ULTIMA1:
|
||||
return new Ultima1::Ultima1Game();
|
||||
#endif
|
||||
default:
|
||||
error("Unknown game");
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error UltimaEarlyEngine::loadGameStream(Common::SeekableReadStream *stream) {
|
||||
// Read in the game's data
|
||||
Common::Serializer s(stream, nullptr);
|
||||
_game->synchronize(s);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error UltimaEarlyEngine::saveGameStream(Common::WriteStream *stream, bool) {
|
||||
// Write out the game's data
|
||||
Common::Serializer s(nullptr, stream);
|
||||
_game->synchronize(s);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool UltimaEarlyEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return _game->canLoadGameStateCurrently(msg);
|
||||
}
|
||||
|
||||
bool UltimaEarlyEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return _game->canSaveGameStateCurrently(msg);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
169
engines/ultima/shared/early/ultima_early.h
Normal file
169
engines/ultima/shared/early/ultima_early.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_EARLY_ULTIMA_EARLY_H
|
||||
#define ULTIMA_SHARED_EARLY_ULTIMA_EARLY_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/random.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/util.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "engines/engine.h"
|
||||
#include "ultima/detection.h"
|
||||
|
||||
#include "ultima/shared/engine/events.h"
|
||||
|
||||
namespace Ultima {
|
||||
|
||||
struct UltimaGameDescription;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
struct UltimaSavegameHeader {
|
||||
uint8 _version;
|
||||
uint8 _gameId;
|
||||
uint8 _language;
|
||||
uint8 _videoMode;
|
||||
Common::String _saveName;
|
||||
Graphics::Surface *_thumbnail;
|
||||
int _year, _month, _day;
|
||||
int _hour, _minute;
|
||||
int _totalFrames;
|
||||
};
|
||||
|
||||
class Events;
|
||||
class Game;
|
||||
class GameBase;
|
||||
class MouseCursor;
|
||||
class Resources;
|
||||
|
||||
namespace Gfx {
|
||||
class Screen;
|
||||
}
|
||||
|
||||
class UltimaEarlyEngine : public Engine, public EventsCallback {
|
||||
private:
|
||||
/**
|
||||
* Initialize the engine
|
||||
*/
|
||||
virtual bool initialize();
|
||||
|
||||
/**
|
||||
* Deinitialize the engine
|
||||
*/
|
||||
virtual void deinitialize() {}
|
||||
|
||||
private:
|
||||
Common::RandomSource _randomSource;
|
||||
protected:
|
||||
const UltimaGameDescription *_gameDescription;
|
||||
public:
|
||||
GameBase *_game;
|
||||
MouseCursor *_mouseCursor;
|
||||
Gfx::Screen *_screen;
|
||||
EventsManager *_events;
|
||||
public:
|
||||
UltimaEarlyEngine(OSystem *syst, const UltimaGameDescription *gameDesc);
|
||||
~UltimaEarlyEngine() override;
|
||||
|
||||
/**
|
||||
* Main method for running the game
|
||||
*/
|
||||
Common::Error run() override;
|
||||
|
||||
/**
|
||||
* Returns supported engine features
|
||||
*/
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
|
||||
/**
|
||||
* Play the game
|
||||
*/
|
||||
void playGame();
|
||||
|
||||
/**
|
||||
* Get a random number
|
||||
*/
|
||||
uint getRandomNumber(uint maxVal) { return _randomSource.getRandomNumber(maxVal); }
|
||||
|
||||
/**
|
||||
* Gets a random number
|
||||
*/
|
||||
uint getRandomNumber(uint min, uint max) {
|
||||
return min + _randomSource.getRandomNumber(max - min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the screen
|
||||
*/
|
||||
Graphics::Screen *getScreen() const override;
|
||||
|
||||
/**
|
||||
* Indicates whether a game state can be loaded.
|
||||
* @param isAutosave Flags whether it's an autosave check
|
||||
*/
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
|
||||
/**
|
||||
* Indicates whether a game state can be saved.
|
||||
* @param isAutosave Flags whether it's an autosave check
|
||||
*/
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
|
||||
/**
|
||||
* Load a savegame
|
||||
*/
|
||||
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
|
||||
|
||||
/**
|
||||
* Save a game state.
|
||||
*/
|
||||
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
|
||||
|
||||
/**
|
||||
* Returns the game type being played
|
||||
*/
|
||||
GameId getGameId() const;
|
||||
|
||||
/**
|
||||
* Returns true if the game is running an enhanced version
|
||||
* as compared to the original game
|
||||
*/
|
||||
bool isEnhanced() const;
|
||||
|
||||
/*
|
||||
* Creates a new hierarchy for the game, that contains all the logic for playing that particular game.
|
||||
*/
|
||||
Game *createGame() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
|
||||
extern Shared::UltimaEarlyEngine *g_vm;
|
||||
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
241
engines/ultima/shared/engine/data_archive.cpp
Normal file
241
engines/ultima/shared/engine/data_archive.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/* 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 "ultima/shared/engine/data_archive.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/compression/unzip.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define DATA_FILENAME "ultima.dat"
|
||||
|
||||
class UltimaDataArchiveMember : public Common::ArchiveMember {
|
||||
private:
|
||||
Common::SharedPtr<Common::ArchiveMember> _member;
|
||||
Common::Path _publicFolder;
|
||||
Common::Path _innerfolder;
|
||||
public:
|
||||
UltimaDataArchiveMember(Common::SharedPtr<Common::ArchiveMember> member,
|
||||
const Common::Path &subfolder) :
|
||||
_member(member), _publicFolder("data/"), _innerfolder(subfolder) {
|
||||
}
|
||||
~UltimaDataArchiveMember() override {}
|
||||
Common::SeekableReadStream *createReadStream() const override {
|
||||
return _member->createReadStream();
|
||||
}
|
||||
Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
|
||||
return _member->createReadStreamForAltStream(altStreamType);
|
||||
}
|
||||
Common::Path getPathInArchive() const override {
|
||||
Common::Path name = _member->getPathInArchive();
|
||||
assert(name.isRelativeTo(_innerfolder));
|
||||
return _publicFolder.join(name.relativeTo(_innerfolder));
|
||||
}
|
||||
Common::U32String getDisplayName() const override {
|
||||
return _member->getDisplayName();
|
||||
}
|
||||
|
||||
Common::String getFileName() const override { return _member->getFileName(); }
|
||||
Common::String getName() const override { return getPathInArchive().toString('/'); }
|
||||
|
||||
bool isDirectory() const override { return _member->isDirectory(); }
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool UltimaDataArchive::load(const Common::Path &subfolder,
|
||||
int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg) {
|
||||
Common::Archive *dataArchive = nullptr;
|
||||
Common::File f;
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
Common::FSNode folder;
|
||||
if (ConfMan.hasKey("extrapath")) {
|
||||
if ((folder = Common::FSNode(ConfMan.getPath("extrapath"))).exists()
|
||||
&& (folder = folder.getChild("files")).exists()
|
||||
&& (folder = folder.getChild(subfolder.baseName())).exists()) {
|
||||
f.open(folder.getChild("version.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!f.isOpen()) {
|
||||
if (!Common::File::exists(DATA_FILENAME) ||
|
||||
(dataArchive = Common::makeZipArchive(DATA_FILENAME)) == 0 ||
|
||||
!f.open(subfolder.join("version.txt"), *dataArchive)) {
|
||||
delete dataArchive;
|
||||
errorMsg = Common::U32String::format(_("Could not locate engine data %s"), DATA_FILENAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the version
|
||||
char buffer[5];
|
||||
f.read(buffer, 4);
|
||||
buffer[4] = '\0';
|
||||
|
||||
int major = 0, minor = 0;
|
||||
if (buffer[1] == '.') {
|
||||
major = buffer[0] - '0';
|
||||
minor = atoi(&buffer[2]);
|
||||
}
|
||||
|
||||
if (major != reqMajorVersion || minor != reqMinorVersion) {
|
||||
delete dataArchive;
|
||||
errorMsg = Common::U32String::format(_("Out of date engine data. Expected %d.%d, but got version %d.%d"),
|
||||
reqMajorVersion, reqMinorVersion, major, minor);
|
||||
return false;
|
||||
}
|
||||
|
||||
// It was all validated correctly
|
||||
Common::Archive *archive;
|
||||
#ifndef RELEASE_BUILD
|
||||
if (!dataArchive)
|
||||
archive = new UltimaDataArchiveProxy(folder);
|
||||
else
|
||||
#endif
|
||||
archive = new UltimaDataArchive(dataArchive, subfolder);
|
||||
|
||||
SearchMan.add("data", archive);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool UltimaDataArchive::hasFile(const Common::Path &path) const {
|
||||
if (!path.isRelativeTo(_publicFolder))
|
||||
return false;
|
||||
|
||||
Common::Path realFilename = innerToPublic(path);
|
||||
return _zip->hasFile(realFilename);
|
||||
}
|
||||
|
||||
int UltimaDataArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
|
||||
Common::ArchiveMemberList innerList;
|
||||
int numMatches = 0;
|
||||
// Test whether we can skip filtering.
|
||||
bool matchAll = matchPathComponents && pattern == "*";
|
||||
|
||||
// First, get all zip members relevant to the current game
|
||||
_zip->listMatchingMembers(innerList, _innerfolder.appendComponent("*"), true);
|
||||
|
||||
// Modify the results to change the filename, then filter with pattern
|
||||
for (const auto &innerMember : innerList) {
|
||||
Common::ArchiveMemberPtr member = Common::ArchiveMemberPtr(
|
||||
new UltimaDataArchiveMember(innerMember, _innerfolder));
|
||||
if (matchAll || member->getPathInArchive().toString().matchString(pattern.toString(), true, matchPathComponents ? nullptr : "/")) {
|
||||
list.push_back(member);
|
||||
++numMatches;
|
||||
}
|
||||
}
|
||||
return numMatches;
|
||||
}
|
||||
|
||||
int UltimaDataArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
return listMatchingMembers(list, "*", true);
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr UltimaDataArchive::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *UltimaDataArchive::createReadStreamForMember(const Common::Path &path) const {
|
||||
if (hasFile(path)) {
|
||||
Common::Path filename = innerToPublic(path);
|
||||
return _zip->createReadStreamForMember(filename);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UltimaDataArchive::isPathDirectory(const Common::Path &path) const {
|
||||
return _zip->isPathDirectory(innerToPublic(path));
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
|
||||
const Common::ArchiveMemberPtr UltimaDataArchiveProxy::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *UltimaDataArchiveProxy::createReadStreamForMember(const Common::Path &path) const {
|
||||
if (hasFile(path))
|
||||
return getNode(path).createReadStream();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::FSNode UltimaDataArchiveProxy::getNode(const Common::Path &name) const {
|
||||
Common::Path remainingName = name.relativeTo(_publicFolder);
|
||||
Common::FSNode node = _folder;
|
||||
|
||||
Common::StringArray components = remainingName.splitComponents();
|
||||
|
||||
if (components.empty()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
for(Common::StringArray::const_iterator it = components.begin(); it != components.end() - 1; it++) {
|
||||
node = node.getChild(*it);
|
||||
if (!node.exists())
|
||||
return node;
|
||||
}
|
||||
|
||||
node = node.getChild(*(components.end() - 1));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int UltimaDataArchiveProxy::listMembers(Common::ArchiveMemberList &list) const {
|
||||
return listMatchingMembers(list, "*", true);
|
||||
}
|
||||
|
||||
int UltimaDataArchiveProxy::listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents) const {
|
||||
// Let FSDirectory adjust the filenames for us by using its prefix feature.
|
||||
// Note: dir is intentionally constructed again on each call to prevent stale entries due to caching:
|
||||
// Since this proxy class is intended for use during development, picking up modifications while the
|
||||
// game is running might be useful.
|
||||
const int maxDepth = 255; // chosen arbitrarily
|
||||
Common::FSDirectory dir(_publicFolder, _folder, maxDepth, false, false, true);
|
||||
if (matchPathComponents && pattern == "*")
|
||||
return dir.listMembers(list);
|
||||
else
|
||||
return dir.listMatchingMembers(list, pattern, matchPathComponents);
|
||||
}
|
||||
|
||||
bool UltimaDataArchiveProxy::isPathDirectory(const Common::Path &path) const {
|
||||
return getNode(path).isDirectory();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
183
engines/ultima/shared/engine/data_archive.h
Normal file
183
engines/ultima/shared/engine/data_archive.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/* 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 ULTIMA_SHARED_ENGINE_DATA_ARCHIVE_H
|
||||
#define ULTIMA_SHARED_ENGINE_DATA_ARCHIVE_H
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/path.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* The data archive class encapsulates access to a specific subfolder within
|
||||
* the ultima.dat data file for a game. It wraps up the subfolder so it can
|
||||
* be accessed in each game as a generic "data" subfolder. This allows the
|
||||
* individual games to simplify their data loading code.
|
||||
*/
|
||||
class UltimaDataArchive : public Common::Archive {
|
||||
private:
|
||||
Common::Archive *_zip;
|
||||
Common::Path _publicFolder;
|
||||
Common::Path _innerfolder;
|
||||
|
||||
|
||||
UltimaDataArchive(Common::Archive *zip, const Common::Path &subfolder) :
|
||||
_zip(zip), _publicFolder("data/"), _innerfolder(subfolder) {}
|
||||
|
||||
Common::Path innerToPublic(const Common::Path &filename) const {
|
||||
assert(filename.isRelativeTo(_publicFolder));
|
||||
return _innerfolder.join(filename.relativeTo(_publicFolder));
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Creates a data archive wrapper for the ultima.dat datafile.
|
||||
* Firstly, for debugging purposes, if a "files" folder exists on any path that
|
||||
* has the given subfolder, it will be used first. This will allow for setting
|
||||
* the ScummVM Extra Path to the create_ultima folder, and it will give preference
|
||||
* the files there. Otherwise, it checks for the presence of ultima.dat, and
|
||||
* if the required data is found, it returns the new archive.
|
||||
* Otherwise, returns an error message in the errorMsg field
|
||||
*/
|
||||
static bool load(const Common::Path &subfolder,
|
||||
int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg);
|
||||
public:
|
||||
~UltimaDataArchive() override {
|
||||
delete _zip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive matching the specified pattern to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of members added to list
|
||||
*/
|
||||
int listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents = false) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path)
|
||||
const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(
|
||||
const Common::Path &path) const override;
|
||||
|
||||
bool isPathDirectory(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
|
||||
/**
|
||||
* The data archive proxy class is used for debugging purposes to access engine data
|
||||
* files when the create_ultima folder is in the search path. It will allow for
|
||||
* local mucking around with the data files and committing changes without having to
|
||||
* recreate the ultima.dat file every time a change is made. ultima.dat then just has
|
||||
* to be recreated prior to a release or when the changes are completed and stable
|
||||
*/
|
||||
class UltimaDataArchiveProxy : public Common::Archive {
|
||||
friend class UltimaDataArchive;
|
||||
private:
|
||||
Common::FSNode _folder;
|
||||
const Common::Path _publicFolder;
|
||||
|
||||
UltimaDataArchiveProxy(const Common::FSNode &folder) : _folder(folder), _publicFolder("data/") {}
|
||||
|
||||
/**
|
||||
* Gets a file node from the passed filename
|
||||
*/
|
||||
Common::FSNode getNode(const Common::Path &name) const;
|
||||
public:
|
||||
~UltimaDataArchiveProxy() override {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override {
|
||||
return path.isRelativeTo(_publicFolder) && getNode(path).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all members of the Archive matching the specified pattern to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of members added to list
|
||||
*/
|
||||
int listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents = false) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path)
|
||||
const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(
|
||||
const Common::Path &path) const override;
|
||||
|
||||
bool isPathDirectory(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
255
engines/ultima/shared/engine/events.cpp
Normal file
255
engines/ultima/shared/engine/events.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "common/events.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/system.h"
|
||||
#include "engines/util.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EventsManager::EventsManager(EventsCallback *callback) : _callback(callback), _playTime(0),
|
||||
_gameCounter(0), _frameCounter(0), _priorFrameCounterTime(0), _buttonsDown(0),
|
||||
_specialButtons(0), _priorFrameTime(0) {
|
||||
}
|
||||
|
||||
void EventsManager::showCursor() {
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void EventsManager::hideCursor() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
bool EventsManager::isCursorVisible() {
|
||||
return CursorMan.isVisible();
|
||||
}
|
||||
|
||||
bool EventsManager::pollEvent(Common::Event &event) {
|
||||
uint32 timer = g_system->getMillis();
|
||||
|
||||
if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) {
|
||||
// Time to build up next game frame
|
||||
_priorFrameCounterTime = timer;
|
||||
nextFrame();
|
||||
}
|
||||
|
||||
// Event handling
|
||||
if (g_system->getEventManager()->pollEvent(event)) {
|
||||
if (isMouseDownEvent(event.type)) {
|
||||
setButtonDown(whichButton(event.type), true);
|
||||
_mousePos = event.mouse;
|
||||
} else if (isMouseUpEvent(event.type)) {
|
||||
setButtonDown(whichButton(event.type), false);
|
||||
_mousePos = event.mouse;
|
||||
} else if (event.type == Common::EVENT_MOUSEMOVE) {
|
||||
_mousePos = event.mouse;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYDOWN: {
|
||||
handleKbdSpecial(event.kbd);
|
||||
break;
|
||||
}
|
||||
case Common::EVENT_KEYUP:
|
||||
handleKbdSpecial(event.kbd);
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_mousePos = event.mouse;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventsManager::pollEvents() {
|
||||
Common::Event event;
|
||||
|
||||
while (pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
eventTarget()->mouseMove(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
eventTarget()->leftButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
eventTarget()->leftButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_MBUTTONDOWN:
|
||||
eventTarget()->middleButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_MBUTTONUP:
|
||||
eventTarget()->middleButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
eventTarget()->rightButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
eventTarget()->rightButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_WHEELUP:
|
||||
case Common::EVENT_WHEELDOWN:
|
||||
eventTarget()->mouseWheel(_mousePos, event.type == Common::EVENT_WHEELUP);
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
eventTarget()->keyDown(event.kbd);
|
||||
break;
|
||||
case Common::EVENT_KEYUP:
|
||||
eventTarget()->keyUp(event.kbd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::pollEventsAndWait() {
|
||||
pollEvents();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
void EventsManager::nextFrame() {
|
||||
++_frameCounter;
|
||||
++_playTime;
|
||||
|
||||
// Handle any idle updates
|
||||
if (!_eventTargets.empty())
|
||||
eventTarget()->onIdle();
|
||||
|
||||
// Render anything pending for the screen
|
||||
Graphics::Screen *screen = _callback->getScreen();
|
||||
if (screen)
|
||||
screen->update();
|
||||
}
|
||||
|
||||
void EventsManager::setButtonDown(MouseButton button, bool isDown) {
|
||||
assert(button != BUTTON_NONE);
|
||||
|
||||
byte mask = 0;
|
||||
switch (button) {
|
||||
case BUTTON_LEFT:
|
||||
mask = MK_LBUTTON;
|
||||
break;
|
||||
case BUTTON_RIGHT:
|
||||
mask = MK_RBUTTON;
|
||||
break;
|
||||
case BUTTON_MIDDLE:
|
||||
mask = MK_MBUTTON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isDown) {
|
||||
_buttonsDown |= BUTTON_MASK(button);
|
||||
_specialButtons |= mask;
|
||||
} else {
|
||||
_buttonsDown &= ~BUTTON_MASK(button);
|
||||
_specialButtons &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 EventsManager::getTicksCount() const {
|
||||
return _frameCounter * GAME_FRAME_TIME;
|
||||
}
|
||||
|
||||
void EventsManager::sleep(uint time) {
|
||||
uint32 delayEnd = g_system->getMillis() + time;
|
||||
|
||||
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd)
|
||||
pollEventsAndWait();
|
||||
}
|
||||
|
||||
bool EventsManager::waitForPress(uint expiry) {
|
||||
uint32 delayEnd = g_system->getMillis() + expiry;
|
||||
CPressTarget pressTarget;
|
||||
addTarget(&pressTarget);
|
||||
|
||||
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd && !pressTarget._pressed) {
|
||||
pollEventsAndWait();
|
||||
}
|
||||
|
||||
removeTarget();
|
||||
return pressTarget._pressed;
|
||||
}
|
||||
|
||||
void EventsManager::setMousePos(const Point &pt) {
|
||||
g_system->warpMouse(pt.x, pt.y);
|
||||
_mousePos = pt;
|
||||
eventTarget()->mouseMove(_mousePos);
|
||||
}
|
||||
|
||||
void EventsManager::handleKbdSpecial(Common::KeyState keyState) {
|
||||
if (keyState.flags & Common::KBD_CTRL)
|
||||
_specialButtons |= MK_CONTROL;
|
||||
else
|
||||
_specialButtons &= ~MK_CONTROL;
|
||||
|
||||
if (keyState.flags & Common::KBD_SHIFT)
|
||||
_specialButtons |= MK_SHIFT;
|
||||
else
|
||||
_specialButtons &= ~MK_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
bool shouldQuit() {
|
||||
return g_engine->shouldQuit();
|
||||
}
|
||||
|
||||
bool isMouseDownEvent(Common::EventType type) {
|
||||
return type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_RBUTTONDOWN
|
||||
|| type == Common::EVENT_MBUTTONDOWN;
|
||||
}
|
||||
|
||||
bool isMouseUpEvent(Common::EventType type) {
|
||||
return type == Common::EVENT_LBUTTONUP || type == Common::EVENT_RBUTTONUP
|
||||
|| type == Common::EVENT_MBUTTONUP;
|
||||
}
|
||||
|
||||
MouseButton whichButton(Common::EventType type) {
|
||||
if (type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_LBUTTONUP)
|
||||
return BUTTON_LEFT;
|
||||
else if (type == Common::EVENT_RBUTTONDOWN || type == Common::EVENT_RBUTTONUP)
|
||||
return BUTTON_RIGHT;
|
||||
else if (type == Common::EVENT_MBUTTONDOWN || type == Common::EVENT_MBUTTONUP)
|
||||
return BUTTON_MIDDLE;
|
||||
else
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
338
engines/ultima/shared/engine/events.h
Normal file
338
engines/ultima/shared/engine/events.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/* 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 ULTIMA_SHARED_ENGINE_EVENTS_H
|
||||
#define ULTIMA_SHARED_ENGINE_EVENTS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/events.h"
|
||||
#include "common/stack.h"
|
||||
#include "gui/debugger.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define GAME_FRAME_RATE (1000 / 50)
|
||||
#define GAME_FRAME_TIME 50
|
||||
#define SCREEN_UPDATE_TIME 10
|
||||
#define BUTTON_MASK(MB) (1 << ((int)(MB) - 1))
|
||||
#define DOUBLE_CLICK_TIME 100
|
||||
|
||||
enum MouseButton {
|
||||
BUTTON_NONE = 0,
|
||||
BUTTON_LEFT = 1,
|
||||
BUTTON_RIGHT = 2,
|
||||
BUTTON_MIDDLE = 3,
|
||||
MOUSE_LAST
|
||||
};
|
||||
|
||||
enum SpecialButtons {
|
||||
MK_LBUTTON = 1, MK_RBUTTON = 2, MK_MBUTTON = 4, MK_SHIFT = 8, MK_CONTROL = 0x10
|
||||
};
|
||||
|
||||
/**
|
||||
* A base class for windows that can receive event messages
|
||||
*/
|
||||
class EventTarget {
|
||||
public:
|
||||
virtual ~EventTarget() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to handle any regular updates the game requires
|
||||
*/
|
||||
virtual void onIdle() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse/key event handlers
|
||||
*/
|
||||
virtual void mouseMove(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonDoubleClick(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonDoubleClick(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void rightButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void rightButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void mouseWheel(const Common::Point &mousePos, bool wheelUp) {
|
||||
}
|
||||
virtual void keyDown(Common::KeyState keyState) {
|
||||
}
|
||||
virtual void keyUp(Common::KeyState keyState) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An eent target used for waiting for a mouse or keypress
|
||||
*/
|
||||
class CPressTarget : public EventTarget {
|
||||
public:
|
||||
bool _pressed;
|
||||
public:
|
||||
CPressTarget() : _pressed(false) {
|
||||
}
|
||||
~CPressTarget() override {
|
||||
}
|
||||
void leftButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void middleButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void rightButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void keyDown(Common::KeyState keyState) override {
|
||||
_pressed = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract interface for engine functionality the events manager needs to access
|
||||
*/
|
||||
class EventsCallback {
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~EventsCallback() {}
|
||||
|
||||
/**
|
||||
* Get the screen
|
||||
*/
|
||||
virtual Graphics::Screen *getScreen() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class EventsManager {
|
||||
private:
|
||||
EventsCallback *_callback;
|
||||
Common::Stack<EventTarget *> _eventTargets;
|
||||
uint32 _frameCounter;
|
||||
uint32 _priorFrameTime;
|
||||
uint32 _priorFrameCounterTime;
|
||||
uint32 _gameCounter;
|
||||
uint32 _playTime;
|
||||
Point _mousePos;
|
||||
uint _specialButtons;
|
||||
uint8 _buttonsDown;
|
||||
|
||||
/**
|
||||
* Check whether it's time to display the next screen frame
|
||||
*/
|
||||
bool checkForNextFrameCounter();
|
||||
|
||||
/**
|
||||
* Return the currently active event target
|
||||
*/
|
||||
EventTarget *eventTarget() const {
|
||||
return _eventTargets.top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles setting/resettings special buttons on key up/down
|
||||
*/
|
||||
void handleKbdSpecial(Common::KeyState keyState);
|
||||
|
||||
/**
|
||||
* Sets whether a given button is depressed
|
||||
*/
|
||||
void setButtonDown(MouseButton button, bool isDown);
|
||||
protected:
|
||||
/**
|
||||
* Handles moving to the next game frame
|
||||
*/
|
||||
virtual void nextFrame();
|
||||
public:
|
||||
EventsManager(EventsCallback *callback);
|
||||
virtual ~EventsManager() {}
|
||||
|
||||
/**
|
||||
* Adds a new event target to the top of the list. It will get
|
||||
* all events generated until such time as another is pushed on
|
||||
* top of it, or the removeTarget method is called
|
||||
*/
|
||||
void addTarget(EventTarget *target) {
|
||||
_eventTargets.push(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the currently active event target
|
||||
*/
|
||||
void removeTarget() {
|
||||
_eventTargets.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the ScummVM backend for any pending events, passing out the event, if any
|
||||
*/
|
||||
|
||||
virtual bool pollEvent(Common::Event &event);
|
||||
|
||||
/**
|
||||
* Checks for any pending events. This differs from pollEvent, in that the event manager will dispatch
|
||||
* all pending events to the currently registered active event target, rather than simply returning a
|
||||
* single event like pollEvent does
|
||||
*/
|
||||
void pollEvents();
|
||||
|
||||
/**
|
||||
* Poll for events and introduce a small delay, to allow the system to
|
||||
* yield to other running programs
|
||||
*/
|
||||
void pollEventsAndWait();
|
||||
|
||||
/**
|
||||
* Return the current game frame number
|
||||
*/
|
||||
uint32 getFrameCounter() const {
|
||||
return _frameCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the elapsed playtime
|
||||
*/
|
||||
uint32 getTicksCount() const;
|
||||
|
||||
/**
|
||||
* Sleep for a specified period of time
|
||||
*/
|
||||
void sleep(uint time);
|
||||
|
||||
/**
|
||||
* Wait for a mouse or keypress
|
||||
*/
|
||||
bool waitForPress(uint expiry);
|
||||
|
||||
/**
|
||||
* Sets the mouse position
|
||||
*/
|
||||
void setMousePos(const Point &pt);
|
||||
|
||||
/*
|
||||
* Return whether a given special key is currently pressed
|
||||
*/
|
||||
bool isSpecialPressed(SpecialButtons btn) const {
|
||||
return (_specialButtons & btn) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bitset of the currently pressed special buttons
|
||||
*/
|
||||
uint getSpecialButtons() const {
|
||||
return _specialButtons;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the cursor
|
||||
*/
|
||||
virtual void setCursor(int cursorId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the mouse cursor
|
||||
*/
|
||||
void showCursor();
|
||||
|
||||
/**
|
||||
* Hide the mouse cursor
|
||||
*/
|
||||
void hideCursor();
|
||||
|
||||
/**
|
||||
* Returns if the mouse cursor is visible
|
||||
*/
|
||||
bool isCursorVisible();
|
||||
|
||||
/**
|
||||
* Gets the current total ticks
|
||||
*/
|
||||
uint32 getTicks() {
|
||||
return _frameCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total overall play time
|
||||
*/
|
||||
uint32 playTime() const {
|
||||
return _playTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current play time
|
||||
*/
|
||||
void setPlayTime(uint32 time) {
|
||||
_playTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given mouse button is pressed
|
||||
*/
|
||||
inline bool isButtonDown(MouseButton button) const {
|
||||
return (_buttonsDown & BUTTON_MASK(button)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any mouse button is pressed
|
||||
*/
|
||||
bool isButtonDown() const {
|
||||
return isButtonDown(BUTTON_LEFT) || isButtonDown(BUTTON_RIGHT) || isButtonDown(BUTTON_MIDDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mouse buttons states
|
||||
*/
|
||||
byte getButtonState() const {
|
||||
return _buttonsDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mouse position
|
||||
*/
|
||||
Common::Point getMousePos() const {
|
||||
return _mousePos;
|
||||
}
|
||||
};
|
||||
|
||||
extern bool isMouseDownEvent(Common::EventType type);
|
||||
|
||||
extern bool isMouseUpEvent(Common::EventType type);
|
||||
|
||||
extern MouseButton whichButton(Common::EventType type);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
118
engines/ultima/shared/engine/input_handler.cpp
Normal file
118
engines/ultima/shared/engine/input_handler.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 "ultima/shared/engine/input_handler.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
InputHandler::InputHandler(GameBase *game) : _game(game), _inputTranslator(nullptr), _dragging(false),
|
||||
_buttonDown(false), _lockCount(0), _abortMessage(false) {
|
||||
}
|
||||
|
||||
InputHandler::~InputHandler() {
|
||||
}
|
||||
|
||||
void InputHandler::setTranslator(InputTranslator *translator) {
|
||||
_inputTranslator = translator;
|
||||
}
|
||||
|
||||
void InputHandler::incLockCount() {
|
||||
++_lockCount;
|
||||
}
|
||||
|
||||
void InputHandler::decLockCount() {
|
||||
--_lockCount;
|
||||
assert(_lockCount >= 0);
|
||||
|
||||
if (_lockCount == 0 && _inputTranslator) {
|
||||
if (_dragging && !_inputTranslator->isMousePressed()) {
|
||||
CMouseButtonUpMsg upMsg(_mousePos, MK_LBUTTON);
|
||||
handleMessage(upMsg);
|
||||
}
|
||||
|
||||
_buttonDown = _inputTranslator->isMousePressed();
|
||||
_abortMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::handleMessage(CMessage &msg, bool respectLock) {
|
||||
if (!respectLock || _lockCount <= 0) {
|
||||
processMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::processMessage(CMessage *msg) {
|
||||
const CMouseMsg *mouseMsg = dynamic_cast<const CMouseMsg *>(msg);
|
||||
_abortMessage = false;
|
||||
dispatchMessage(msg);
|
||||
|
||||
if (_abortMessage) {
|
||||
_abortMessage = false;
|
||||
} else if (mouseMsg) {
|
||||
// Keep the game state mouse position up to date
|
||||
if (_mousePos != mouseMsg->_mousePos) {
|
||||
_mousePos = mouseMsg->_mousePos;
|
||||
}
|
||||
|
||||
// Set flag for whether a mouse button is currently being pressed
|
||||
if (mouseMsg->isButtonDownMsg())
|
||||
_buttonDown = true;
|
||||
else if (mouseMsg->isButtonUpMsg())
|
||||
_buttonDown = false;
|
||||
|
||||
// Drag events generation
|
||||
if (_dragging) {
|
||||
if (mouseMsg->isMouseMoveMsg()) {
|
||||
CMouseDragMsg moveMsg(_mousePos, mouseMsg->_buttons);
|
||||
dispatchMessage(&moveMsg);
|
||||
} else if (mouseMsg->isButtonUpMsg()) {
|
||||
_dragging = false;
|
||||
}
|
||||
} else if (_buttonDown) {
|
||||
if (!mouseMsg->isMouseMoveMsg()) {
|
||||
// Save where the drag movement started from
|
||||
_dragStartPos = _mousePos;
|
||||
} else {
|
||||
Point delta = _mousePos - _dragStartPos;
|
||||
int distance = (int)sqrt(double(delta.x * delta.x + delta.y * delta.y));
|
||||
|
||||
if (distance > 4) {
|
||||
// A drag has started
|
||||
_dragging = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::dispatchMessage(CMessage *msg) {
|
||||
Gfx::VisualItem *view = _game->getView();
|
||||
if (view)
|
||||
msg->execute(view);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
78
engines/ultima/shared/engine/input_handler.h
Normal file
78
engines/ultima/shared/engine/input_handler.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_INPUT_HANDLER_H
|
||||
#define ULTIMA_SHARED_ENGINE_INPUT_HANDLER_H
|
||||
|
||||
#include "ultima/shared/engine/input_translator.h"
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class GameBase;
|
||||
|
||||
class InputHandler {
|
||||
private:
|
||||
/**
|
||||
* Process and dispatch a passed message
|
||||
*/
|
||||
void processMessage(CMessage *msg);
|
||||
|
||||
/**
|
||||
* Dispatches a message to the project
|
||||
*/
|
||||
void dispatchMessage(CMessage *msg);
|
||||
public:
|
||||
GameBase *_game;
|
||||
InputTranslator *_inputTranslator;
|
||||
bool _dragging;
|
||||
bool _buttonDown;
|
||||
Point _mousePos;
|
||||
Point _dragStartPos;
|
||||
int _lockCount;
|
||||
bool _abortMessage;
|
||||
public:
|
||||
InputHandler(GameBase *game);
|
||||
~InputHandler();
|
||||
|
||||
void setTranslator(InputTranslator *translator);
|
||||
|
||||
/**
|
||||
* Increment the lock count
|
||||
*/
|
||||
void incLockCount();
|
||||
|
||||
/**
|
||||
* Decrement the lock count on the input handler
|
||||
*/
|
||||
void decLockCount();
|
||||
|
||||
/**
|
||||
* Handles a genereated mouse message
|
||||
*/
|
||||
void handleMessage(CMessage &msg, bool respectLock = true);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
123
engines/ultima/shared/engine/input_translator.cpp
Normal file
123
engines/ultima/shared/engine/input_translator.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/* 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 "ultima/shared/engine/input_handler.h"
|
||||
#include "ultima/shared/engine/input_translator.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
InputTranslator::InputTranslator(InputHandler *inputHandler) :
|
||||
_inputHandler(inputHandler) {
|
||||
inputHandler->setTranslator(this);
|
||||
}
|
||||
|
||||
int InputTranslator::getButtons(int special) const {
|
||||
int buttons = 0;
|
||||
if (special & MK_LBUTTON)
|
||||
buttons |= MB_LEFT;
|
||||
if (special & MK_MBUTTON)
|
||||
buttons |= MB_MIDDLE;
|
||||
if (special & MK_RBUTTON)
|
||||
buttons |= MB_RIGHT;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
void InputTranslator::mouseMove(int special, const Point &pt) {
|
||||
CMouseMoveMsg msg(pt, getButtons(special));
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::mouseDrag(int special, const Point &pt) {
|
||||
CMouseDragMsg msg(pt, getButtons(special));
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::mouseWheel(bool wheelUp, const Point &pt) {
|
||||
CMouseWheelMsg msg(pt, wheelUp);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::keyDown(const Common::KeyState &keyState) {
|
||||
CKeypressMsg pressMsg(keyState);
|
||||
_inputHandler->handleMessage(pressMsg);
|
||||
|
||||
if (keyState.ascii >= 32 && keyState.ascii <= 127) {
|
||||
CKeyCharMsg charMsg(keyState.ascii);
|
||||
_inputHandler->handleMessage(charMsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputTranslator::isMousePressed() const {
|
||||
return g_vm->_events->getSpecialButtons() & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
67
engines/ultima/shared/engine/input_translator.h
Normal file
67
engines/ultima/shared/engine/input_translator.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 ULTIMA_SHARED_ENGINE_INPUT_TRANSLATOR_H
|
||||
#define ULTIMA_SHARED_ENGINE_INPUT_TRANSLATOR_H
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class InputHandler;
|
||||
|
||||
class InputTranslator {
|
||||
private:
|
||||
/**
|
||||
* Converts the special buttons bitset into a buttons bitset
|
||||
*/
|
||||
int getButtons(int special) const;
|
||||
public:
|
||||
InputHandler *_inputHandler;
|
||||
public:
|
||||
InputTranslator(InputHandler *inputHandler);
|
||||
|
||||
void mouseMove(int special, const Point &pt);
|
||||
void mouseDrag(int special, const Point &pt);
|
||||
void leftButtonDown(int special, const Point &pt);
|
||||
void leftButtonUp(int special, const Point &pt);
|
||||
void leftButtonDoubleClick(int special, const Point &pt);
|
||||
void middleButtonDown(int special, const Point &pt);
|
||||
void middleButtonUp(int special, const Point &pt);
|
||||
void middleButtonDoubleClick(int special, const Point &pt);
|
||||
void rightButtonDown(int special, const Point &pt);
|
||||
void rightButtonUp(int special, const Point &pt);
|
||||
void mouseWheel(bool wheelUp, const Point &pt);
|
||||
void rightButtonDoubleClick(int special, const Point &pt);
|
||||
void keyDown(const Common::KeyState &keyState);
|
||||
|
||||
/**
|
||||
* Returns true if any mouse button is currently pressed
|
||||
*/
|
||||
bool isMousePressed() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
121
engines/ultima/shared/engine/messages.cpp
Normal file
121
engines/ultima/shared/engine/messages.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
CMessage::CMessage() : BaseObject() {
|
||||
}
|
||||
|
||||
bool CMessage::execute(TreeItem *target, const ClassDef *classDef, int flags) {
|
||||
// If no target was specified, then there's nothing to do
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
TreeItem *item = target;
|
||||
TreeItem *nextItem = nullptr;
|
||||
do {
|
||||
if (flags & MSGFLAG_SCAN)
|
||||
nextItem = item->scan(target);
|
||||
|
||||
if (!classDef || item->isInstanceOf(*classDef)) {
|
||||
bool handled = perform(item);
|
||||
|
||||
if (handled) {
|
||||
result = true;
|
||||
if (flags & MSGFLAG_BREAK_IF_HANDLED)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
item = nextItem;
|
||||
} while (nextItem);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMessage::execute(const Common::String &target, const ClassDef *classDef, int flags) {
|
||||
// Scan for the target by name
|
||||
GameBase *game = g_vm->_game;
|
||||
for (TreeItem *treeItem = game; treeItem; treeItem = treeItem->scan(game)) {
|
||||
if (!treeItem->getName().compareToIgnoreCase(target))
|
||||
return execute(treeItem, classDef, flags);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const MSGMAP_ENTRY *CMessage::findMapEntry(const TreeItem *treeItem, const ClassDef &classDef) {
|
||||
// Iterate through the class and any parent classes
|
||||
for (const MSGMAP *msgMap = treeItem->getMessageMap(); msgMap->pFnGetBaseMap;
|
||||
msgMap = msgMap->pFnGetBaseMap()) {
|
||||
// Iterate through the map entries for this class
|
||||
for (const MSGMAP_ENTRY *entry = msgMap->lpEntries;
|
||||
entry->_classDef != nullptr; ++entry) {
|
||||
// Check if the class or any of it's ancesotrs is handled by this entry
|
||||
for (ClassDef def = (*entry->_classDef)(); def.hasParent(); def = def.parent()) {
|
||||
if (def == classDef)
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::perform(TreeItem *treeItem) {
|
||||
const MSGMAP_ENTRY *entry = findMapEntry(treeItem, getType());
|
||||
return entry && (*treeItem.*(entry->_fn))(this);
|
||||
}
|
||||
|
||||
bool CMessage::supports(const TreeItem *treeItem, const ClassDef &classDef) {
|
||||
return findMapEntry(treeItem, classDef) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isMouseMsg() const {
|
||||
return dynamic_cast<const CMouseMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isButtonDownMsg() const {
|
||||
return dynamic_cast<const CMouseButtonDownMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isButtonUpMsg() const {
|
||||
return dynamic_cast<const CMouseButtonUpMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isMouseMoveMsg() const {
|
||||
return dynamic_cast<const CMouseMoveMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isDoubleClickMsg() const {
|
||||
return dynamic_cast<const CMouseDoubleClickMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
407
engines/ultima/shared/engine/messages.h
Normal file
407
engines/ultima/shared/engine/messages.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/* 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 ULTIMA_SHARED_ENGINE_MESSAGES_H
|
||||
#define ULTIMA_SHARED_ENGINE_MESSAGES_H
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "common/events.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/core/base_object.h"
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
enum MessageFlag {
|
||||
MSGFLAG_SCAN = 1,
|
||||
MSGFLAG_BREAK_IF_HANDLED = 2,
|
||||
MSGFLAG_CLASS_DEF = 4
|
||||
};
|
||||
|
||||
class CMessage;
|
||||
namespace Gfx {
|
||||
class VisualItem;
|
||||
class TextInput;
|
||||
class Popup;
|
||||
}
|
||||
|
||||
#define MESSAGEDEF(theClass) \
|
||||
static ClassDef type() { return ClassDef(#theClass, &CMessage::type); } \
|
||||
virtual ClassDef getType() const { return type(); }
|
||||
#define MESSAGEDEFP(theClass, baseClass) \
|
||||
static ClassDef type() { return ClassDef(#theClass, &baseClass::type); } \
|
||||
virtual ClassDef getType() const { return type(); }
|
||||
|
||||
#define MESSAGE0(NAME) \
|
||||
class NAME: public CMessage { \
|
||||
public: NAME() : CMessage() {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE1(NAME, F1, N1, V1) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; \
|
||||
NAME(F1 N1 = V1) : CMessage(), _##N1(N1) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE2(NAME, F1, N1, V1, F2, N2, V2) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2) : CMessage(), _##N1(N1), _##N2(N2) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE3(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; F3 _##N3; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2, F3 N3 = V3) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE4(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3, F4, N4, V4) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; F3 _##N3; F4 _##N4; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2, F3 N3 = V3, F4 N4 = V4) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3), _##N4(N4) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for all messages
|
||||
*/
|
||||
class CMessage : public BaseObject {
|
||||
private:
|
||||
/**
|
||||
* Find a map entry that supports the given class
|
||||
*/
|
||||
static const MSGMAP_ENTRY *findMapEntry(const TreeItem *treeItem, const ClassDef &classDef);
|
||||
public:
|
||||
MESSAGEDEFP(CMessage, BaseObject);
|
||||
CMessage();
|
||||
|
||||
/**
|
||||
* Executes the message, passing it on to the designated target,
|
||||
* and optionally it's children
|
||||
*/
|
||||
bool execute(TreeItem *target, const ClassDef *classDef = nullptr,
|
||||
int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED);
|
||||
|
||||
/**
|
||||
* Executes the message, passing it on to the designated target,
|
||||
* and optionally it's children
|
||||
*/
|
||||
bool execute(const Common::String &target, const ClassDef *classDef = nullptr,
|
||||
int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED);
|
||||
|
||||
/**
|
||||
* Makes the passed item execute the message
|
||||
*/
|
||||
virtual bool perform(TreeItem *treeItem);
|
||||
|
||||
/**
|
||||
* Returns true if the passed item supports the specified message class
|
||||
*/
|
||||
static bool supports(const TreeItem *treeItem, const ClassDef &classDef);
|
||||
|
||||
virtual bool isMouseMsg() const;
|
||||
virtual bool isButtonDownMsg() const;
|
||||
virtual bool isButtonUpMsg() const;
|
||||
virtual bool isMouseMoveMsg() const;
|
||||
virtual bool isDoubleClickMsg() const;
|
||||
};
|
||||
|
||||
|
||||
enum CMouseButton {
|
||||
MB_LEFT = 1, MB_MIDDLE = 2, MB_RIGHT = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for the different mouse notifications
|
||||
*/
|
||||
class CMouseMsg : public CMessage {
|
||||
public:
|
||||
int _buttons;
|
||||
Point _mousePos;
|
||||
public:
|
||||
MESSAGEDEF(CMouseMsg);
|
||||
|
||||
CMouseMsg() : _buttons(0) {}
|
||||
CMouseMsg(const Point &pt, int buttons) :
|
||||
_mousePos(pt), _buttons(buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse movement
|
||||
*
|
||||
*/
|
||||
class CMouseMoveMsg : public CMouseMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseMoveMsg, CMouseMsg);
|
||||
CMouseMoveMsg() : CMouseMsg() {}
|
||||
CMouseMoveMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies of a mouse drag operation
|
||||
*/
|
||||
class CMouseDragMsg : public CMouseMoveMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseDragMsg, CMouseMoveMsg);
|
||||
CMouseDragMsg() : CMouseMoveMsg() {}
|
||||
CMouseDragMsg(const Point &pt, int buttons) : CMouseMoveMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for mouse button notifications
|
||||
*/
|
||||
class CMouseButtonMsg : public CMouseMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonMsg, CMouseMsg);
|
||||
CMouseButtonMsg() : CMouseMsg() {}
|
||||
CMouseButtonMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse button down
|
||||
*/
|
||||
class CMouseButtonDownMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonDownMsg, CMouseButtonMsg);
|
||||
CMouseButtonDownMsg() : CMouseButtonMsg() {}
|
||||
CMouseButtonDownMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse button release
|
||||
*/
|
||||
class CMouseButtonUpMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonUpMsg, CMouseButtonMsg);
|
||||
CMouseButtonUpMsg() : CMouseButtonMsg() {}
|
||||
CMouseButtonUpMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse wheel action
|
||||
*/
|
||||
class CMouseWheelMsg : public CMouseMsg {
|
||||
public:
|
||||
bool _wheelUp;
|
||||
public:
|
||||
MESSAGEDEFP(CMouseWheelMsg, CMouseMsg);
|
||||
CMouseWheelMsg() : CMouseMsg(), _wheelUp(false) {}
|
||||
CMouseWheelMsg(const Point &pt, bool wheelUp) :
|
||||
CMouseMsg(pt, 0), _wheelUp(wheelUp) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse double-click
|
||||
*/
|
||||
class CMouseDoubleClickMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseDuobleClickMsg, CMouseButtonMsg);
|
||||
CMouseDoubleClickMsg() : CMouseButtonMsg() {}
|
||||
CMouseDoubleClickMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to notify that a rendering frame has finished, occurring at GAME_FRAME_RATE times every second
|
||||
*/
|
||||
MESSAGE1(CFrameMsg, uint, ticks, 0);
|
||||
|
||||
/**
|
||||
* Notifies a game view is being hidden
|
||||
*/
|
||||
MESSAGE2(CHideMsg, Gfx::VisualItem *, view, (Gfx::VisualItem *)nullptr, bool, fadeOut, false);
|
||||
|
||||
/**
|
||||
* Show a prompt in the info area, and get a keypress for a command
|
||||
*/
|
||||
MESSAGE1(CInfoGetCommandKeypress, TreeItem *, responder, (TreeItem *)nullptr);
|
||||
|
||||
/**
|
||||
* Get a keypress in the info area
|
||||
*/
|
||||
MESSAGE1(CInfoGetKeypress, TreeItem *, responder, (TreeItem *)nullptr);
|
||||
|
||||
/**
|
||||
* Get a text input in the input area
|
||||
*/
|
||||
MESSAGE3(CInfoGetInput, TreeItem *, responder, (TreeItem *)nullptr, bool, isNumeric, false, size_t, maxCharacters, 10);
|
||||
|
||||
/**
|
||||
* Adds text strings to the info area
|
||||
*/
|
||||
MESSAGE3(CInfoMsg, Common::String, text, "", bool, newLine, true, bool, replaceLine, false);
|
||||
|
||||
/**
|
||||
* Signals an unknown/unhandled keypress
|
||||
*/
|
||||
MESSAGE0(CHuhMsg);
|
||||
|
||||
/**
|
||||
* Signals a single standard ASCII keypress
|
||||
*/
|
||||
MESSAGE1(CKeyCharMsg, int, key, 32);
|
||||
|
||||
/**
|
||||
* Signals a keypress
|
||||
*/
|
||||
MESSAGE1(CKeypressMsg, Common::KeyState, keyState, Common::KeyState());
|
||||
|
||||
/**
|
||||
* Called when a popup is finally shown
|
||||
*/
|
||||
MESSAGE1(CPopupShownMsg, Gfx::Popup *, view, (Gfx::Popup *)nullptr);
|
||||
|
||||
/**
|
||||
* Called when a popup is hidden
|
||||
*/
|
||||
MESSAGE1(CPopupHiddenMsg, Gfx::Popup *, view, (Gfx::Popup *)nullptr);
|
||||
|
||||
/**
|
||||
* Called when a game view is shown
|
||||
*/
|
||||
MESSAGE2(CShowMsg, Gfx::VisualItem *, view, (Gfx::VisualItem *)nullptr, bool, fadeIn, false);
|
||||
|
||||
/**
|
||||
* Used when text input is finished, to pass the text back to the owning view
|
||||
*/
|
||||
MESSAGE2(CTextInputMsg, Common::String, text, "", bool, escaped, false);
|
||||
|
||||
/**
|
||||
* Used when character input is finished, to pass the text back to the owning view
|
||||
*/
|
||||
MESSAGE1(CCharacterInputMsg, Common::KeyState, keyState, Common::KeyState());
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Used to trigger a party movement
|
||||
*/
|
||||
MESSAGE1(CMoveMsg, int, direction, 0);
|
||||
|
||||
/**
|
||||
* Used to trigger an attack
|
||||
*/
|
||||
MESSAGE1(CAttackMsg, int, direction, 0);
|
||||
|
||||
/**
|
||||
* Used to trigger a board action
|
||||
*/
|
||||
MESSAGE0(CBoardMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a cast action
|
||||
*/
|
||||
MESSAGE0(CCastMsg);
|
||||
|
||||
/**
|
||||
* Climb up or down
|
||||
*/
|
||||
MESSAGE0(CClimbMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a drop action
|
||||
*/
|
||||
MESSAGE0(CDropMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an Enter action
|
||||
*/
|
||||
MESSAGE0(CEnterMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an exit action
|
||||
*/
|
||||
MESSAGE0(CExitTransportMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a fire action
|
||||
*/
|
||||
MESSAGE0(CFireMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a Get action
|
||||
*/
|
||||
MESSAGE0(CGetMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a HyperJump action
|
||||
*/
|
||||
MESSAGE0(CHyperJumpMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an inform action
|
||||
*/
|
||||
MESSAGE0(CInformMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an open action
|
||||
*/
|
||||
MESSAGE0(COpenMsg);
|
||||
|
||||
/**
|
||||
* Pass a turn
|
||||
*/
|
||||
MESSAGE0(CPassMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a quit (save) action
|
||||
*/
|
||||
MESSAGE0(CQuitMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a ready item/weapon/spell action
|
||||
*/
|
||||
MESSAGE0(CReadyMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a stats action
|
||||
*/
|
||||
MESSAGE0(CStatsMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a steal action
|
||||
*/
|
||||
MESSAGE0(CStealMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a Transact action
|
||||
*/
|
||||
MESSAGE0(CTransactMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an Unlock action
|
||||
*/
|
||||
MESSAGE0(CUnlockMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a view change action
|
||||
*/
|
||||
MESSAGE0(CViewChangeMsg);
|
||||
|
||||
/**
|
||||
* Used to signal an end of turn
|
||||
*/
|
||||
MESSAGE0(CEndOfTurnMsg);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
265
engines/ultima/shared/engine/resources.cpp
Normal file
265
engines/ultima/shared/engine/resources.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/* 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 "ultima/shared/engine/resources.h"
|
||||
#include "ultima/shared/early/font_resources.h"
|
||||
#include "common/endian.h"
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
#include "ultima/ultima1/core/resources.h"
|
||||
#endif
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool Resources::open() {
|
||||
// Save locally constructred resources to the archive manager for access
|
||||
Shared::FontResources sharedFonts(this);
|
||||
sharedFonts.save();
|
||||
#ifndef RELEASE_BUILD
|
||||
Ultima1::GameResources u1Data(this);
|
||||
u1Data.save();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Resources::addResource(const Common::Path &name, const byte *data, size_t size) {
|
||||
// Add a new entry to the local resources list for the passed data
|
||||
_localResources.push_back(LocalResource());
|
||||
LocalResource &lr = _localResources[_localResources.size() - 1];
|
||||
|
||||
lr._name = name;
|
||||
lr._data.resize(size);
|
||||
Common::copy(data, data + size, &lr._data[0]);
|
||||
}
|
||||
|
||||
bool Resources::hasFile(const Common::Path &path) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx)
|
||||
if (_localResources[idx]._name.equalsIgnoreCase(path))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int Resources::listMembers(Common::ArchiveMemberList &list) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx) {
|
||||
list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_localResources[idx]._name, *this)));
|
||||
}
|
||||
|
||||
return _localResources.size();
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr Resources::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *Resources::createReadStreamForMember(const Common::Path &path) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx) {
|
||||
const LocalResource &lr = _localResources[idx];
|
||||
if (lr._name.equalsIgnoreCase(path))
|
||||
return new Common::MemoryReadStream(&lr._data[0], lr._data.size());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void Resources::FileResource::load(File &f) {
|
||||
_name = f.readString();
|
||||
_offset = f.readUint32LE();
|
||||
_size = f.readUint16LE();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
ResourceFile::ResourceFile(const Common::Path &filename) : _filename(filename), _bufferP(_buffer) {
|
||||
Common::fill(_buffer, _buffer + STRING_BUFFER_SIZE, 0);
|
||||
}
|
||||
|
||||
void ResourceFile::load() {
|
||||
_file.open(_filename);
|
||||
synchronize();
|
||||
_file.close();
|
||||
}
|
||||
|
||||
void ResourceFile::syncString(const char *&str) {
|
||||
str = _bufferP;
|
||||
do {
|
||||
*_bufferP = _file.readByte();
|
||||
} while (*_bufferP++);
|
||||
|
||||
assert(_bufferP < (_buffer + STRING_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
void ResourceFile::syncStrings(const char **str, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
|
||||
void ResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumber(int &val) {
|
||||
val = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers(int *vals, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, count3, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2 * count3; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncBytes(byte *vals, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
_file.read(vals, count);
|
||||
}
|
||||
|
||||
void ResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
_file.read(vals, count1 * count2);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void LocalResourceFile::save() {
|
||||
synchronize();
|
||||
_file.finalize();
|
||||
_owner->addResource(_filename, _file.getData(), _file.size());
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncString(const char *&str) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncString(str);
|
||||
} else {
|
||||
_file.writeString(str);
|
||||
_file.writeByte('\0');
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncStrings(const char **str, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncStrings(str, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncStrings2D(str, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumber(int &val) {
|
||||
if (!_owner)
|
||||
ResourceFile::syncNumber(val);
|
||||
else
|
||||
_file.writeUint32LE(val);
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers(int *vals, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers(vals, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers2D(vals, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers3D(vals, count1, count2, count3);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, count3, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2 * count3; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncBytes(byte *vals, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncBytes(vals, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
_file.write(vals, count);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncBytes2D(vals, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
_file.write(vals, count1 * count2);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
196
engines/ultima/shared/engine/resources.h
Normal file
196
engines/ultima/shared/engine/resources.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* 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 ULTIMA_SHARED_ENGINE_RESOURCES_H
|
||||
#define ULTIMA_SHARED_ENGINE_RESOURCES_H
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/archive.h"
|
||||
#include "common/array.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/str.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
|
||||
#define STRING_BUFFER_SIZE 32768
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Resources;
|
||||
|
||||
/**
|
||||
* Base class for classes that exposes a set of strings, arrays, and other data from a resource
|
||||
*/
|
||||
class ResourceFile {
|
||||
private:
|
||||
File _file;
|
||||
char _buffer[STRING_BUFFER_SIZE];
|
||||
char *_bufferP;
|
||||
protected:
|
||||
Common::Path _filename;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ResourceFile(const Common::Path &filename);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ResourceFile() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the data for the resource
|
||||
*/
|
||||
virtual void synchronize() = 0;
|
||||
|
||||
virtual void syncString(const char *&str);
|
||||
virtual void syncStrings(const char **str, size_t count);
|
||||
virtual void syncStrings2D(const char **str, size_t count1, size_t count2);
|
||||
virtual void syncNumber(int &val);
|
||||
virtual void syncNumbers(int *vals, size_t count);
|
||||
virtual void syncNumbers2D(int *vals, size_t count1, size_t count2);
|
||||
virtual void syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3);
|
||||
virtual void syncBytes(byte *vals, size_t count);
|
||||
virtual void syncBytes2D(byte *vals, size_t count1, size_t count2);
|
||||
public:
|
||||
/**
|
||||
* Loads in a resource
|
||||
*/
|
||||
void load();
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived base class for resources that have their contents within the executable rather than a data file.
|
||||
* This will allow the data for a particular Ultima game to be gradually built up without repeatedly
|
||||
* regenerating a data file. Once a game has been properly tested, then it can be moved out.
|
||||
*/
|
||||
class LocalResourceFile : public ResourceFile {
|
||||
private:
|
||||
Common::MemoryWriteStreamDynamic _file;
|
||||
Resources *_owner;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
LocalResourceFile(const Common::Path &filename) : ResourceFile(filename), _owner(nullptr), _file(DisposeAfterUse::YES) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
LocalResourceFile(Resources *owner, const Common::Path &filename) : ResourceFile(filename),
|
||||
_owner(owner), _file(DisposeAfterUse::YES) {}
|
||||
|
||||
/**
|
||||
* Return true if in saving mode
|
||||
*/
|
||||
bool isSaving() const { return _owner != nullptr; }
|
||||
|
||||
void syncString(const char *&str) override;
|
||||
void syncStrings(const char **str, size_t count) override;
|
||||
void syncStrings2D(const char **str, size_t count1, size_t count2) override;
|
||||
void syncNumber(int &val) override;
|
||||
void syncNumbers(int *vals, size_t count) override;
|
||||
void syncNumbers2D(int *vals, size_t count1, size_t count2) override;
|
||||
void syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) override;
|
||||
void syncBytes(byte *vals, size_t count) override;
|
||||
void syncBytes2D(byte *vals, size_t count1, size_t count2) override;
|
||||
public:
|
||||
/**
|
||||
* Write out the resource to the in-memory resource store
|
||||
*/
|
||||
void save();
|
||||
};
|
||||
|
||||
/**
|
||||
* Resources manager
|
||||
*/
|
||||
class Resources : public Common::Archive {
|
||||
struct LocalResource {
|
||||
Common::Path _name;
|
||||
Common::Array<byte> _data;
|
||||
};
|
||||
struct FileResource {
|
||||
Common::Path _name;
|
||||
size_t _offset, _size;
|
||||
|
||||
/**
|
||||
* Load an index entry from the datafile
|
||||
*/
|
||||
void load(File &f);
|
||||
};
|
||||
private:
|
||||
Common::Array<LocalResource> _localResources;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Resources() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the resources for the engine
|
||||
* @returns False if setup failed
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Adds a resource created in memory to the ScummVM archive manager, so that it can be
|
||||
* later opened like a normal file. Just as it will when eventually shifted to the
|
||||
* data file for the engine
|
||||
*/
|
||||
void addResource(const Common::Path &name, const byte *data, size_t size);
|
||||
|
||||
// Archive implementation
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
66
engines/ultima/shared/gfx/bitmap.cpp
Normal file
66
engines/ultima/shared/gfx/bitmap.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/bitmap.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
void Bitmap::load(const Common::Path &filename) {
|
||||
File srcFile(filename);
|
||||
Common::MemoryWriteStreamDynamic decompressedFile(DisposeAfterUse::YES);
|
||||
decompress(&srcFile, &decompressedFile);
|
||||
|
||||
// Set the bitmap size
|
||||
Common::MemoryReadStream f(decompressedFile.getData(), decompressedFile.size());
|
||||
int16 xs = f.readSint16LE();
|
||||
int16 ys = f.readSint16LE();
|
||||
create(xs, ys);
|
||||
assert(f.size() == (xs * ys + 4));
|
||||
|
||||
Graphics::Surface s = getSubArea(Common::Rect(0, 0, xs, ys));
|
||||
|
||||
// Read in the lines
|
||||
for (int y = 0; y < ys; ++y) {
|
||||
byte *dest = (byte *)s.getBasePtr(0, y);
|
||||
f.read(dest, xs);
|
||||
}
|
||||
}
|
||||
|
||||
void Bitmap::flipHorizontally() {
|
||||
Graphics::Surface s = getSubArea(Common::Rect(0, 0, this->w, this->h));
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
byte *lineStart = (byte *)s.getBasePtr(0, y);
|
||||
byte *lineEnd = (byte *)s.getBasePtr(this->w - 1, y);
|
||||
|
||||
for (int x = 0; x < (this->w - 1) / 2; ++x, ++lineStart, --lineEnd)
|
||||
SWAP(*lineStart, *lineEnd);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
51
engines/ultima/shared/gfx/bitmap.h
Normal file
51
engines/ultima/shared/gfx/bitmap.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_BITMAP_H
|
||||
#define ULTIMA_BITMAP_H
|
||||
|
||||
#include "ultima/shared/core/lzw.h"
|
||||
#include "common/path.h"
|
||||
#include "common/stream.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
class Bitmap : public Graphics::ManagedSurface, public LZW {
|
||||
public:
|
||||
/**
|
||||
* Loads an Ultima 6 bitmap
|
||||
*/
|
||||
void load(const Common::Path &filename);
|
||||
|
||||
/**
|
||||
* Flips a bitmap horizontally
|
||||
*/
|
||||
void flipHorizontally();
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
55
engines/ultima/shared/gfx/character_input.cpp
Normal file
55
engines/ultima/shared/gfx/character_input.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/character_input.h"
|
||||
#include "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
BEGIN_MESSAGE_MAP(CharacterInput, Popup)
|
||||
ON_MESSAGE(KeypressMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
void CharacterInput::show(const Point &pt, byte color, TreeItem *respondTo) {
|
||||
Popup::show(respondTo);
|
||||
_color = color;
|
||||
_bounds = Rect(pt.x, pt.y, pt.x + 8, pt.y + 8);
|
||||
|
||||
_game->_textCursor->setPosition(Point(_bounds.left, _bounds.top));
|
||||
_game->_textCursor->setVisible(true);
|
||||
}
|
||||
|
||||
bool CharacterInput::KeypressMsg(CKeypressMsg *msg) {
|
||||
hide();
|
||||
|
||||
CCharacterInputMsg inputMsg(msg->_keyState);
|
||||
inputMsg.execute(_respondTo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
58
engines/ultima/shared/gfx/character_input.h
Normal file
58
engines/ultima/shared/gfx/character_input.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_GFX_CHARACTER_INPUT_H
|
||||
#define ULTIMA_GFX_CHARACTER_INPUT_H
|
||||
|
||||
#include "ultima/shared/gfx/popup.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
* Text input control
|
||||
*/
|
||||
class CharacterInput : public Popup {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool KeypressMsg(CKeypressMsg *msg);
|
||||
private:
|
||||
byte _color;
|
||||
public:
|
||||
CLASSDEF;
|
||||
CharacterInput(GameBase *game) : Popup(game), _color(0) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the character input
|
||||
* @param pt Position of the input
|
||||
* @param color Text color
|
||||
* @param respondTo Where to send response to
|
||||
* @remarks Generates a TextInputMsg message with the character when pressed
|
||||
*/
|
||||
void show(const Point &pt, byte color, TreeItem *respondTo = nullptr);
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
195
engines/ultima/shared/gfx/dungeon_surface.cpp
Normal file
195
engines/ultima/shared/gfx/dungeon_surface.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/dungeon_surface.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
const byte ARRAY_X[] = { 0, 72, 108, 126, 135, 144 };
|
||||
const byte ARRAY_Y[] = { 0, 36, 54, 63, 68, 72 };
|
||||
|
||||
DungeonSurface::DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn) :
|
||||
Gfx::VisualSurface(src, bounds), _widgetFn(widgetFn) {
|
||||
_edgeColor = game->_edgeColor;
|
||||
_highlightColor = game->_highlightColor;
|
||||
_widgetColor = 0;
|
||||
}
|
||||
|
||||
void DungeonSurface::drawWall(uint distance) {
|
||||
int offsetX = !distance ? 8 : 0, offsetY = !distance ? 8 : 0;
|
||||
|
||||
if (distance <= 5) {
|
||||
hLine(ARRAY_X[distance] + 16 + offsetX, ARRAY_Y[distance] + 8 + offsetY,
|
||||
303 - ARRAY_X[distance] - offsetX, _edgeColor);
|
||||
hLine(ARRAY_X[distance] + 16 + offsetX, 151 - ARRAY_Y[distance] - offsetY,
|
||||
303 - ARRAY_X[distance] - offsetX, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawDoorway(uint distance) {
|
||||
int offsetY = !distance ? 8 : 0;
|
||||
byte color = !distance ? 0 : _edgeColor;
|
||||
|
||||
if (distance < 5) {
|
||||
drawWall(distance);
|
||||
drawLine(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY,
|
||||
ARRAY_X[distance + 1] + 16, ARRAY_Y[distance + 1] + 8, _edgeColor);
|
||||
drawLineTo(303 - ARRAY_X[distance + 1], ARRAY_Y[distance + 1] + 8, _edgeColor);
|
||||
drawLineTo(303 - ARRAY_X[distance + 1], 151 - ARRAY_Y[distance] - offsetY, _edgeColor);
|
||||
drawLineTo(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY, color);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLeftEdge(uint distance) {
|
||||
if (distance <= 5) {
|
||||
vLine(ARRAY_X[distance] + 16, ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawRightEdge(uint distance) {
|
||||
if (distance <= 5) {
|
||||
vLine(303 - ARRAY_X[distance], ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawWidget(uint widgetId, uint distance, byte color) {
|
||||
_widgetFn(*this, widgetId, distance, color);
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLadderDownFaceOn(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawWidget(27, distance, _edgeColor);
|
||||
drawWidget(28, distance, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLadderDownSideOn(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawWidget(27, distance, _edgeColor);
|
||||
drawWidget(29, distance, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLadderUpFaceOn(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawWidget(26, distance, _edgeColor);
|
||||
drawWidget(28, distance, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLadderUpSideOn(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawWidget(26, distance, _edgeColor);
|
||||
drawWidget(29, distance, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLeftDoor(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawLeftWall(distance);
|
||||
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
Point diff = p1 - p2;
|
||||
diff.x /= 9;
|
||||
diff.y /= 5;
|
||||
|
||||
drawLine(p2.x + diff.x * 2 + 16, 151 - diff.y - p2.y - 1, p2.x + diff.x * 2 + 16,
|
||||
p1.y + 8 - diff.y, _edgeColor);
|
||||
drawLineTo(p2.x + diff.x * 6 + 16, p1.y + diff.y + 8, _edgeColor);
|
||||
drawLineTo(p2.x + diff.x * 6 + 16, 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLeftWall(uint distance) {
|
||||
if (distance <= 5) {
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
drawLine(p2.x + 16, p2.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
|
||||
drawLine(p2.x + 16, 151 - p2.y, p1.x + 16, 151 - p1.y, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawLeftBlank(uint distance) {
|
||||
if (distance <= 5) {
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
drawLine(p2.x + 16, p1.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
|
||||
drawLine(p2.x + 16, 151 - p1.y, p1.x + 16, 151 - p1.y, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawRightDoor(uint distance) {
|
||||
if (distance <= 5) {
|
||||
drawRightWall(distance);
|
||||
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
Point diff = p1 - p2;
|
||||
diff.x /= 9;
|
||||
diff.y /= 5;
|
||||
|
||||
drawLine(303 - (p2.x + diff.x * 2), 151 - diff.y - p2.y - 1, 303 - (p2.x + diff.x * 2),
|
||||
p1.y + 8 - diff.y, _edgeColor);
|
||||
drawLineTo(303 - (diff.x * 6 + p2.x), p1.y + 8 + diff.y, _edgeColor);
|
||||
drawLineTo(303 - (diff.x * 6 + p2.x), 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawRightWall(uint distance) {
|
||||
if (distance <= 5) {
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
|
||||
drawLine(303 - p2.x, p2.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
|
||||
drawLine(303 - p2.x, 151 - p2.y, 303 - p1.x, 151 - p1.y, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawRightBlank(uint distance) {
|
||||
if (distance <= 5) {
|
||||
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
|
||||
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
|
||||
drawLine(303 - p2.x, p1.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
|
||||
drawLine(303 - p2.x, 151 - p1.y, 303 - p1.x, 151 - p1.y, _edgeColor);
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonSurface::drawBeams(uint distance) {
|
||||
if (distance <= 5) {
|
||||
// Figure out the Y difference between each beam
|
||||
const int Y_START = ARRAY_Y[distance] + 8;
|
||||
const int Y_END = 151 - ARRAY_Y[distance];
|
||||
const int HEIGHT = (Y_END - Y_START) / 4;
|
||||
|
||||
for (int beamNum = 0; beamNum < 4; ++beamNum) {
|
||||
const int YP = Y_START + HEIGHT * beamNum + (distance / 2);
|
||||
|
||||
drawLine(ARRAY_X[distance] + 16, YP, 303 - ARRAY_X[distance], YP, _highlightColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
174
engines/ultima/shared/gfx/dungeon_surface.h
Normal file
174
engines/ultima/shared/gfx/dungeon_surface.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/* 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 ULTIMA_SHARED_GFX_DUNGEON_H
|
||||
#define ULTIMA_SHARED_GFX_DUNGEON_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
typedef void(*DrawWidgetFn)(Graphics::ManagedSurface &s, uint widgetId, uint distance, byte color);
|
||||
|
||||
class Game;
|
||||
|
||||
/**
|
||||
* Acts as a handy container for the drawing methods for rendering the dungeon view
|
||||
*/
|
||||
class DungeonSurface : public Gfx::VisualSurface {
|
||||
private:
|
||||
Point _penPos;
|
||||
byte _edgeColor;
|
||||
byte _highlightColor;
|
||||
byte _widgetColor;
|
||||
DrawWidgetFn _widgetFn;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn);
|
||||
|
||||
/**
|
||||
* Draw a line
|
||||
*/
|
||||
void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
|
||||
Gfx::VisualSurface::drawLine(x0 - 8, y0 - 8, x1 - 8, y1 - 8, color);
|
||||
_penPos = Point(x1, y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a line from a prior line ending point to a new destination pos
|
||||
*/
|
||||
void drawLineTo(int x, int y, uint32 color) {
|
||||
Gfx::VisualSurface::drawLine(_penPos.x - 8, _penPos.y - 8, x - 8, y - 8, color);
|
||||
_penPos = Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a horizontal line.
|
||||
*/
|
||||
void hLine(int x, int y, int x2, uint32 color) {
|
||||
Gfx::VisualSurface::hLine(x - 8, y - 8, x2 - 8, color);
|
||||
_penPos = Point(x2, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a vertical line.
|
||||
*/
|
||||
void vLine(int x, int y, int y2, uint32 color) {
|
||||
Gfx::VisualSurface::vLine(x - 8, y - 8, y2 - 8, color);
|
||||
_penPos = Point(x, y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a frame around a specified rect.
|
||||
*/
|
||||
void frameRect(const Common::Rect &r, uint32 color) {
|
||||
Gfx::VisualSurface::frameRect(Rect(r.left - 8, r.top - 8, r.right - 8, r.bottom - 8), color);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws a wall
|
||||
*/
|
||||
void drawWall(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a doorway directly in front of the player
|
||||
*/
|
||||
void drawDoorway(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a vertical line forming the edge of cells to the left of the player
|
||||
*/
|
||||
void drawLeftEdge(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a vertical line forming the edge of cells to the right of the player
|
||||
*/
|
||||
void drawRightEdge(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a monster or item at a given distance from the player
|
||||
*/
|
||||
void drawWidget(uint widgetId, uint distance, byte color);
|
||||
|
||||
/**
|
||||
* Draw a ladder down face on
|
||||
*/
|
||||
void drawLadderDownFaceOn(uint distance);
|
||||
|
||||
/**
|
||||
* Draw a ladder down side on
|
||||
*/
|
||||
void drawLadderDownSideOn(uint distance);
|
||||
|
||||
/**
|
||||
* Draw a ladder down face on
|
||||
*/
|
||||
void drawLadderUpFaceOn(uint distance);
|
||||
|
||||
/**
|
||||
* Draw a ladder down side on
|
||||
*/
|
||||
void drawLadderUpSideOn(uint distance);
|
||||
|
||||
/**
|
||||
* Draw beams
|
||||
*/
|
||||
void drawBeams(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a door on the left hand side
|
||||
*/
|
||||
void drawLeftDoor(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a wall on the left-hand side
|
||||
*/
|
||||
void drawLeftWall(uint distance);
|
||||
|
||||
/**
|
||||
* Draws the partial wall visible at the back of a corridor leading to the left
|
||||
*/
|
||||
void drawLeftBlank(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a door on the right hand side
|
||||
*/
|
||||
void drawRightDoor(uint distance);
|
||||
|
||||
/**
|
||||
* Draws a wall on the right-hand side
|
||||
*/
|
||||
void drawRightWall(uint distance);
|
||||
|
||||
/**
|
||||
* Draws the partial wall visible at the back of a corridor leading to the right
|
||||
*/
|
||||
void drawRightBlank(uint distance);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
83
engines/ultima/shared/gfx/font.cpp
Normal file
83
engines/ultima/shared/gfx/font.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/font.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
Font::Font(const byte *data, size_t startingChar, size_t charCount) :
|
||||
_data(data), _startingChar(startingChar), _endingChar(startingChar + charCount - 1) {}
|
||||
|
||||
int Font::writeString(Graphics::ManagedSurface &surface, const Common::String &msg, Point &pt,
|
||||
byte color, byte bgColor) {
|
||||
int total = 0;
|
||||
int xs = pt.x;
|
||||
|
||||
for (const char *msgP = msg.c_str(); *msgP; ++msgP, total += 8) {
|
||||
if (*msgP == '\n') {
|
||||
// Move to next line
|
||||
pt.x = xs;
|
||||
pt.y += lineHeight();
|
||||
} else {
|
||||
// Write out character
|
||||
writeChar(surface, (unsigned char)*msgP, pt, color, bgColor);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void Font::writeChar(Graphics::ManagedSurface &surface, unsigned char c, Point &pt,
|
||||
byte color, byte bgColor) {
|
||||
assert(c >= _startingChar && c <= _endingChar);
|
||||
const byte *charP = _data + (c - _startingChar) * 8;
|
||||
Graphics::Surface s = surface.getSubArea(Common::Rect(pt.x, pt.y, pt.x + 8, pt.y + 8));
|
||||
|
||||
for (int y = 0; y < 8; ++y) {
|
||||
byte *lineP = (byte *)s.getBasePtr(0, y);
|
||||
byte lineData = charP[y];
|
||||
|
||||
for (int x = 0; x < 8; ++x, lineData <<= 1, ++lineP) {
|
||||
*lineP = (lineData & 0x80) ? color : bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
pt.x += charWidth(c);
|
||||
}
|
||||
|
||||
uint Font::charWidth(char c) const {
|
||||
return 8;
|
||||
}
|
||||
|
||||
uint Font::lineHeight() const {
|
||||
return 8;
|
||||
}
|
||||
|
||||
uint Font::stringWidth(const Common::String &msg) const {
|
||||
return msg.size() * 8;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
73
engines/ultima/shared/gfx/font.h
Normal file
73
engines/ultima/shared/gfx/font.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_FONT_H
|
||||
#define ULTIMA_SHARED_GFX_FONT_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
class Font {
|
||||
private:
|
||||
const byte *_data;
|
||||
size_t _startingChar, _endingChar;
|
||||
public:
|
||||
Font(const byte *data, size_t startingChar = 0, size_t charCount = 256);
|
||||
|
||||
/**
|
||||
* Write out a string
|
||||
*/
|
||||
int writeString(Graphics::ManagedSurface &surface, const Common::String &msg,
|
||||
Point &pt, byte color, byte bgColor = 0);
|
||||
|
||||
/**
|
||||
* Draw a character
|
||||
*/
|
||||
void writeChar(Graphics::ManagedSurface &surface, unsigned char c, Point &pt,
|
||||
byte color, byte bgColor = 0);
|
||||
|
||||
/**
|
||||
* Return the width of a character
|
||||
*/
|
||||
uint charWidth(char c) const;
|
||||
|
||||
/**
|
||||
* Return the width of a string
|
||||
*/
|
||||
uint stringWidth(const Common::String &msg) const;
|
||||
|
||||
/**
|
||||
* Returns the height of the font
|
||||
*/
|
||||
uint lineHeight() const;
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
156
engines/ultima/shared/gfx/info.cpp
Normal file
156
engines/ultima/shared/gfx/info.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/info.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/core/str.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define PROMPT_CHAR '\x1'
|
||||
#define SUGGESTED_CR '\r'
|
||||
|
||||
BEGIN_MESSAGE_MAP(Info, Shared::Gfx::VisualItem)
|
||||
ON_MESSAGE(InfoMsg)
|
||||
ON_MESSAGE(InfoGetCommandKeypress)
|
||||
ON_MESSAGE(InfoGetKeypress)
|
||||
ON_MESSAGE(InfoGetInput)
|
||||
ON_MESSAGE(KeypressMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
Info::Info(TreeItem *parent, const Rect &bounds) : Gfx::VisualItem("Info", bounds, parent),
|
||||
_commandRespondTo(nullptr) {
|
||||
_characterInput = new Gfx::CharacterInput(getGame());
|
||||
_textInput = new Gfx::TextInput(getGame());
|
||||
}
|
||||
|
||||
Info::~Info() {
|
||||
delete _characterInput;
|
||||
delete _textInput;
|
||||
}
|
||||
|
||||
bool Info::InfoMsg(CInfoMsg *msg) {
|
||||
// Iterate through text, dealing with lines one at a time
|
||||
StringArray lines = String(msg->_text).split("\r\n");
|
||||
|
||||
if (!_lines.empty() && msg->_replaceLine)
|
||||
_lines.back() = _lines.back().firstChar();
|
||||
|
||||
for (uint idx = 0; idx < lines.size(); ++idx) {
|
||||
if (_lines.empty() || idx > 0)
|
||||
_lines.push_back(" ");
|
||||
|
||||
_lines.back() += lines[idx];
|
||||
}
|
||||
|
||||
// Add newline if necessary
|
||||
if (msg->_newLine)
|
||||
_lines.push_back(" ");
|
||||
|
||||
setDirty();
|
||||
|
||||
// Adding any text hides any visible cursor
|
||||
_commandRespondTo = nullptr;
|
||||
Gfx::TextCursor *textCursor = getGame()->_textCursor;
|
||||
textCursor->setVisible(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Info::InfoGetCommandKeypress(CInfoGetCommandKeypress *msg) {
|
||||
if (_lines.empty() || _lines.back() != " ")
|
||||
_lines.push_back("");
|
||||
_lines.back() = PROMPT_CHAR;
|
||||
|
||||
Gfx::TextCursor *textCursor = getGame()->_textCursor;
|
||||
textCursor->setVisible(true);
|
||||
textCursor->setPosition(Point(8, _bounds.bottom - 8));
|
||||
|
||||
_commandRespondTo = msg->_responder;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Info::InfoGetKeypress(CInfoGetKeypress *msg) {
|
||||
Game *game = getGame();
|
||||
Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8);
|
||||
_characterInput->show(pt, game->_textColor, msg->_responder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Info::InfoGetInput(CInfoGetInput *msg) {
|
||||
Game *game = getGame();
|
||||
Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8);
|
||||
_textInput->show(pt, msg->_isNumeric, msg->_maxCharacters, game->_textColor, msg->_responder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Info::KeypressMsg(CKeypressMsg *msg) {
|
||||
// If waiting for a command, dispatch the key to the respond, and hide the cursor
|
||||
if (_commandRespondTo) {
|
||||
TreeItem *target = _commandRespondTo;
|
||||
_commandRespondTo = nullptr;
|
||||
|
||||
getGame()->_textCursor->setVisible(false);
|
||||
CCharacterInputMsg cMsg(msg->_keyState);
|
||||
cMsg.execute(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Info::draw() {
|
||||
// Clear the background
|
||||
Gfx::VisualSurface s = getSurface();
|
||||
s.clear();
|
||||
|
||||
// Get the number og lines to display
|
||||
uint lineHeight = s.fontHeight();
|
||||
uint numLines = (s.h + lineHeight - 1) / lineHeight;
|
||||
|
||||
// Discard any stored lines beyond the top of the display
|
||||
while (_lines.size() > numLines)
|
||||
_lines.remove_at(0);
|
||||
|
||||
// Display the lines
|
||||
int x = 0, y = s.h - _lines.size() * lineHeight;
|
||||
for (uint idx = 0; idx < _lines.size(); ++idx, x = 0, y += lineHeight) {
|
||||
// Handle drawing the prompt character at the start of lines if necessary
|
||||
Common::String line = _lines[idx];
|
||||
if (!line.empty() && line[0] == PROMPT_CHAR) {
|
||||
drawPrompt(s, Point(0, y));
|
||||
x = 8;
|
||||
line.deleteChar(0);
|
||||
}
|
||||
|
||||
// Write the remainder of the line
|
||||
s.writeString(line, Point(x, y));
|
||||
}
|
||||
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
80
engines/ultima/shared/gfx/info.h
Normal file
80
engines/ultima/shared/gfx/info.h
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_INFO_H
|
||||
#define ULTIMA_SHARED_GFX_INFO_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/gfx/text_input.h"
|
||||
#include "ultima/shared/gfx/character_input.h"
|
||||
#include "common/str-array.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
using Shared::CInfoMsg;
|
||||
using Shared::CInfoGetCommandKeypress;
|
||||
using Shared::CInfoGetInput;
|
||||
using Shared::CKeypressMsg;
|
||||
|
||||
/**
|
||||
* Textual info area, showing what commands area done, and any responses to them
|
||||
*/
|
||||
class Info : public Gfx::VisualItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool InfoMsg(CInfoMsg *msg);
|
||||
bool InfoGetCommandKeypress(CInfoGetCommandKeypress *msg);
|
||||
bool InfoGetKeypress(CInfoGetKeypress *msg);
|
||||
bool InfoGetInput(CInfoGetInput *msg);
|
||||
bool KeypressMsg(CKeypressMsg *msg);
|
||||
private:
|
||||
Common::StringArray _lines;
|
||||
Gfx::TextInput *_textInput;
|
||||
Gfx::CharacterInput *_characterInput;
|
||||
TreeItem *_commandRespondTo;
|
||||
protected:
|
||||
/**
|
||||
* Draws a prompt character
|
||||
*/
|
||||
virtual void drawPrompt(Gfx::VisualSurface &surf, const Point &pt) = 0;
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Info(TreeItem *parent, const Rect &bounds);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Info() override;
|
||||
|
||||
/**
|
||||
* Draw the contents
|
||||
*/
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
70
engines/ultima/shared/gfx/popup.cpp
Normal file
70
engines/ultima/shared/gfx/popup.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 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 "ultima/shared/gfx/popup.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
BEGIN_MESSAGE_MAP(Popup, VisualItem)
|
||||
ON_MESSAGE(ShowMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
Popup::Popup(GameBase *game) : VisualItem(nullptr), _game(game), _respondTo(nullptr), _parentView(nullptr) {
|
||||
game->addChild(this);
|
||||
}
|
||||
|
||||
Popup::~Popup() {
|
||||
detach();
|
||||
}
|
||||
|
||||
void Popup::show(TreeItem *respondTo) {
|
||||
// Save a copy of the view the popup is being shown on, and activate it
|
||||
_parentView = _game->getView();
|
||||
_respondTo = respondTo;
|
||||
if (!_respondTo)
|
||||
_respondTo = _parentView;
|
||||
|
||||
_game->setPopup(this);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
|
||||
void Popup::hide() {
|
||||
CPopupHiddenMsg hiddenMsg(this);
|
||||
hiddenMsg.execute(_respondTo, nullptr, 0);
|
||||
|
||||
// Reset back to the parent view
|
||||
_game->setView(_parentView);
|
||||
_parentView->setDirty();
|
||||
}
|
||||
|
||||
bool Popup::ShowMsg(CShowMsg *msg) {
|
||||
CPopupShownMsg shownMsg(this);
|
||||
shownMsg.execute(_respondTo, nullptr, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
75
engines/ultima/shared/gfx/popup.h
Normal file
75
engines/ultima/shared/gfx/popup.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_POPUP_H
|
||||
#define ULTIMA_SHARED_GFX_POPUP_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class GameBase;
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
* Base class for graphic elements that "pop up" on top of existing views. This includes things like
|
||||
* dialogs, text input, etc.
|
||||
*/
|
||||
class Popup : public VisualItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool ShowMsg(CShowMsg *msg);
|
||||
protected:
|
||||
GameBase *_game;
|
||||
VisualItem *_parentView;
|
||||
TreeItem *_respondTo;
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Popup(GameBase *game);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Popup() override;
|
||||
|
||||
/**
|
||||
* Show the popup
|
||||
* @param respondTo Element to send any response to when the popup closes.
|
||||
* If not provided, any response goes to the active view
|
||||
*/
|
||||
void show(TreeItem *respondTo = nullptr);
|
||||
|
||||
/**
|
||||
* Hide the popup
|
||||
*/
|
||||
virtual void hide();
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
61
engines/ultima/shared/gfx/screen.cpp
Normal file
61
engines/ultima/shared/gfx/screen.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/util.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
Screen::Screen(): Graphics::Screen(320, 200), _cursor(nullptr), _drawCursor(false) {
|
||||
initGraphics(320, 200);
|
||||
}
|
||||
|
||||
void Screen::update() {
|
||||
_drawCursor = false;
|
||||
|
||||
if (_cursor) {
|
||||
// Check whether the area the cursor occupies will be being updated
|
||||
Common::Rect cursorBounds = _cursor->getBounds();
|
||||
for (const auto &r : _dirtyRects) {
|
||||
if (r.intersects(cursorBounds)) {
|
||||
addDirtyRect(cursorBounds);
|
||||
_drawCursor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Screen::update();
|
||||
}
|
||||
|
||||
void Screen::updateScreen() {
|
||||
if (_drawCursor)
|
||||
_cursor->draw();
|
||||
|
||||
Graphics::Screen::updateScreen();
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
88
engines/ultima/shared/gfx/screen.h
Normal file
88
engines/ultima/shared/gfx/screen.h
Normal 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 ULTIMA_SHARED_GFX_SCREEN_H
|
||||
#define ULTIMA_SHARED_GFX_SCREEN_H
|
||||
|
||||
#include "common/list.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "ultima/shared/gfx/font.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
|
||||
/**
|
||||
* Base class for an on-screen cursor. Currently used for text cursor display
|
||||
*/
|
||||
class Cursor {
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Cursor() {}
|
||||
|
||||
/**
|
||||
* Get the bounds of the cursor
|
||||
*/
|
||||
virtual Common::Rect getBounds() const = 0;
|
||||
|
||||
/**
|
||||
* Draw the cursor
|
||||
*/
|
||||
virtual void draw() = 0;
|
||||
};
|
||||
|
||||
class Screen: public Graphics::Screen {
|
||||
private:
|
||||
Cursor *_cursor;
|
||||
bool _drawCursor;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Screen();
|
||||
|
||||
/**
|
||||
* Updates the screen by copying any affected areas to the system
|
||||
*/
|
||||
void update() override;
|
||||
|
||||
/**
|
||||
* Updates the screen at the end of an update call
|
||||
*/
|
||||
void updateScreen() override;
|
||||
|
||||
/**
|
||||
* Sets the currently active cursor
|
||||
*/
|
||||
void setCursor(Cursor *cursor) { _cursor = cursor; }
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
106
engines/ultima/shared/gfx/sprites.cpp
Normal file
106
engines/ultima/shared/gfx/sprites.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/sprites.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
Sprite::Sprite() {
|
||||
}
|
||||
|
||||
Sprite::Sprite(const Sprite &src) {
|
||||
_surface.copyFrom(src._surface);
|
||||
_transSurface.copyFrom(src._transSurface);
|
||||
}
|
||||
|
||||
Sprite::Sprite(const byte *src, uint bpp, uint16 w, uint16 h) {
|
||||
_surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
assert((w % bpp) == 0);
|
||||
byte v = 0;
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
byte *destP = (byte *)_surface.getBasePtr(0, y);
|
||||
|
||||
for (int x = 0; x < w; ++x, v <<= bpp) {
|
||||
if ((x % (8 / bpp)) == 0)
|
||||
v = *src++;
|
||||
|
||||
*destP++ = (((uint)v << bpp) & 0xff00) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sprite &Sprite::operator=(const Sprite &src) {
|
||||
_surface.copyFrom(src._surface);
|
||||
_transSurface.copyFrom(src._transSurface);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Sprite::draw(Graphics::ManagedSurface &dest, const Common::Point &pt) {
|
||||
// Get area to be drawn on
|
||||
Graphics::Surface s = dest.getSubArea(Common::Rect(pt.x, pt.y, pt.x + _surface.w, pt.y + _surface.h));
|
||||
|
||||
// Draw the sprite
|
||||
for (uint16 y = 0; y < _surface.h; ++y) {
|
||||
const byte *srcP = (const byte *)_surface.getBasePtr(0, y);
|
||||
const byte *transP = (const byte *)_transSurface.getBasePtr(0, y);
|
||||
byte *destP = (byte *)s.getBasePtr(0, y);
|
||||
|
||||
for (uint16 x = 0; x < _surface.w; ++x, ++srcP, ++transP, ++destP) {
|
||||
if (_transSurface.empty() || *transP)
|
||||
*destP = *srcP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void Sprites::load(const Common::Path &name, uint bpp, uint16 w, uint16 h) {
|
||||
_spriteSize = Point(w, h);
|
||||
|
||||
// Open the tiles for access
|
||||
File f(name);
|
||||
byte *buffer = new byte[w * h];
|
||||
|
||||
// Figure out how many tiles the file has
|
||||
size_t bytesPerTile = (w / (8 / bpp)) * h;
|
||||
size_t count = f.size() / bytesPerTile;
|
||||
|
||||
// Ensure there's enough capacity for the tileset
|
||||
if (count > size())
|
||||
_data.resize(count);
|
||||
|
||||
// Iterate through loading the tile data and creating sprites for them
|
||||
for (size_t idx = 0; idx < count; ++idx) {
|
||||
f.read(buffer, bytesPerTile);
|
||||
|
||||
_data[idx] = Sprite(buffer, bpp, w, h);
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
138
engines/ultima/shared/gfx/sprites.h
Normal file
138
engines/ultima/shared/gfx/sprites.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/* 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 ULTIMA_SPRITES_H
|
||||
#define ULTIMA_SPRITES_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/path.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
class Sprite {
|
||||
private:
|
||||
Graphics::ManagedSurface _surface;
|
||||
Graphics::ManagedSurface _transSurface;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Sprite();
|
||||
|
||||
/**
|
||||
* Constructor, copying from another sprite
|
||||
*/
|
||||
Sprite(const Sprite &src);
|
||||
|
||||
/**
|
||||
* Constructor, loading a sprite from passed data
|
||||
* @param src Source data
|
||||
* @param bpp The bits per pixel for tiles in the file
|
||||
* @param w Width of tiles
|
||||
* @param h Height of files
|
||||
*/
|
||||
Sprite(const byte *src, uint bpp, uint16 w = 16, uint16 h = 16);
|
||||
|
||||
/**
|
||||
* Copy assignment operator
|
||||
*/
|
||||
Sprite &operator=(const Sprite &src);
|
||||
|
||||
/**
|
||||
* Draw a tile onto a passed surface
|
||||
*/
|
||||
void draw(Graphics::ManagedSurface &dest, const Common::Point &pt);
|
||||
|
||||
/**
|
||||
* Return the width of the sprite
|
||||
*/
|
||||
uint16 w() const { return _surface.w; }
|
||||
|
||||
/**
|
||||
* Return the height of the sprite
|
||||
*/
|
||||
uint16 h() const { return _surface.h; }
|
||||
|
||||
/**
|
||||
* Get a reference to the sprite surface
|
||||
*/
|
||||
byte *getPixels() { return (byte *)_surface.getPixels(); }
|
||||
|
||||
/**
|
||||
* Get a reference to a specified position within the sprite
|
||||
*/
|
||||
byte *getBasePtr(int16 x, int16 y) { return (byte *)_surface.getBasePtr(x, y); }
|
||||
|
||||
/**
|
||||
* Get a reference to a specified position within the sprite
|
||||
*/
|
||||
const byte *getBasePtr(int16 x, int16 y) const { return (const byte *)_surface.getBasePtr(x, y); }
|
||||
};
|
||||
|
||||
class Sprites {
|
||||
protected:
|
||||
Common::Array<Sprite> _data;
|
||||
Point _spriteSize; // Size of individual sprites
|
||||
protected:
|
||||
/**
|
||||
* Load a raw data file containing sprite pixels
|
||||
* @param name Filename
|
||||
* @param bpp The bits per pixel for tiles in the file
|
||||
* @param w Width of tiles
|
||||
* @param h Height of files
|
||||
*/
|
||||
void load(const Common::Path &name, uint bpp, uint16 w = 16, uint16 h = 16);
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Sprites() {}
|
||||
|
||||
/**
|
||||
* Return the default dimensions for tiles
|
||||
*/
|
||||
Point getSpriteSize() const { return _spriteSize; }
|
||||
|
||||
/**
|
||||
* Return the size of the sprites list
|
||||
*/
|
||||
size_t size() const { return _data.size(); }
|
||||
|
||||
/**
|
||||
* Returns true if the sprites list is empty
|
||||
*/
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
/**
|
||||
* Return a specific sprite
|
||||
*/
|
||||
virtual Sprite &operator[](uint idx) { return _data[idx]; }
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
35
engines/ultima/shared/gfx/text_cursor.cpp
Normal file
35
engines/ultima/shared/gfx/text_cursor.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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 "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
void TextCursor::markAsDirty() {
|
||||
g_vm->_screen->getSubArea(_bounds);
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
95
engines/ultima/shared/gfx/text_cursor.h
Normal file
95
engines/ultima/shared/gfx/text_cursor.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 ULTIMA_SHARED_GFX_TEXT_CURSOR_H
|
||||
#define ULTIMA_SHARED_GFX_TEXT_CURSOR_H
|
||||
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
* Base class for text cursors, and is used by those games that don't have a visible cursor
|
||||
*/
|
||||
class TextCursor : public Cursor {
|
||||
protected:
|
||||
bool _visible;
|
||||
Common::Rect _bounds;
|
||||
protected:
|
||||
/**
|
||||
* Marks the area of the screen the cursor covers as dirty
|
||||
*/
|
||||
void markAsDirty();
|
||||
public:
|
||||
TextCursor() : _visible(false) {
|
||||
}
|
||||
~TextCursor() override {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the cursor is visible
|
||||
*/
|
||||
bool isVisible() const {
|
||||
return _visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visibility of the cursor
|
||||
*/
|
||||
virtual void setVisible(bool isVis) {
|
||||
_visible = isVis;
|
||||
markAsDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bounds of the cursor
|
||||
*/
|
||||
Common::Rect getBounds() const override { return _bounds; }
|
||||
|
||||
/**
|
||||
* Returns the position of the cursor
|
||||
*/
|
||||
Point getPosition() const { return Point(_bounds.left, _bounds.top); }
|
||||
|
||||
/**
|
||||
* Sets the position of the cursor
|
||||
*/
|
||||
void setPosition(const Point &pt) {
|
||||
bool vis = _visible;
|
||||
setVisible(false);
|
||||
_bounds.moveTo(pt);
|
||||
setVisible(vis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cursor
|
||||
*/
|
||||
virtual void update() = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
96
engines/ultima/shared/gfx/text_input.cpp
Normal file
96
engines/ultima/shared/gfx/text_input.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* 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 "ultima/shared/gfx/text_input.h"
|
||||
#include "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
BEGIN_MESSAGE_MAP(TextInput, Popup)
|
||||
ON_MESSAGE(KeypressMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
void TextInput::show(const Point &pt, bool isNumeric, size_t maxCharacters, byte color, TreeItem *respondTo) {
|
||||
Popup::show(respondTo);
|
||||
_isNumeric = isNumeric;
|
||||
_maxCharacters = maxCharacters;
|
||||
_color = color;
|
||||
_bounds = Rect(pt.x, pt.y, pt.x + 8 * (maxCharacters + 1), pt.y + 8);
|
||||
_text = "";
|
||||
|
||||
_game->_textCursor->setPosition(Point(_bounds.left, _bounds.top));
|
||||
_game->_textCursor->setVisible(true);
|
||||
}
|
||||
|
||||
void TextInput::draw() {
|
||||
Popup::draw();
|
||||
|
||||
VisualSurface s = getSurface();
|
||||
|
||||
// Ensure the cursor is at the right position
|
||||
_game->_textCursor->setPosition(Point(_bounds.left + _text.size() * 8, _bounds.top));
|
||||
|
||||
// Display the text
|
||||
Common::String text = _text;
|
||||
while (text.size() < _maxCharacters)
|
||||
text += ' ';
|
||||
s.writeString(text, TextPoint(0, 0), _color);
|
||||
}
|
||||
|
||||
bool TextInput::KeypressMsg(CKeypressMsg *msg) {
|
||||
uint16 c = msg->_keyState.ascii;
|
||||
//TreeItem *respondTo = _respondTo;
|
||||
|
||||
if (c >= ' ' && c <= 0x7f) {
|
||||
// Printable character
|
||||
if (_text.size() < _maxCharacters && (!_isNumeric || (c >= '0' && c <= '9'))) {
|
||||
_text += msg->_keyState.ascii;
|
||||
setDirty();
|
||||
}
|
||||
} else if (msg->_keyState.keycode == Common::KEYCODE_BACKSPACE || msg->_keyState.keycode == Common::KEYCODE_LEFT) {
|
||||
if (!_text.empty()) {
|
||||
_text.deleteLastChar();
|
||||
setDirty();
|
||||
}
|
||||
} else if (msg->_keyState.keycode == Common::KEYCODE_RETURN || msg->_keyState.keycode == Common::KEYCODE_KP_ENTER) {
|
||||
_game->_textCursor->setVisible(false);
|
||||
hide();
|
||||
|
||||
CTextInputMsg inputMsg(_text, false);
|
||||
inputMsg.execute(_respondTo);
|
||||
} else if (msg->_keyState.keycode == Common::KEYCODE_ESCAPE) {
|
||||
_game->_textCursor->setVisible(false);
|
||||
hide();
|
||||
|
||||
CTextInputMsg inputMsg("", true);
|
||||
inputMsg.execute(_respondTo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
68
engines/ultima/shared/gfx/text_input.h
Normal file
68
engines/ultima/shared/gfx/text_input.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_GFX_TEXT_INPUT_H
|
||||
#define ULTIMA_GFX_TEXT_INPUT_H
|
||||
|
||||
#include "ultima/shared/gfx/popup.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
* Text input control
|
||||
*/
|
||||
class TextInput : public Popup {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool KeypressMsg(CKeypressMsg *msg);
|
||||
private:
|
||||
bool _isNumeric;
|
||||
size_t _maxCharacters;
|
||||
Common::String _text;
|
||||
byte _color;
|
||||
public:
|
||||
CLASSDEF;
|
||||
TextInput(GameBase *game) : Popup(game), _isNumeric(false), _maxCharacters(0), _color(0) {}
|
||||
|
||||
/**
|
||||
* Draws the visual item on the screen
|
||||
*/
|
||||
void draw() override;
|
||||
|
||||
/**
|
||||
* Show the text input
|
||||
* @param pt Position of the input
|
||||
* @param maxCharacters Maximum length of input
|
||||
* @param color Text color
|
||||
* @param respondTo Element to send any response to when the popup closes.
|
||||
* If not provided, any response goes to the active view
|
||||
* @remarks Generates a TextInputMsg message with the text when Enter or escape is pressed
|
||||
*/
|
||||
void show(const Point &pt, bool isNumeric, size_t maxCharacters, byte color,
|
||||
TreeItem *respondTo = nullptr);
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
267
engines/ultima/shared/gfx/viewport_dungeon.cpp
Normal file
267
engines/ultima/shared/gfx/viewport_dungeon.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
/* 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 "ultima/shared/gfx/viewport_dungeon.h"
|
||||
#include "ultima/shared/maps/dungeon_widget.h"
|
||||
#include "ultima/shared/maps/dungeon_creature.h"
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EMPTY_MESSAGE_MAP(ViewportDungeon, Shared::Gfx::VisualItem);
|
||||
|
||||
void ViewportDungeon::draw() {
|
||||
// Get a surface reference and clear it's contents
|
||||
DungeonSurface s = getSurface();
|
||||
s.clear();
|
||||
|
||||
// Get the position delta for the facing direction, and the cells to the left and right of that
|
||||
Maps::Map *map = getGame()->getMap();
|
||||
Point delta = map->getDirectionDelta();
|
||||
|
||||
Point leftDelta, rightDelta;
|
||||
switch (map->getDirection()) {
|
||||
case Maps::DIR_LEFT:
|
||||
leftDelta.y = 1;
|
||||
rightDelta.y = -1;
|
||||
break;
|
||||
case Maps::DIR_RIGHT:
|
||||
leftDelta.y = -1;
|
||||
rightDelta.y = 1;
|
||||
break;
|
||||
case Maps::DIR_UP:
|
||||
leftDelta.x = -1;
|
||||
rightDelta.x = 1;
|
||||
break;
|
||||
case Maps::DIR_DOWN:
|
||||
leftDelta.x = 1;
|
||||
rightDelta.x = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Maps::MapTile tile, deltaTile, leftTile, rightTile, backTile;
|
||||
Point currentPos = map->getPosition();
|
||||
map->getTileAt(currentPos, &tile);
|
||||
map->getTileAt(currentPos + delta, &deltaTile);
|
||||
|
||||
bool isDoor = tile.isDoor();
|
||||
bool isWall = tile.isWallOrSecretDoor();
|
||||
int distance = distanceToOccupiedCell(delta);
|
||||
|
||||
// If stuck in a wall, draw it and exit
|
||||
if (isWall) {
|
||||
s.drawWall(0);
|
||||
return;
|
||||
}
|
||||
|
||||
Point backDelta(delta.x * distance, delta.y * distance),
|
||||
currDelta(delta.x * distance, delta.y * distance);
|
||||
|
||||
if (isDoor && deltaTile.isWallOrDoorway()) {
|
||||
s.drawWall(0);
|
||||
} else {
|
||||
if (isDoor)
|
||||
s.drawDoorway(0);
|
||||
|
||||
// These are essentially boolean flags with an extra 'initial' state
|
||||
byte endingLeft = 100, endingRight = 100;
|
||||
byte leftFlag = 100, rightFlag = 100;
|
||||
byte priorLeftFlag = 100, priorRightFlag = 100;
|
||||
|
||||
for (int index = distance; index; --index) {
|
||||
currDelta -= delta;
|
||||
Point pt = currentPos + currDelta;
|
||||
|
||||
if (!isDoor || index > 1) {
|
||||
map->getTileAt(pt + leftDelta, &leftTile);
|
||||
map->getTileAt(pt + rightDelta, &rightTile);
|
||||
leftFlag = leftTile.isSolid();
|
||||
rightFlag = rightTile.isSolid();
|
||||
if (index == distance) {
|
||||
endingLeft = leftFlag;
|
||||
endingRight = rightFlag;
|
||||
} else {
|
||||
if (leftFlag != priorLeftFlag)
|
||||
s.drawLeftEdge(index);
|
||||
if (rightFlag != priorRightFlag)
|
||||
s.drawRightEdge(index);
|
||||
}
|
||||
|
||||
drawLeftCell(index, leftTile);
|
||||
drawRightCell(index, rightTile);
|
||||
}
|
||||
|
||||
drawCell(index, pt + delta);
|
||||
priorLeftFlag = leftFlag;
|
||||
priorRightFlag = rightFlag;
|
||||
}
|
||||
|
||||
if (!isDoor)
|
||||
drawCell(0, currentPos);
|
||||
|
||||
map->getTileAt(currentPos + delta, &backTile);
|
||||
if (distance < 5 && isMonsterBlocking(currentPos + backDelta) && backTile.isDoor()) {
|
||||
map->getTileAt(currentPos + leftDelta, &leftTile);
|
||||
map->getTileAt(currentPos + rightDelta, &rightTile);
|
||||
|
||||
drawLeftCell(distance + 1, leftTile);
|
||||
drawRightCell(distance + 1, rightTile);
|
||||
|
||||
map->getTileAt(currentPos + leftDelta, &leftTile);
|
||||
if (!leftTile.isSolid())
|
||||
s.drawLeftEdge(distance);
|
||||
|
||||
if (!rightTile.isSolid())
|
||||
s.drawRightEdge(distance);
|
||||
} else {
|
||||
if (endingLeft)
|
||||
s.drawLeftEdge(distance);
|
||||
if (endingRight)
|
||||
s.drawRightEdge(distance);
|
||||
}
|
||||
}
|
||||
|
||||
Maps::DungeonWidget *widget = dynamic_cast<Maps::DungeonWidget *>(tile._widget);
|
||||
if (isDoor && widget) {
|
||||
widget->draw(s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint ViewportDungeon::distanceToOccupiedCell(const Point &delta) {
|
||||
Point d = delta;
|
||||
uint distance;
|
||||
for (distance = 1; !isCellOccupied(d); ++distance, d.x += delta.x, d.y += delta.y) {}
|
||||
|
||||
return MIN(distance, (uint)5);
|
||||
}
|
||||
|
||||
bool ViewportDungeon::isCellOccupied(const Point &delta) {
|
||||
Maps::Map *map = getGame()->getMap();
|
||||
Point pt = map->getPosition() + delta;
|
||||
|
||||
Maps::MapTile tile;
|
||||
map->getTileAt(pt, &tile);
|
||||
if (tile.isWallOrDoorway())
|
||||
return true;
|
||||
|
||||
return isMonsterBlocking(pt);
|
||||
}
|
||||
|
||||
bool ViewportDungeon::isMonsterBlocking(const Point &pt) {
|
||||
Maps::MapTile tile;
|
||||
getGame()->getMap()->getTileAt(pt, &tile);
|
||||
Maps::DungeonCreature *monster = dynamic_cast<Maps::DungeonCreature *>(tile._widget);
|
||||
return monster != nullptr && monster->isBlockingView();
|
||||
}
|
||||
|
||||
void ViewportDungeon::drawCell(uint distance, const Point &pt) {
|
||||
Game *game = getGame();
|
||||
DungeonSurface s = getSurface();
|
||||
Maps::Map *map = game->getMap();
|
||||
|
||||
Maps::MapTile tile;
|
||||
map->getTileAt(pt, &tile);
|
||||
|
||||
// TODO: This currently contains dungeon cell types specific to Ultima 1
|
||||
Maps::DungeonCreature *monster = dynamic_cast<Maps::DungeonCreature *>(tile._widget);
|
||||
if (monster) {
|
||||
// Draw a monster
|
||||
if (tile.isWallOrDoorway())
|
||||
s.drawWall(distance);
|
||||
if (tile._tileId == 7)
|
||||
// Ladder down
|
||||
s.drawWidget(27, distance + 1, game->_edgeColor);
|
||||
if (tile._tileId == 6)
|
||||
// Ladder up
|
||||
s.drawWidget(26, distance + 1, game->_edgeColor);
|
||||
|
||||
monster->draw(s, distance);
|
||||
} else {
|
||||
switch (tile._tileId) {
|
||||
case 1:
|
||||
case 2:
|
||||
// Wall or secret door
|
||||
s.drawWall(distance);
|
||||
break;
|
||||
case 3:
|
||||
// Doorway
|
||||
s.drawDoorway(distance);
|
||||
break;
|
||||
case 6:
|
||||
// Ladder down
|
||||
if (map->getDirection() == Maps::DIR_UP || map->getDirection() == Maps::DIR_DOWN) {
|
||||
s.drawLadderDownFaceOn(distance + 1);
|
||||
} else {
|
||||
s.drawLadderDownSideOn(distance + 1);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
// Ladder up
|
||||
if (map->getDirection() == Maps::DIR_UP || map->getDirection() == Maps::DIR_DOWN) {
|
||||
s.drawLadderUpFaceOn(distance + 1);
|
||||
} else {
|
||||
s.drawLadderUpSideOn(distance + 1);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// Beams
|
||||
s.drawBeams(distance);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw any item at that distance
|
||||
Maps::DungeonWidget *widget = dynamic_cast<Maps::DungeonWidget *>(tile._widget);
|
||||
if (widget)
|
||||
widget->draw(s, distance);
|
||||
}
|
||||
|
||||
void ViewportDungeon::drawLeftCell(uint distance, const Maps::MapTile &tile) {
|
||||
DungeonSurface s = getSurface();
|
||||
|
||||
if (tile.isDoor())
|
||||
s.drawLeftDoor(distance);
|
||||
else if (tile.isWallOrSecretDoor())
|
||||
s.drawLeftWall(distance);
|
||||
else
|
||||
s.drawLeftBlank(distance);
|
||||
}
|
||||
|
||||
void ViewportDungeon::drawRightCell(uint distance, const Maps::MapTile &tile) {
|
||||
DungeonSurface s = getSurface();
|
||||
|
||||
if (tile.isDoor())
|
||||
s.drawRightDoor(distance);
|
||||
else if (tile.isWallOrSecretDoor())
|
||||
s.drawRightWall(distance);
|
||||
else
|
||||
s.drawRightBlank(distance);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
83
engines/ultima/shared/gfx/viewport_dungeon.h
Normal file
83
engines/ultima/shared/gfx/viewport_dungeon.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_VIEWPORT_DUNGEON_H
|
||||
#define ULTIMA_SHARED_GFX_VIEWPORT_DUNGEON_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/gfx/dungeon_surface.h"
|
||||
#include "ultima/shared/maps/map_tile.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class ViewportDungeon : public Gfx::VisualItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
private:
|
||||
/**
|
||||
* Returns the distance to an occupied cell, if any
|
||||
*/
|
||||
uint distanceToOccupiedCell(const Point &delta);
|
||||
|
||||
/**
|
||||
* Returns if a cell at a given delta to the player is occupied
|
||||
*/
|
||||
bool isCellOccupied(const Point &delta);
|
||||
|
||||
/**
|
||||
* Returns true if a monster is at a given position, and it has the blocking attribute
|
||||
*/
|
||||
bool isMonsterBlocking(const Point &pt);
|
||||
|
||||
/**
|
||||
* Draw a monster or, failing that, the given tile at a given cell and distance
|
||||
*/
|
||||
void drawCell(uint distance, const Point &pt);
|
||||
|
||||
/**
|
||||
* Draw a cell to the left
|
||||
*/
|
||||
void drawLeftCell(uint distance, const Maps::MapTile &tile);
|
||||
|
||||
/**
|
||||
* Draw a cell to the left
|
||||
*/
|
||||
void drawRightCell(uint distance, const Maps::MapTile &tile);
|
||||
protected:
|
||||
/**
|
||||
* Returns the surface for rendering the dungeon
|
||||
*/
|
||||
virtual DungeonSurface getSurface() = 0;
|
||||
public:
|
||||
CLASSDEF;
|
||||
ViewportDungeon(TreeItem *parent) : Gfx::VisualItem("ViewportDungeon", Rect(8, 8, 312, 152), parent) {}
|
||||
~ViewportDungeon() override {}
|
||||
|
||||
/**
|
||||
* Draws the dungeon
|
||||
*/
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
62
engines/ultima/shared/gfx/viewport_map.cpp
Normal file
62
engines/ultima/shared/gfx/viewport_map.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/viewport_map.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EMPTY_MESSAGE_MAP(ViewportMap, Gfx::VisualItem);
|
||||
|
||||
void ViewportMap::draw() {
|
||||
// Get a surface reference and clear it's contents
|
||||
Gfx::VisualSurface s = getSurface();
|
||||
s.clear();
|
||||
|
||||
// Figure out how many tiles can fit into the display
|
||||
const Point spriteSize = _sprites->getSpriteSize();
|
||||
const Point visibleTiles(_bounds.width() / spriteSize.x, _bounds.height() / spriteSize.y);
|
||||
|
||||
// Get a reference to the map and get the starting tile position
|
||||
Maps::Map *map = getGame()->getMap();
|
||||
const Point topLeft = map->getViewportPosition(visibleTiles);
|
||||
|
||||
// Iterate through drawing the map
|
||||
Maps::MapTile tile;
|
||||
for (int y = 0; y < visibleTiles.y; ++y) {
|
||||
for (int x = 0; x < visibleTiles.x; ++x) {
|
||||
Point drawPos(x * spriteSize.x, y * spriteSize.y);
|
||||
|
||||
// Get the next tile to display and draw it
|
||||
map->getTileAt(Point(topLeft.x + x, topLeft.y + y), &tile);
|
||||
(*_sprites)[tile._tileDisplayNum].draw(s, drawPos);
|
||||
|
||||
// Draw any widgets on the tile
|
||||
for (uint idx = 0; idx < tile._widgets.size(); ++idx)
|
||||
(*_sprites)[tile._widgets[idx]->getTileNum()].draw(s, drawPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
57
engines/ultima/shared/gfx/viewport_map.h
Normal file
57
engines/ultima/shared/gfx/viewport_map.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_VIEWPORT_MAP_H
|
||||
#define ULTIMA_SHARED_GFX_VIEWPORT_MAP_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/gfx/sprites.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class ViewportMap : public Gfx::VisualItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
protected:
|
||||
Gfx::Sprites *_sprites;
|
||||
public:
|
||||
CLASSDEF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ViewportMap(TreeItem *parent) : Gfx::VisualItem("ViewportMap", Rect(8, 8, 312, 152), parent), _sprites(nullptr) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ViewportMap() override {}
|
||||
|
||||
/**
|
||||
* Draws the map
|
||||
*/
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
140
engines/ultima/shared/gfx/visual_container.cpp
Normal file
140
engines/ultima/shared/gfx/visual_container.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/* 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 "ultima/shared/gfx/visual_container.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
BEGIN_MESSAGE_MAP(VisualContainer, VisualItem)
|
||||
ON_MESSAGE(MouseButtonDownMsg)
|
||||
ON_MESSAGE(MouseButtonUpMsg)
|
||||
ON_MESSAGE(MouseMoveMsg)
|
||||
ON_MESSAGE(MouseDoubleClickMsg)
|
||||
ON_MESSAGE(MouseWheelMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
bool VisualContainer::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
|
||||
if (msg->_buttons & MB_LEFT) {
|
||||
_mouseFocusItem = handleMouseMsg(msg);
|
||||
return _mouseFocusItem != nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualContainer::MouseButtonUpMsg(CMouseButtonUpMsg *msg) {
|
||||
if (msg->_buttons & MB_LEFT) {
|
||||
bool result = handleMouseMsg(msg) != nullptr;
|
||||
_mouseFocusItem = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualContainer::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) {
|
||||
if (msg->_buttons & MB_LEFT)
|
||||
return handleMouseMsg(msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualContainer::MouseWheelMsg(CMouseWheelMsg *msg) {
|
||||
return handleMouseMsg(msg);
|
||||
}
|
||||
|
||||
bool VisualContainer::MouseMoveMsg(CMouseMoveMsg *msg) {
|
||||
if (msg->_buttons & MB_LEFT)
|
||||
return handleMouseMsg(msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualContainer::MouseDragMsg(CMouseDragMsg *msg) {
|
||||
return handleMouseMsg(msg);
|
||||
}
|
||||
|
||||
VisualItem *VisualContainer::handleMouseMsg(CMouseMsg *msg) {
|
||||
if (_mouseFocusItem) {
|
||||
// An item currently has focus, so pass all events directly to
|
||||
// it, irrespective of whether the mouse is still in it or not
|
||||
msg->execute(_mouseFocusItem);
|
||||
return _mouseFocusItem;
|
||||
|
||||
} else {
|
||||
// Iterate through each child and pass the message to the first
|
||||
// immediate child the mouse position falls within
|
||||
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
|
||||
VisualItem *item = dynamic_cast<VisualItem *>(child);
|
||||
if (item && item->getBounds().contains(msg->_mousePos)) {
|
||||
if (msg->execute(item))
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualContainer::draw() {
|
||||
// If the overall container is dirty, clear it
|
||||
if (_isDirty)
|
||||
getSurface().clear();
|
||||
|
||||
// Iterate through each child and draw any dirty visual items
|
||||
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
|
||||
VisualItem *item = dynamic_cast<VisualItem *>(child);
|
||||
if (item && item->isDirty())
|
||||
item->draw();
|
||||
}
|
||||
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
void VisualContainer::setDirty(bool dirty) {
|
||||
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
|
||||
VisualItem *item = dynamic_cast<VisualItem *>(child);
|
||||
if (item)
|
||||
item->setDirty(dirty);
|
||||
}
|
||||
|
||||
VisualItem::setDirty(dirty);
|
||||
}
|
||||
|
||||
bool VisualContainer::isDirty() const {
|
||||
if (_isDirty)
|
||||
return true;
|
||||
|
||||
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
|
||||
VisualItem *item = dynamic_cast<VisualItem *>(child);
|
||||
if (item && item->isDirty())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
78
engines/ultima/shared/gfx/visual_container.h
Normal file
78
engines/ultima/shared/gfx/visual_container.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_VISUAL_CONTAINER_H
|
||||
#define ULTIMA_SHARED_GFX_VISUAL_CONTAINER_H
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/core/message_target.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
class VisualContainer : public VisualItem {
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
|
||||
bool MouseButtonUpMsg(CMouseButtonUpMsg *msg);
|
||||
bool MouseMoveMsg(CMouseMoveMsg *msg);
|
||||
bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg);
|
||||
bool MouseWheelMsg(CMouseWheelMsg *msg);
|
||||
bool MouseDragMsg(CMouseDragMsg *msg);
|
||||
private:
|
||||
VisualItem *_mouseFocusItem;
|
||||
private:
|
||||
/**
|
||||
* Called to handle mouse messagaes on the view
|
||||
*/
|
||||
VisualItem *handleMouseMsg(CMouseMsg *msg);
|
||||
public:
|
||||
CLASSDEF;
|
||||
VisualContainer(TreeItem *parent = nullptr) : VisualItem(parent), _mouseFocusItem(nullptr) {}
|
||||
VisualContainer(const Rect &r, TreeItem *parent = nullptr) :
|
||||
VisualItem(r, parent), _mouseFocusItem(nullptr) {}
|
||||
VisualContainer(const Common::String &name, TreeItem *parent = nullptr) :
|
||||
VisualItem(name, parent), _mouseFocusItem(nullptr) {}
|
||||
VisualContainer(const Common::String &name, const Rect &r, TreeItem *parent = nullptr) :
|
||||
VisualItem(name, r, parent), _mouseFocusItem(nullptr) {}
|
||||
~VisualContainer() override {}
|
||||
|
||||
/**
|
||||
* Draws the container by iterating through each child and letting it draw
|
||||
*/
|
||||
void draw() override;
|
||||
|
||||
/**
|
||||
* Flags the item as being changed, requiring a redraw
|
||||
*/
|
||||
void setDirty(bool dirty = true) override;
|
||||
|
||||
/**
|
||||
* Returns true if the item is dirty, requiring a redraw
|
||||
*/
|
||||
bool isDirty() const override;
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
90
engines/ultima/shared/gfx/visual_item.cpp
Normal file
90
engines/ultima/shared/gfx/visual_item.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
BEGIN_MESSAGE_MAP(VisualItem, NamedItem)
|
||||
ON_MESSAGE(ShowMsg)
|
||||
ON_MESSAGE(HideMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
void VisualItem::init(TreeItem *parent) {
|
||||
_isDirty = true;
|
||||
if (parent != nullptr)
|
||||
addUnder(parent);
|
||||
}
|
||||
|
||||
bool VisualItem::ShowMsg(CShowMsg *msg) {
|
||||
// When a view is shown, mark it to be redrawn
|
||||
_isDirty = true;
|
||||
// Font *font = Font::getActiveFont();
|
||||
// _fontDetails._fontNumber = font ? font->_fontNumber : 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualItem::HideMsg(CHideMsg *msg) {
|
||||
// When view is hidden, mark it as not dirty
|
||||
_isDirty = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
VisualSurface VisualItem::getSurface() {
|
||||
Graphics::ManagedSurface src(*g_vm->_screen, _bounds);
|
||||
return VisualSurface(src, _bounds, getGame());
|
||||
}
|
||||
|
||||
void VisualItem::setBounds(const Rect &r) {
|
||||
_bounds = r;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void VisualItem::setPosition(const Point &pt) {
|
||||
_bounds.moveTo(pt);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void VisualItem::setDirty(bool dirty) {
|
||||
// Flag the item as dirty
|
||||
_isDirty = dirty;
|
||||
}
|
||||
|
||||
void VisualItem::setView(const Common::String &viewName) {
|
||||
getGame()->setView(viewName);
|
||||
}
|
||||
|
||||
void VisualItem::setPopup(Gfx::Popup *popup) {
|
||||
getGame()->setPopup(popup);
|
||||
}
|
||||
|
||||
void VisualItem::setView() {
|
||||
getGame()->setView(this);
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shaerd
|
||||
} // End of namespace Ultima
|
||||
128
engines/ultima/shared/gfx/visual_item.h
Normal file
128
engines/ultima/shared/gfx/visual_item.h
Normal 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 ULTIMA_SHARED_GFX_VISUAL_ITEM_H
|
||||
#define ULTIMA_SHARED_GFX_VISUAL_ITEM_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "ultima/shared/core/named_item.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
#include "ultima/shared/gfx/visual_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
class Popup;
|
||||
|
||||
/**
|
||||
* Acts as the base class for all classes that have a visual representation on the screen
|
||||
*/
|
||||
class VisualItem : public NamedItem {
|
||||
friend class VisualSurface;
|
||||
DECLARE_MESSAGE_MAP;
|
||||
bool ShowMsg(CShowMsg *msg);
|
||||
bool HideMsg(CHideMsg *msg);
|
||||
private:
|
||||
/**
|
||||
* Common initialization method used by the constructors
|
||||
*/
|
||||
void init(TreeItem *parent = nullptr);
|
||||
protected:
|
||||
Rect _bounds;
|
||||
bool _isDirty;
|
||||
public:
|
||||
CLASSDEF;
|
||||
VisualItem(TreeItem *parent = nullptr) { init(parent); }
|
||||
VisualItem(const Rect &r, TreeItem *parent = nullptr) : _bounds(r) { init(parent); }
|
||||
VisualItem(const Common::String &name, TreeItem *parent = nullptr) : NamedItem(name) { init(parent); }
|
||||
VisualItem(const Common::String &name, const Rect &r, TreeItem *parent = nullptr) : NamedItem(name),
|
||||
_bounds(r) { init(parent); }
|
||||
|
||||
~VisualItem() override {
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the visual item on the screen
|
||||
*/
|
||||
virtual void draw() {
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a managed surface representing the portion of the screen defined by _bounds.
|
||||
* This allows drawing to be done without worrying about offsets or clipping
|
||||
*/
|
||||
VisualSurface getSurface();
|
||||
|
||||
/**
|
||||
* Gets the bounds for the item
|
||||
*/
|
||||
const Rect &getBounds() { return _bounds; }
|
||||
|
||||
/**
|
||||
* Sets the bounds for the item
|
||||
* @remarks Does not erase the item if it's already been drawn
|
||||
*/
|
||||
void setBounds(const Rect &r);
|
||||
|
||||
/**
|
||||
* Set the position for the item
|
||||
* @remarks Does not erase the item if it's already been drawn
|
||||
*/
|
||||
void setPosition(const Point &pt);
|
||||
|
||||
/**
|
||||
* Flags the item as being changed, requiring a redraw
|
||||
*/
|
||||
virtual void setDirty(bool dirty = true);
|
||||
|
||||
/**
|
||||
* Clears the dirty flag
|
||||
*/
|
||||
void clearDirty() { setDirty(false); }
|
||||
|
||||
/**
|
||||
* Returns true if the item is dirty, requiring a redraw
|
||||
*/
|
||||
virtual bool isDirty() const { return _isDirty; }
|
||||
|
||||
/**
|
||||
* Helper function to switch to a different visual item
|
||||
*/
|
||||
void setView(const Common::String &viewName);
|
||||
|
||||
/**
|
||||
* Helper function to switch to an on-screen popup
|
||||
*/
|
||||
void setPopup(Gfx::Popup *popup);
|
||||
|
||||
/**
|
||||
* Helper function to switch the item to be the current view
|
||||
*/
|
||||
void setView();
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
72
engines/ultima/shared/gfx/visual_surface.cpp
Normal file
72
engines/ultima/shared/gfx/visual_surface.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/gfx/visual_surface.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Gfx {
|
||||
|
||||
VisualSurface::VisualSurface(const Graphics::ManagedSurface &src, const Rect &bounds, GameBase *game) :
|
||||
_bounds(bounds), _textColor(255), _bgColor(0) {
|
||||
copyFrom(src);
|
||||
Shared::Game *sharedGame = dynamic_cast<Shared::Game *>(game);
|
||||
if (sharedGame) {
|
||||
_textColor = sharedGame->_textColor;
|
||||
_bgColor = sharedGame->_bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualSurface::drawPoint(const Point &pt, byte color) {
|
||||
fillRect(Rect(pt.x, pt.y, pt.x + 1, pt.y + 1), color);
|
||||
}
|
||||
|
||||
void VisualSurface::writeString(const Common::String &msg, const Point &pt, int color, int bgColor) {
|
||||
_textPos = pt;
|
||||
writeString(msg, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
|
||||
}
|
||||
|
||||
void VisualSurface::writeString(const Common::String &msg, int color, int bgColor) {
|
||||
Gfx::Font *font = g_vm->_game->getFont();
|
||||
font->writeString(*this, msg, _textPos, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
|
||||
}
|
||||
|
||||
void VisualSurface::writeChar(unsigned char c, const Point &pt, int color, int bgColor) {
|
||||
_textPos = pt;
|
||||
writeChar(c, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
|
||||
}
|
||||
|
||||
void VisualSurface::writeChar(unsigned char c, int color, int bgColor) {
|
||||
Gfx::Font *font = g_vm->_game->getFont();
|
||||
font->writeChar(*this, c, _textPos, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
|
||||
}
|
||||
|
||||
size_t VisualSurface::fontHeight() {
|
||||
Gfx::Font *font = g_vm->_game->getFont();
|
||||
return font->lineHeight();
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
91
engines/ultima/shared/gfx/visual_surface.h
Normal file
91
engines/ultima/shared/gfx/visual_surface.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_GFX_VISUAL_SURFACE_H
|
||||
#define ULTIMA_SHARED_GFX_VISUAL_SURFACE_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "ultima/shared/core/named_item.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class GameBase;
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class Font;
|
||||
|
||||
class VisualSurface : public Graphics::ManagedSurface {
|
||||
private:
|
||||
Rect _bounds;
|
||||
Point _textPos;
|
||||
byte _textColor;
|
||||
byte _bgColor;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
VisualSurface(const Graphics::ManagedSurface &src, const Rect &bounds, GameBase *game = nullptr);
|
||||
|
||||
/**
|
||||
* Draws a point on the surface
|
||||
*/
|
||||
void drawPoint(const Point &pt, byte color);
|
||||
|
||||
/**
|
||||
* Set the position for writing text to
|
||||
*/
|
||||
void setTextPos(const Point &pt) { _textPos = pt; }
|
||||
|
||||
/**
|
||||
* Write out a string
|
||||
*/
|
||||
void writeString(const Common::String &msg, const Point &pt, int color = -1, int bgColor = -1);
|
||||
|
||||
/**
|
||||
* Write out a string
|
||||
*/
|
||||
void writeString(const Common::String &msg, int color = -1, int bgColor = -1);
|
||||
|
||||
/**
|
||||
* Draw a character
|
||||
*/
|
||||
void writeChar(unsigned char c, const Point &pt, int color = -1, int bgColor = -1);
|
||||
|
||||
/**
|
||||
* Draw a character
|
||||
*/
|
||||
void writeChar(unsigned char c, int color = -1, int bgColor = -1);
|
||||
|
||||
/**
|
||||
* Get the current font height
|
||||
*/
|
||||
size_t fontHeight();
|
||||
};
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
55
engines/ultima/shared/maps/creature.cpp
Normal file
55
engines/ultima/shared/maps/creature.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/maps/creature.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
void Creature::synchronize(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(_hitPoints);
|
||||
}
|
||||
|
||||
void Creature::update(bool isPreUpdate) {
|
||||
if (isPreUpdate) {
|
||||
// Check whether creature can attack
|
||||
movement();
|
||||
_isAttacking = attackDistance() != 0;
|
||||
} else if (_isAttacking && !_gameRef->_party->isDead()) {
|
||||
attackParty();
|
||||
}
|
||||
}
|
||||
|
||||
bool Creature::subtractHitPoints(uint amount) {
|
||||
if ((int)amount >= _hitPoints) {
|
||||
_hitPoints = 0;
|
||||
return true;
|
||||
} else {
|
||||
_hitPoints -= amount;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
105
engines/ultima/shared/maps/creature.h
Normal file
105
engines/ultima/shared/maps/creature.h
Normal 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 ULTIMA_SHARED_WIDGETS_CREATURE_H
|
||||
#define ULTIMA_SHARED_WIDGETS_CREATURE_H
|
||||
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
class Map;
|
||||
|
||||
namespace Maps {
|
||||
|
||||
/**
|
||||
* Base class for creatures that can be killed
|
||||
*/
|
||||
class Creature {
|
||||
private:
|
||||
Game *_gameRef;
|
||||
// MapBase *_mapRef;
|
||||
protected:
|
||||
int _hitPoints;
|
||||
bool _isAttacking;
|
||||
protected:
|
||||
/**
|
||||
* Returns either the maximum attack distance for a monster, or 0 if the monster is beyond
|
||||
* that distance from the player
|
||||
*/
|
||||
virtual uint attackDistance() const { return 0; }
|
||||
|
||||
/**
|
||||
* Handles moving creatures
|
||||
*/
|
||||
virtual void movement() {}
|
||||
|
||||
/**
|
||||
* Handles attacking the player
|
||||
*/
|
||||
virtual void attackParty() {}
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Creature(Game *game, MapBase *) : _gameRef(game), _hitPoints(0), _isAttacking(false) {}
|
||||
Creature(Game *game, MapBase *, int hitPoints) : _gameRef(game),
|
||||
_hitPoints(hitPoints), _isAttacking(false) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Creature() {}
|
||||
|
||||
/**
|
||||
* Handles loading and saving games
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Called to update the widget at the end of a turn
|
||||
* @param isPreUpdate Update is called twice in succession during the end of turn update.
|
||||
* Once with true for all widgets, then with it false
|
||||
*/
|
||||
virtual void update(bool isPreUpdate);
|
||||
|
||||
/**
|
||||
* True true if the creature is dead
|
||||
*/
|
||||
bool isDead() const { return _hitPoints <= 0; }
|
||||
|
||||
/**
|
||||
* Removes hit points from a creature
|
||||
* @param amount Amount to remove
|
||||
* @returns Returns true if kills the creature
|
||||
*/
|
||||
virtual bool subtractHitPoints(uint amount);
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
66
engines/ultima/shared/maps/dungeon_creature.h
Normal file
66
engines/ultima/shared/maps/dungeon_creature.h
Normal 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 ULTIMA_SHARED_MAPS_DUNGEON_CREATURE_H
|
||||
#define ULTIMA_SHARED_MAPS_DUNGEON_CREATURE_H
|
||||
|
||||
#include "ultima/shared/maps/creature.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
class Map;
|
||||
|
||||
namespace Maps {
|
||||
|
||||
/**
|
||||
* Stub class for dungeon creatures
|
||||
*/
|
||||
class DungeonCreature : public Creature {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
DungeonCreature(Game *game, MapBase *map) : Creature(game, map) {}
|
||||
DungeonCreature(Game *game, MapBase *map, int hitPoints) : Creature(game, map, hitPoints) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~DungeonCreature() override {}
|
||||
|
||||
/**
|
||||
* Returns true if a monster blocks the background behind him
|
||||
*/
|
||||
virtual bool isBlockingView() const = 0;
|
||||
|
||||
/**
|
||||
* Draw a monster
|
||||
*/
|
||||
virtual void draw(DungeonSurface &s, uint distance) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
67
engines/ultima/shared/maps/dungeon_widget.h
Normal file
67
engines/ultima/shared/maps/dungeon_widget.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 ULTIMA_SHARED_MAPS_DUNGEON_WIDGET_H
|
||||
#define ULTIMA_SHARED_MAPS_DUNGEON_WIDGET_H
|
||||
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/gfx/dungeon_surface.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
class Map;
|
||||
|
||||
namespace Maps {
|
||||
|
||||
/**
|
||||
* Base class for things that appear within the dungeons
|
||||
*/
|
||||
class DungeonWidget : public MapWidget {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
DungeonWidget(Game *game, Maps::MapBase *map) : MapWidget(game, map) {}
|
||||
DungeonWidget(Game *game, Maps::MapBase *map, const Point &pt, Direction dir = DIR_NONE) : MapWidget(game, map, pt, dir) {}
|
||||
DungeonWidget(Game *game, Maps::MapBase *map, const Common::String &name, const Point &pt, Direction dir = DIR_NONE) :
|
||||
MapWidget(game, map, name, pt, dir) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~DungeonWidget() override {}
|
||||
|
||||
/**
|
||||
* Draws an item
|
||||
*/
|
||||
virtual void draw(DungeonSurface &s, uint distance) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
58
engines/ultima/shared/maps/map.cpp
Normal file
58
engines/ultima/shared/maps/map.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
void Map::clear() {
|
||||
if (_mapArea)
|
||||
_mapArea->clear();
|
||||
_mapArea = nullptr;
|
||||
}
|
||||
|
||||
void Map::load(MapId mapId) {
|
||||
_mapArea = nullptr;
|
||||
}
|
||||
|
||||
void Map::synchronize(Common::Serializer &s) {
|
||||
int mapId;
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Saving
|
||||
mapId = _mapArea->getMapId();
|
||||
s.syncAsUint16LE(mapId);
|
||||
} else {
|
||||
// Loading
|
||||
s.syncAsUint16LE(mapId);
|
||||
load(mapId);
|
||||
}
|
||||
|
||||
_mapArea->synchronize(s);
|
||||
}
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
250
engines/ultima/shared/maps/map.h
Normal file
250
engines/ultima/shared/maps/map.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/* 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 n redistribute it and/or
|
||||
* 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 ULTIMA_SHARED_MAPS_MAP_H
|
||||
#define ULTIMA_SHARED_MAPS_MAP_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/maps/map_base.h"
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map_tile.h"
|
||||
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
|
||||
namespace Maps {
|
||||
|
||||
#define REGISTER_WIDGET(NAME) if (name == #NAME) return new Widgets::NAME(_game, this)
|
||||
#define DECLARE_WIDGET(NAME) const char *getClassName() const override { return #NAME; }
|
||||
|
||||
/**
|
||||
* Base class for managing maps within the game
|
||||
*/
|
||||
class Map {
|
||||
protected:
|
||||
MapBase *_mapArea;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Map() : _mapArea(nullptr) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Map() {}
|
||||
|
||||
/**
|
||||
* Load a given map
|
||||
*/
|
||||
virtual void load(MapId mapId);
|
||||
|
||||
/**
|
||||
* Clears all map data
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Handles loading and saving the map's data
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Instantiates a widget type by name
|
||||
*/
|
||||
MapWidget *createWidget(const Common::String &name) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->createWidget(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tile at a given position
|
||||
*/
|
||||
void getTileAt(const Point &pt, MapTile *tile, bool includePlayer = true) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getTileAt(pt, tile, includePlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a tile at a given position
|
||||
*/
|
||||
void setTileAt(const Point &pt, uint tileId) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->setTileAt(pt, tileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the viewport position
|
||||
*/
|
||||
Point getViewportPosition(const Point &viewportSize) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getViewportPosition(viewportSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the map
|
||||
*/
|
||||
size_t width() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->width();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the map
|
||||
*/
|
||||
size_t height() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->height();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current position
|
||||
*/
|
||||
Point getPosition() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position
|
||||
*/
|
||||
void setPosition(const Point &pt) {
|
||||
assert(_mapArea);
|
||||
_mapArea->setPosition(pt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current direction
|
||||
*/
|
||||
Direction getDirection() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current direction
|
||||
*/
|
||||
void setDirection(Direction dir) {
|
||||
assert(_mapArea);
|
||||
_mapArea->setDirection(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a delta for the cell in front of the player based on the direction they're facing
|
||||
*/
|
||||
Point getDirectionDelta() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDirectionDelta();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a point relative to the current position
|
||||
*/
|
||||
Point getDeltaPosition(const Point &delta) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getDeltaPosition(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts the viewport by a given delta
|
||||
*/
|
||||
void shiftViewport(const Point &delta) {
|
||||
assert(_mapArea);
|
||||
_mapArea->shiftViewport(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the map there are for each tile in the original game.
|
||||
* This allows for more detailed maps in the enhanced game modes
|
||||
*/
|
||||
Point getTilesPerOrigTile() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_tilesPerOrigTile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the map
|
||||
*/
|
||||
Common::String getName() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active widget that the player is controlling
|
||||
*/
|
||||
MapWidget *getPlayerWidget() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->_playerWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param delta Delta to change dungeon level by
|
||||
* @returns False if dungeon left, true if still within dungeon
|
||||
*/
|
||||
bool changeLevel(int delta) {
|
||||
assert(_mapArea);
|
||||
return _mapArea->changeLevel(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current map level
|
||||
*/
|
||||
uint getLevel() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the map wraps around to the other side at it's edges (i.e. the overworld)
|
||||
*/
|
||||
bool isMapWrapped() const {
|
||||
assert(_mapArea);
|
||||
return _mapArea->isMapWrapped();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the map at the end of a turn
|
||||
*/
|
||||
void update() {
|
||||
assert(_mapArea);
|
||||
return _mapArea->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast a specific spell
|
||||
*/
|
||||
void castSpell(uint spellId) {
|
||||
assert(_mapArea);
|
||||
_mapArea->castSpell(spellId);
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
236
engines/ultima/shared/maps/map_base.cpp
Normal file
236
engines/ultima/shared/maps/map_base.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
/* 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 "ultima/shared/maps/map_base.h"
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
MapWidget *MapBase::WidgetsArray::findByClass(const ClassDef &classDef) const {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
MapWidget *w = (*this)[idx].get();
|
||||
if (w->isInstanceOf(classDef))
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void MapBase::clear() {
|
||||
_mapId = 0;
|
||||
_data.clear();
|
||||
_widgets.clear();
|
||||
}
|
||||
|
||||
void MapBase::load(MapId mapId) {
|
||||
_mapId = mapId;
|
||||
}
|
||||
|
||||
void MapBase::synchronize(Common::Serializer &s) {
|
||||
_viewportPos.synchronize(s);
|
||||
uint size;
|
||||
int transportIndex = -1;
|
||||
Common::String name;
|
||||
|
||||
// If the map is modified in any way, it gets synchronized as well
|
||||
s.syncAsByte(_mapModified);
|
||||
if (_mapModified) {
|
||||
for (uint y = 0; y < height(); ++y) {
|
||||
for (uint x = 0; x < width(); ++x)
|
||||
s.syncAsByte(_data[y][x]);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Save widgets
|
||||
size = 0;
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
if (_widgets[idx]->getClassName())
|
||||
++size;
|
||||
if (_playerWidget == _widgets[idx].get())
|
||||
transportIndex = (int)idx;
|
||||
}
|
||||
assert(transportIndex >= 0);
|
||||
|
||||
s.syncAsUint16LE(size);
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
name = _widgets[idx]->getClassName();
|
||||
if (!name.empty()) {
|
||||
s.syncString(name);
|
||||
_widgets[idx]->synchronize(s);
|
||||
}
|
||||
}
|
||||
s.syncAsUint16LE(transportIndex);
|
||||
|
||||
} else {
|
||||
// Load widgets
|
||||
s.syncAsUint16LE(size);
|
||||
_widgets.clear();
|
||||
for (uint idx = 0; idx < size; ++idx) {
|
||||
s.syncString(name);
|
||||
|
||||
MapWidget *w = createWidget(name);
|
||||
w->synchronize(s);
|
||||
addWidget(w);
|
||||
}
|
||||
|
||||
s.syncAsUint16LE(transportIndex);
|
||||
_playerWidget = _widgets[transportIndex].get();
|
||||
}
|
||||
}
|
||||
|
||||
void MapBase::setDimensions(const Point &size) {
|
||||
_data.resize(size.y);
|
||||
for (int y = 0; y < size.y; ++y)
|
||||
_data[y].resize(size.x);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
Point MapBase::getDirectionDelta() const {
|
||||
switch (_playerWidget->_direction) {
|
||||
case DIR_LEFT:
|
||||
return Point(-1, 0);
|
||||
case DIR_RIGHT:
|
||||
return Point(1, 0);
|
||||
case DIR_UP:
|
||||
return Point(0, -1);
|
||||
default:
|
||||
return Point(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Point MapBase::getDeltaPosition(const Point &delta) {
|
||||
return _playerWidget->_position + delta;
|
||||
}
|
||||
|
||||
void MapBase::resetViewport() {
|
||||
// Reset the viewport, so it's position will get recalculated
|
||||
_viewportPos.reset();
|
||||
}
|
||||
|
||||
Point MapBase::getViewportPosition(const Point &viewportSize) {
|
||||
Point &topLeft = _viewportPos._topLeft;
|
||||
|
||||
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
|
||||
// Calculate the new position
|
||||
topLeft.x = _playerWidget->_position.x - (viewportSize.x - 1) / 2;
|
||||
topLeft.y = _playerWidget->_position.y - (viewportSize.y - 1) / 2;
|
||||
|
||||
// Fixed maps, so constrain top left corner so the map fills the viewport.
|
||||
// This will accommodate future renderings with more tiles, or greater tile size
|
||||
topLeft.x = CLIP((int)topLeft.x, 0, (int)(width() - viewportSize.x));
|
||||
topLeft.y = CLIP((int)topLeft.y, 0, (int)(height() - viewportSize.y));
|
||||
}
|
||||
|
||||
return topLeft;
|
||||
}
|
||||
|
||||
void MapBase::shiftViewport(const Point &delta) {
|
||||
Point &topLeft = _viewportPos._topLeft;
|
||||
topLeft += delta;
|
||||
|
||||
// Shift the viewport, but constraining the map to fill up the screen
|
||||
topLeft.x = CLIP(topLeft.x, (int16)0, (int16)(width() - _viewportPos._size.x));
|
||||
topLeft.y = CLIP(topLeft.y, (int16)0, (int16)(height() - _viewportPos._size.y));
|
||||
}
|
||||
|
||||
void MapBase::addWidget(MapWidget *widget) {
|
||||
_widgets.push_back(MapWidgetPtr(widget));
|
||||
}
|
||||
|
||||
void MapBase::removeWidget(MapWidget *widget) {
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx) {
|
||||
if (_widgets[idx].get() == widget) {
|
||||
_widgets.remove_at(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapBase::getTileAt(const Point &pt, MapTile *tile, bool includePlayer) {
|
||||
tile->clear();
|
||||
|
||||
// Get the base tile
|
||||
tile->_tileDisplayNum = tile->_tileId = _data[pt.y][pt.x];
|
||||
|
||||
// Check for any widgets on that map tile
|
||||
tile->_widgets.clear();
|
||||
tile->_widget = nullptr;
|
||||
tile->_widgetNum = -1;
|
||||
|
||||
for (int idx = (int)_widgets.size() - 1; idx >= 0; --idx) {
|
||||
MapWidget *widget = _widgets[idx].get();
|
||||
if (widget->_position == pt && (includePlayer || widget != _playerWidget)) {
|
||||
tile->_widgets.push_back(widget);
|
||||
|
||||
if (!tile->_widget) {
|
||||
tile->_widgetNum = idx;
|
||||
tile->_widget = widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapBase::setTileAt(const Point &pt, uint tileId) {
|
||||
_data[pt.y][pt.x] = tileId;
|
||||
}
|
||||
|
||||
void MapBase::update() {
|
||||
// Call the update method of each widget, to allow for things like npc movement, etc.
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx)
|
||||
_widgets[idx].get()->update(true);
|
||||
|
||||
// Call the update method of each widget, to allow for things like npc movement, etc.
|
||||
for (uint idx = 0; idx < _widgets.size(); ++idx)
|
||||
_widgets[idx].get()->update(false);
|
||||
}
|
||||
|
||||
Point MapBase::getPosition() const {
|
||||
return _playerWidget->_position;
|
||||
}
|
||||
|
||||
void MapBase::setPosition(const Point &pt) {
|
||||
_playerWidget->_position = pt;
|
||||
}
|
||||
|
||||
Direction MapBase::getDirection() const {
|
||||
return _playerWidget->_direction;
|
||||
}
|
||||
|
||||
void MapBase::setDirection(Direction dir) {
|
||||
_playerWidget->_direction = dir;
|
||||
}
|
||||
|
||||
void MapBase::addInfoMsg(const Common::String &text, bool newLine, bool replaceLine) {
|
||||
CInfoMsg msg(text, newLine, replaceLine);
|
||||
msg.execute(_game->getView());
|
||||
}
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
291
engines/ultima/shared/maps/map_base.h
Normal file
291
engines/ultima/shared/maps/map_base.h
Normal file
@@ -0,0 +1,291 @@
|
||||
/* 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 ULTIMA_SHARED_MAPS_MAP_BASE_H
|
||||
#define ULTIMA_SHARED_MAPS_MAP_BASE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/base_object.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Game;
|
||||
|
||||
namespace Maps {
|
||||
|
||||
typedef int MapId;
|
||||
typedef byte MapCell;
|
||||
|
||||
class Map;
|
||||
class MapTile;
|
||||
|
||||
/**
|
||||
* Base class for specific map types
|
||||
*/
|
||||
class MapBase {
|
||||
/**
|
||||
* Widgets array
|
||||
*/
|
||||
class WidgetsArray : public Common::Array<MapWidgetPtr> {
|
||||
public:
|
||||
/**
|
||||
* Finds a widget by class
|
||||
*/
|
||||
MapWidget *findByClass(const ClassDef &classDef) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal class used for storing the data for a row
|
||||
*/
|
||||
struct MapCellsRow {
|
||||
private:
|
||||
Common::Array<MapCell> _data;
|
||||
public:
|
||||
byte &operator[](int idx) { return _data[idx]; }
|
||||
byte operator[](int idx) const { return _data[idx]; }
|
||||
|
||||
/**
|
||||
* Resize the row
|
||||
*/
|
||||
void resize(size_t newSize) { _data.resize(newSize); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores state about the current viewport being displayed. It's kept as part of the Map class
|
||||
* as a convenience to be alongside the current party position
|
||||
*/
|
||||
struct ViewportPosition {
|
||||
Point _topLeft; // Top, left tile position for viewport
|
||||
Point _size; // Size of the viewport. Just in case we ever allow it to change
|
||||
MapId _mapId; // Maze the viewport is for. Used to detect when the map changes
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ViewportPosition() : _topLeft(-1, -1), _mapId(-1) {}
|
||||
|
||||
/**
|
||||
* Returns true if the viewport is in a valid state
|
||||
*/
|
||||
bool isValid() const { return _mapId != -1; }
|
||||
|
||||
/**
|
||||
* Handles loading and saving viewport
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_topLeft.x);
|
||||
s.syncAsUint16LE(_topLeft.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the viewport position, so it'll get recalculated the next call to getViewportPosition
|
||||
*/
|
||||
void reset() { _mapId = -1; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Map *_map; // Map manager reference
|
||||
Game *_game; // Game reference
|
||||
bool _mapModified; // Tiles have been dynamically changed
|
||||
protected:
|
||||
MapId _mapId; // The map Id
|
||||
uint _mapIndex; // Index of map within the group of same maps
|
||||
uint _mapStyle; // Map style category for towns & castles
|
||||
ViewportPosition _viewportPos; // Viewport position
|
||||
Common::Array<MapCellsRow> _data; // Data for the map
|
||||
protected:
|
||||
/**
|
||||
* Set the size of the map
|
||||
*/
|
||||
void setDimensions(const Point &size);
|
||||
|
||||
/**
|
||||
* Adds a text string to the info area
|
||||
* @param text Text to add
|
||||
* @param newLine Whether to apply a newline at the end
|
||||
* @param replaceLine If true, replaces the current last line
|
||||
*/
|
||||
void addInfoMsg(const Common::String &text, bool newLine = true, bool replaceLine = false);
|
||||
public:
|
||||
Point _size; // X, Y size of the map
|
||||
Point _tilesPerOrigTile; // For enhanced modes, number of tiles per original game tile
|
||||
Common::String _name; // Name of map, if applicable
|
||||
MapWidget *_playerWidget; // Current means of transport, even if on foot
|
||||
WidgetsArray _widgets; // Party, monsteres, transports, etc.
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MapBase(Game *game, Map *) : _game(game),_playerWidget(nullptr),
|
||||
_mapModified(false), _mapId(0), _mapIndex(0), _mapStyle(0) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MapBase() {}
|
||||
|
||||
/**
|
||||
* Handles loading and saving the map's data
|
||||
*/
|
||||
virtual void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Adds a widget to the map
|
||||
*/
|
||||
void addWidget(MapWidget *widget);
|
||||
|
||||
/**
|
||||
* Removes a widget from the map
|
||||
*/
|
||||
void removeWidget(MapWidget *widget);
|
||||
|
||||
/**
|
||||
* Clears all map data
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Gets a tile at a given position
|
||||
*/
|
||||
virtual void getTileAt(const Point &pt, MapTile *tile, bool includePlayer = true);
|
||||
|
||||
/**
|
||||
* Sets a tile at a given position
|
||||
*/
|
||||
virtual void setTileAt(const Point &pt, uint tileId);
|
||||
|
||||
/**
|
||||
* Resets the viewport when the viewport changes
|
||||
*/
|
||||
void resetViewport();
|
||||
|
||||
/**
|
||||
* Get the viewport position
|
||||
*/
|
||||
virtual Point getViewportPosition(const Point &viewportSize);
|
||||
|
||||
/**
|
||||
* Load the map
|
||||
*/
|
||||
virtual void load(MapId mapId);
|
||||
|
||||
/**
|
||||
* Changes the level. Only applicable to dungeon maps which have levels
|
||||
* @param delta Delta to change dungeon level by
|
||||
* @returns False if dungeon left, true if still within dungeon
|
||||
*/
|
||||
virtual bool changeLevel(int delta) { return true; }
|
||||
|
||||
/**
|
||||
* Get the current map level
|
||||
*/
|
||||
virtual uint getLevel() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns whether the map wraps around to the other side at it's edges (i.e. the overworld)
|
||||
*/
|
||||
virtual bool isMapWrapped() const { return false; }
|
||||
|
||||
/**
|
||||
* Instantiates a widget type by name
|
||||
*/
|
||||
virtual MapWidget *createWidget(const Common::String &name) = 0;
|
||||
|
||||
/**
|
||||
* Returns the width of the map
|
||||
*/
|
||||
size_t width() const { return _size.x; }
|
||||
|
||||
/**
|
||||
* Returns the height of the map
|
||||
*/
|
||||
size_t height() const { return _size.y; }
|
||||
|
||||
/**
|
||||
* Get the current position
|
||||
*/
|
||||
Point getPosition() const;
|
||||
|
||||
/**
|
||||
* Set the current position
|
||||
*/
|
||||
void setPosition(const Point &pt);
|
||||
|
||||
/**
|
||||
* Get the current direction
|
||||
*/
|
||||
Direction getDirection() const;
|
||||
|
||||
/**
|
||||
* Set the current direction
|
||||
*/
|
||||
void setDirection(Direction dir);
|
||||
|
||||
/**
|
||||
* Returns a delta for the cell in front of the player based on the direction they're facing
|
||||
*/
|
||||
Point getDirectionDelta() const;
|
||||
|
||||
/**
|
||||
* Gets a point relative to the current position
|
||||
*/
|
||||
virtual Point getDeltaPosition(const Point &delta);
|
||||
|
||||
/**
|
||||
* Returns the map Id
|
||||
*/
|
||||
MapId getMapId() const { return _mapId; }
|
||||
|
||||
/**
|
||||
* Gets the map Index
|
||||
*/
|
||||
uint getMapIndex() const { return _mapIndex; }
|
||||
|
||||
/**
|
||||
* Gets the map style
|
||||
*/
|
||||
uint getMapStyle() const { return _mapStyle; }
|
||||
|
||||
/**
|
||||
* Shifts the viewport by a given delta
|
||||
*/
|
||||
virtual void shiftViewport(const Point &delta);
|
||||
|
||||
/**
|
||||
* Updates the map at the end of a turn
|
||||
*/
|
||||
virtual void update();
|
||||
|
||||
/**
|
||||
* Cast a specific spell
|
||||
*/
|
||||
virtual void castSpell(uint spell) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
41
engines/ultima/shared/maps/map_tile.cpp
Normal file
41
engines/ultima/shared/maps/map_tile.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/shared/maps/map_tile.h"
|
||||
#include "ultima/shared/maps/map_widget.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
void MapTile::clear() {
|
||||
_tileId = _tileDisplayNum = -1;
|
||||
_widgets.clear();
|
||||
_widgetNum = -1;
|
||||
_widget = nullptr;
|
||||
_isDoor = _isSecretDoor = false;
|
||||
_isLadderUp = _isLadderDown = false;
|
||||
_isWall = _isHallway = _isBeams = false;
|
||||
}
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
91
engines/ultima/shared/maps/map_tile.h
Normal file
91
engines/ultima/shared/maps/map_tile.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_MAPS_MAP_TILE_H
|
||||
#define ULTIMA_SHARED_MAPS_MAP_TILE_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
class MapWidget;
|
||||
|
||||
/**
|
||||
* Contains data about a given position within the map
|
||||
*/
|
||||
class MapTile {
|
||||
public:
|
||||
int _tileId; // Original tile Id
|
||||
int _tileDisplayNum; // Tile number to display. Can differ from tileId, such as tiles in the
|
||||
// city for talking/stealing to merchants showing as ground
|
||||
Common::Array<MapWidget *> _widgets; // Widgets on the tile, if any
|
||||
int _widgetNum; // Widget number of first widget, if any
|
||||
MapWidget *_widget; // Pointer tofirst widget on tile, if any
|
||||
// Dungeon tile flags
|
||||
bool _isDoor, _isSecretDoor;
|
||||
bool _isLadderUp, _isLadderDown;
|
||||
bool _isWall, _isHallway, _isBeams;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MapTile() : _tileDisplayNum(-1), _tileId(-1), _widgetNum(-1), _widget(0),
|
||||
_isDoor(false), _isSecretDoor(false), _isLadderUp(false), _isLadderDown(false), _isWall(false),
|
||||
_isHallway(false), _isBeams(false) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MapTile() {}
|
||||
|
||||
/**
|
||||
* Clears the map tile information
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Returns true if the tile is a door in a dungeon
|
||||
*/
|
||||
bool isDoor() const { return _isDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if the tile is a wall or secret door in a dungeon
|
||||
*/
|
||||
bool isWallOrSecretDoor() const { return _isWall || _isSecretDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if the tile in a dungeon is a type that has walls on it: walls, doors, or secret doors
|
||||
*/
|
||||
bool isWallOrDoorway() const { return _isWall || _isDoor || _isSecretDoor; }
|
||||
|
||||
/**
|
||||
* Returns true if a tile is a solid type within a dungeon
|
||||
*/
|
||||
bool isSolid() const { return !(_isHallway || _isLadderUp || _isLadderDown || _isBeams); }
|
||||
};
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
117
engines/ultima/shared/maps/map_widget.cpp
Normal file
117
engines/ultima/shared/maps/map_widget.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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 "ultima/shared/maps/map_widget.h"
|
||||
#include "ultima/shared/maps/map_base.h"
|
||||
#include "ultima/shared/maps/map_tile.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
namespace Maps {
|
||||
|
||||
EMPTY_MESSAGE_MAP(MapWidget, MessageTarget);
|
||||
|
||||
Direction MapWidget::directionFromKey(Common::KeyCode keycode) {
|
||||
switch (keycode) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_KP4:
|
||||
return DIR_WEST;
|
||||
|
||||
case Common::KEYCODE_RIGHT:
|
||||
case Common::KEYCODE_KP6:
|
||||
return DIR_EAST;
|
||||
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_KP8:
|
||||
return DIR_NORTH;
|
||||
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_KP2:
|
||||
return DIR_SOUTH;
|
||||
|
||||
default:
|
||||
return DIR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_position.x);
|
||||
s.syncAsSint16LE(_position.y);
|
||||
s.syncAsByte(_direction);
|
||||
s.syncString(_name);
|
||||
}
|
||||
|
||||
void MapWidget::addInfoMsg(const Common::String &text, bool newLine, bool replaceLine) {
|
||||
CInfoMsg msg(text, newLine, replaceLine);
|
||||
msg.execute(_game->getView());
|
||||
}
|
||||
|
||||
MapWidget::CanMove MapWidget::canMoveTo(const Point &destPos) {
|
||||
if (destPos.x < 0 || destPos.y < 0 || destPos.x >= (int)_map->width() || destPos.y >= (int)_map->height()) {
|
||||
// If the map is fixed, allow moving beyond it's edges so it can be left
|
||||
if (!_map->isMapWrapped())
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Get the details of the position
|
||||
MapTile destTile;
|
||||
_map->getTileAt(destPos, &destTile);
|
||||
|
||||
// If there's a widget blocking the tile, return false
|
||||
if (destTile._widget && destTile._widget->isBlocking())
|
||||
return NO;
|
||||
|
||||
return UNSET;
|
||||
}
|
||||
|
||||
void MapWidget::moveTo(const Point &destPos, Direction dir) {
|
||||
// If no direction is specified, we'll need to figure it out relative to the old position
|
||||
if (dir == DIR_NONE) {
|
||||
Point delta = destPos - _position;
|
||||
if (ABS(delta.x) > ABS(delta.y))
|
||||
_direction = delta.x > 0 ? DIR_EAST : DIR_WEST;
|
||||
else if (delta.y != 0)
|
||||
_direction = delta.y > 0 ? DIR_SOUTH : DIR_NORTH;
|
||||
} else {
|
||||
_direction = dir;
|
||||
}
|
||||
|
||||
// Set new location
|
||||
_position = destPos;
|
||||
|
||||
// Handle wrap around if need be on maps that wrap
|
||||
if (_map->isMapWrapped()) {
|
||||
if (_position.x < 0)
|
||||
_position.x += _map->width();
|
||||
else if (_position.x >= (int)_map->width())
|
||||
_position.x -= _map->width();
|
||||
if (_position.y < 0)
|
||||
_position.y += _map->height();
|
||||
else if (_position.y >= (int)_map->height())
|
||||
_position.y -= _map->height();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Maps
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user