mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
This fixes annpying portability issue, generating tons of warnings, since printing int64s is still platform-dependent.
353 lines
8.6 KiB
C++
353 lines
8.6 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/debug.h"
|
|
#include "common/stream.h"
|
|
|
|
#include "qdengine/qd_fwd.h"
|
|
#include "qdengine/parser/xml_tag_buffer.h"
|
|
#include "qdengine/parser/qdscr_parser.h"
|
|
#include "qdengine/qdcore/qd_trigger_chain.h"
|
|
|
|
namespace QDEngine {
|
|
|
|
qdTriggerChain::qdTriggerChain() {
|
|
root_element()->set_id(qdTriggerElement::ROOT_ID);
|
|
root_element()->set_status(qdTriggerElement::TRIGGER_EL_DONE);
|
|
}
|
|
|
|
qdTriggerChain::~qdTriggerChain() {
|
|
for (auto &it : _elements) {
|
|
delete it;
|
|
}
|
|
|
|
_elements.clear();
|
|
}
|
|
|
|
bool qdTriggerChain::reindex_elements() {
|
|
int id = 0;
|
|
for (auto &it : _elements) {
|
|
it->set_id(id++);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
qdTriggerElementPtr qdTriggerChain::search_element(int id) {
|
|
if (id == qdTriggerElement::ROOT_ID)
|
|
return root_element();
|
|
|
|
for (auto it : _elements)
|
|
if (it->ID() == id)
|
|
return it;
|
|
|
|
return 0;
|
|
}
|
|
|
|
qdTriggerElementPtr qdTriggerChain::add_element(qdNamedObject *p) {
|
|
if (!can_add_element(p)) return 0;
|
|
|
|
qdTriggerElementPtr el = new qdTriggerElement(p);
|
|
_elements.push_back(el);
|
|
|
|
reindex_elements();
|
|
|
|
return el;
|
|
}
|
|
|
|
bool qdTriggerChain::remove_element(qdTriggerElementPtr p, bool free_mem, bool relink_elements) {
|
|
for (auto it = _elements.begin(); it != _elements.end(); it++) {
|
|
if (*it == p) {
|
|
if (relink_elements) {
|
|
for (auto &it_c : (*it)->children()) {
|
|
it_c.element()->remove_parent(*it);
|
|
}
|
|
|
|
for (auto &it_p : (*it)->parents()) {
|
|
it_p.element()->remove_child(*it);
|
|
}
|
|
for (auto &it_c : (*it)->children()) {
|
|
for (auto &it_p : (*it)->parents()) {
|
|
it_c.element()->add_parent(it_p.element());
|
|
it_p.element()->add_child(it_c.element());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (free_mem)
|
|
delete *it;
|
|
|
|
_elements.erase(it);
|
|
reindex_elements();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool qdTriggerChain::can_add_element(const qdNamedObject *p) const {
|
|
if (is_element_in_list(p) && p->named_object_type() != QD_NAMED_OBJECT_SCENE) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::init_elements() {
|
|
for (auto &it : _elements) {
|
|
it->clear_object_trigger_references();
|
|
}
|
|
|
|
for (auto &it : _elements) {
|
|
it->add_object_trigger_reference();
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::is_element_in_list(qdNamedObject const *p) const {
|
|
for (auto &it : _elements) {
|
|
if (it->object() == p)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool qdTriggerChain::is_element_in_list(qdTriggerElementConstPtr p) const {
|
|
for (auto &it : _elements) {
|
|
if (it == p || (it->object() && it->object() == p->object()))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool qdTriggerChain::add_link(qdTriggerElementPtr from, qdTriggerElementPtr to, int link_type, bool auto_restart) {
|
|
if (!from->add_child(to, link_type, auto_restart)) return false;
|
|
if (!to->add_parent(from, link_type)) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::remove_link(qdTriggerElementPtr from, qdTriggerElementPtr to) {
|
|
if (!from->remove_child(to)) return false;
|
|
if (!to->remove_parent(from)) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::load_script(const xml::tag *p) {
|
|
int id0, id1, tp0;
|
|
qdTriggerElementPtr el, el1;
|
|
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
|
|
switch (it->ID()) {
|
|
case QDSCR_NAME:
|
|
set_name(it->data());
|
|
break;
|
|
case QDSCR_TRIGGER_CHAIN_ROOT:
|
|
root_element()->load_script(&*it);
|
|
root_element()->set_status(qdTriggerElement::TRIGGER_EL_DONE);
|
|
break;
|
|
case QDSCR_TRIGGER_ELEMENT:
|
|
el = qdTriggerElementPtr(new qdTriggerElement);
|
|
el->load_script(&*it);
|
|
_elements.push_back(el);
|
|
break;
|
|
case QDSCR_TRIGGER_ELEMENT_LINK:
|
|
xml::tag_buffer(*it) > id0 > id1 > tp0;
|
|
|
|
el = search_element(id0);
|
|
el1 = search_element(id1);
|
|
|
|
if (el && el1) {
|
|
bool auto_restart = false;
|
|
if (const xml::tag * tp = it->search_subtag(QDSCR_TRIGGER_ELEMENT_LINK_AUTO_RESTART)) {
|
|
if (xml::tag_buffer(*tp).get_int())
|
|
auto_restart = true;
|
|
else
|
|
auto_restart = false;
|
|
}
|
|
add_link(el, el1, tp0, auto_restart);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
root_element()->retrieve_link_elements(this);
|
|
for (qdTriggerElementList::iterator it = _elements.begin(); it != _elements.end(); ++it)
|
|
(*it)->retrieve_link_elements(this);
|
|
|
|
for (qdTriggerLinkList::iterator itl = root_element()->children().begin();
|
|
itl != root_element()->children().end();
|
|
++itl)
|
|
itl->activate();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::save_script(Common::WriteStream &fh, int indent) const {
|
|
for (int i = 0; i < indent; i++) {
|
|
fh.writeString("\t");
|
|
}
|
|
|
|
fh.writeString("<trigger_chain name=");
|
|
|
|
if (name()) {
|
|
fh.writeString(Common::String::format("\"%s\"", qdscr_XML_string(name())));
|
|
} else {
|
|
fh.writeString("\" \"");
|
|
}
|
|
|
|
fh.writeString(">\r\n");
|
|
|
|
root_element()->save_script(fh, indent + 1);
|
|
|
|
for (auto &it : _elements) {
|
|
it->save_script(fh, indent + 1);
|
|
};
|
|
|
|
for (int i = 0; i < indent; i++) {
|
|
fh.writeString("\t");
|
|
}
|
|
fh.writeString("</trigger_chain>\r\n");
|
|
|
|
return true;
|
|
}
|
|
|
|
void qdTriggerChain::quant(float dt) {
|
|
root_element()->quant(dt);
|
|
|
|
for (auto &it : _elements)
|
|
it->quant(dt);
|
|
}
|
|
|
|
bool qdTriggerChain::init_debug_check() {
|
|
root_element()->debug_set_done();
|
|
for (qdTriggerElementList::iterator it = _elements.begin(); it != _elements.end(); ++it)
|
|
(*it)->debug_set_done();
|
|
|
|
if (root_element()->is_active()) {
|
|
root_element()->debug_set_active();
|
|
root_element()->set_status(qdTriggerElement::TRIGGER_EL_DONE);
|
|
|
|
for (qdTriggerLinkList::iterator itl = root_element()->children().begin(); itl != root_element()->children().end(); ++itl) {
|
|
itl->activate();
|
|
}
|
|
|
|
}
|
|
|
|
for (qdTriggerElementList::iterator it = _elements.begin(); it != _elements.end(); ++it) {
|
|
if ((*it)->is_active())
|
|
(*it)->debug_set_active();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
const char *qdTriggerChain::debug_comline() {
|
|
static const char *arg = "triggers_debug";
|
|
return arg;
|
|
}
|
|
|
|
bool qdTriggerChain::load_data(Common::SeekableReadStream &fh, int save_version) {
|
|
debugC(4, kDebugSave, " qdTriggerChain::load_data before: %d", (int)fh.pos());
|
|
int32 size = fh.readSint32LE();
|
|
|
|
if (size != (int)_elements.size()) {
|
|
return false;
|
|
}
|
|
|
|
if (!root_element()->load_data(fh, save_version)) {
|
|
return false;
|
|
}
|
|
|
|
for (auto &it : _elements) {
|
|
if (!it->load_data(fh, save_version)) {
|
|
return false;
|
|
}
|
|
}
|
|
debugC(4, kDebugSave, " qdTriggerChain::load_data after: %d", (int)fh.pos());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool qdTriggerChain::save_data(Common::WriteStream &fh) const {
|
|
debugC(4, kDebugSave, " qdTriggerChain::save_data before: %d", (int)fh.pos());
|
|
fh.writeUint32LE(_elements.size());
|
|
|
|
if (!root_element()->save_data(fh)) {
|
|
return false;
|
|
}
|
|
|
|
for (auto &it : _elements) {
|
|
if (!it->save_data(fh)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
debugC(4, kDebugSave, " qdTriggerChain::save_data after: %d", (int)fh.pos());
|
|
return true;
|
|
}
|
|
|
|
void qdTriggerChain::reset() {
|
|
root_element()->reset();
|
|
|
|
for (qdTriggerElementList::iterator it = _elements.begin(); it != _elements.end(); ++it)
|
|
(*it)->reset();
|
|
|
|
root_element()->set_status(qdTriggerElement::TRIGGER_EL_DONE);
|
|
|
|
for (qdTriggerLinkList::iterator itl = root_element()->children().begin(); itl != root_element()->children().end(); ++itl)
|
|
itl->activate();
|
|
}
|
|
|
|
bool qdTriggerChain::activate_links(const qdNamedObject *from) {
|
|
bool ret = false;
|
|
|
|
for (qdTriggerElementList::const_iterator it = _elements.begin(); it != _elements.end(); ++it) {
|
|
if ((*it)->object() == from) {
|
|
for (qdTriggerLinkList::iterator itl = (*it)->children().begin(); itl != (*it)->children().end(); ++itl)
|
|
itl->activate();
|
|
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool qdTriggerChain::deactivate_object_triggers(const qdNamedObject *p) {
|
|
bool ret = false;
|
|
|
|
for (qdTriggerElementList::const_iterator it = _elements.begin(); it != _elements.end(); ++it) {
|
|
if ((*it)->object()) {
|
|
const qdNamedObject *obj = (*it)->object()->owner(qdNamedObjectType(p->named_object_type()));
|
|
if (obj == p) {
|
|
(*it)->deactivate(p);
|
|
ret = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
} // namespace QDEngine
|