/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#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_conditional_object.h"
#include "qdengine/qdcore/qd_game_scene.h"
namespace QDEngine {
qdConditionalObject::qdConditionalObject() : _conditions_mode(CONDITIONS_OR) {
}
qdConditionalObject::qdConditionalObject(const qdConditionalObject &obj) : qdNamedObject(obj),
_conditions_mode(obj._conditions_mode),
_conditions(obj._conditions),
_condition_groups(obj._condition_groups) {
}
qdConditionalObject::~qdConditionalObject() {
}
qdConditionalObject &qdConditionalObject::operator = (const qdConditionalObject &obj) {
if (this == &obj) return *this;
*static_cast(this) = obj;
_conditions_mode = obj._conditions_mode;
_conditions = obj._conditions;
_condition_groups = obj._condition_groups;
return *this;
}
int qdConditionalObject::add_condition(const qdCondition *p) {
_conditions.push_back(*p);
_conditions.back().set_owner(this);
return _conditions.size() - 1;
}
bool qdConditionalObject::update_condition(int num, const qdCondition &p) {
assert(num >= 0 && num < (int)_conditions.size());
qdCondition &cond = _conditions[num];
cond = p;
cond.set_owner(this);
return true;
}
bool qdConditionalObject::check_conditions() {
qdCondition::clear_successful_clicks();
if (!_conditions.empty()) {
switch (conditions_mode()) {
case CONDITIONS_AND:
for (conditions_container_t::iterator it = _conditions.begin(); it != _conditions.end(); ++it) {
if (!it->is_in_group()) {
if (!it->check())
return false;
}
}
for (condition_groups_container_t::iterator it = _condition_groups.begin(); it != _condition_groups.end(); ++it) {
if (!check_group_conditions(*it))
return false;
}
return true;
case CONDITIONS_OR:
for (conditions_container_t::iterator it = _conditions.begin(); it != _conditions.end(); ++it) {
if (!it->is_in_group()) {
if (it->check())
return true;
}
}
for (condition_groups_container_t::iterator it = _condition_groups.begin(); it != _condition_groups.end(); ++it) {
if (check_group_conditions(*it))
return true;
}
return false;
}
}
return true;
}
bool qdConditionalObject::remove_conditon(int idx) {
assert(idx >= 0 && idx < (int)_conditions.size());
_conditions.erase(_conditions.begin() + idx);
for (condition_groups_container_t::iterator it = _condition_groups.begin(); it != _condition_groups.end(); ++it)
it->remove_condition(idx);
return true;
}
bool qdConditionalObject::load_conditions_script(const xml::tag *p) {
int count = 0;
int gr_count = 0;
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_CONDITION:
count++;
break;
case QDSCR_CONDITION_GROUP:
gr_count++;
break;
}
}
if (count) _conditions.resize(count);
conditions_container_t::iterator ict = _conditions.begin();
if (gr_count) _condition_groups.resize(gr_count);
condition_groups_container_t::iterator igt = _condition_groups.begin();
for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
switch (it->ID()) {
case QDSCR_CONDITION:
if (const xml::tag *tp = it->search_subtag(QDSCR_TYPE)) {
qdCondition *cp = &*ict;
cp->set_type(qdCondition::ConditionType(xml::tag_buffer(*tp).get_int()));
cp->load_script(&*it);
cp->set_owner(this);
}
++ict;
break;
case QDSCR_CONDITION_GROUP:
if (const xml::tag *tp = it->search_subtag(QDSCR_TYPE))
igt->set_conditions_mode(qdConditionGroup::conditions_mode_t(xml::tag_buffer(*tp).get_int()));
igt->load_script(&*it);
++igt;
break;
case QDSCR_CONDITIONS_MODE:
set_conditions_mode(ConditionsMode((xml::tag_buffer(*it).get_int())));
break;
}
}
for (uint i = 0; i < _conditions.size(); i++) {
if (is_condition_in_group(i))
_conditions[i].add_group_reference();
}
return true;
}
bool qdConditionalObject::save_conditions_script(Common::WriteStream &fh, int indent) const {
if (_conditions.size()) {
for (auto &it : _conditions) {
it.save_script(fh, indent + 1);
}
for (int i = 0; i <= indent; i++) {
fh.writeString("\t");
}
if (debugChannelSet(-1, kDebugLog))
fh.writeString(Common::String::format("%s\r\n", _conditions_mode == CONDITIONS_AND ? "CONDITIONS_AND" : "CONDITIONS_OR"));
else
fh.writeString(Common::String::format("%d\r\n", _conditions_mode));
}
for (auto &it : _condition_groups) {
it.save_script(fh, indent + 1);
}
return true;
}
void qdConditionalObject::conditions_quant(float dt) {
for (auto &it : _conditions) {
it.quant(dt);
}
}
bool qdConditionalObject::load_data(Common::SeekableReadStream &fh, int save_version) {
debugC(4, kDebugSave, " qdConditionalObject::load_data(): before: %d", (int)fh.pos());
if (!qdNamedObject::load_data(fh, save_version))
return false;
for (auto &it : _conditions)
it.load_data(fh, save_version);
debugC(4, kDebugSave, " qdConditionalObject::load_data(): after: %d", (int)fh.pos());
return true;
}
bool qdConditionalObject::save_data(Common::WriteStream &fh) const {
debugC(4, kDebugSave, " qdConditionalObject::save_data(): before: %d", (int)fh.pos());
if (!qdNamedObject::save_data(fh)) {
return false;
}
for (auto &it : _conditions)
it.save_data(fh);
debugC(4, kDebugSave, " qdConditionalObject::save_data(): after: %d", (int)fh.pos());
return true;
}
bool qdConditionalObject::check_group_conditions(const qdConditionGroup &gr) {
switch (gr.conditions_mode()) {
case qdConditionGroup::CONDITIONS_AND:
for (qdConditionGroup::conditions_iterator_t it = gr.conditions_begin(); it != gr.conditions_end(); ++it) {
if (!_conditions[*it].check())
return false;
}
return true;
case qdConditionGroup::CONDITIONS_OR:
for (qdConditionGroup::conditions_iterator_t it = gr.conditions_begin(); it != gr.conditions_end(); ++it) {
if (_conditions[*it].check())
return true;
}
return false;
}
return true;
}
bool qdConditionalObject::is_condition_in_group(int condition_idx) const {
for (condition_groups_container_t::const_iterator it = _condition_groups.begin(); it != _condition_groups.end(); ++it) {
if (Common::find(it->conditions_begin(), it->conditions_end(), condition_idx) != it->conditions_end())
return true;
}
return false;
}
int qdConditionalObject::add_condition_group(const qdConditionGroup *p) {
_condition_groups.push_back(*p);
return _condition_groups.size() - 1;
}
bool qdConditionalObject::update_condition_group(int num, const qdConditionGroup &p) {
assert(num >= 0 && num < (int)_condition_groups.size());
qdConditionGroup &gr = _condition_groups[num];
gr = p;
for (uint i = 0; i < _conditions.size(); i++) {
if (is_condition_in_group(i))
_conditions[i].add_group_reference();
else
_conditions[i].remove_group_reference();
}
return true;
}
bool qdConditionalObject::remove_conditon_group(int idx) {
assert(idx >= 0 && idx < (int)_condition_groups.size());
_condition_groups.erase(_condition_groups.begin() + idx);
for (uint i = 0; i < _conditions.size(); i++) {
if (is_condition_in_group(i))
_conditions[i].add_group_reference();
else
_conditions[i].remove_group_reference();
}
return true;
}
bool qdConditionalObject::init() {
bool result = true;
for (uint i = 0; i < _conditions.size(); i++) {
if (!_conditions[i].init())
result = false;
}
return result;
}
bool qdConditionalObject::trigger_can_start() const {
if (const qdGameScene *p = static_cast(owner(QD_NAMED_OBJECT_SCENE)))
return p->is_active();
return true;
}
} // namespace QDEngine