/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef QDENGINE_QDCORE_QD_CONDITION_H #define QDENGINE_QDCORE_QD_CONDITION_H #include "qdengine/parser/xml_fwd.h" #include "qdengine/qdcore/qd_named_object.h" #include "qdengine/qdcore/qd_condition_data.h" #include "qdengine/qdcore/qd_condition_object_reference.h" namespace Common { class WriteStream; } namespace QDEngine { //! Условие. /** Структура данных по типам условий. Индексы для доступа к объектам (если они используются в условии) совпадают с индексами для доступа к данным об именах объектов. CONDITION_TRUE CONDITION_FALSE Данные: отсутствуют CONDITION_MOUSE_CLICK Данные: string Объекты: qdGameObject Индескы данных: OBJECT_NAME Имя объекта, по которому надо кликнуть. Если пустое - проверяется клик по объекту, которому принадлежит состояние, в котором выставлено это условие. CONDITION_MOUSE_OBJECT_CLICK Данные: string, string Объекты: qdGameObject, qdGameObject Индескы данных: OBJECT_NAME, MOUSE_OBJECT_NAME Имя объекта, по которому надо кликнуть и имя объекта, который должен быть на мыши. CONDITION_OBJECT_IN_ZONE Данные: string, string Объекты: qdGameObject, qdGridZone Индескы данных: OBJECT_NAME, ZONE_NAME Имя объекта и имя зоны на сетке, в которую он должен попасть. CONDITION_PERSONAGE_WALK_DIRECTION CONDITION_PERSONAGE_STATIC_DIRECTION Данные: string, float[1] Объекты: qdGameObjectMoving Индескы данных: PERSONAGE_NAME, DIRECTION_ANGLE Имя персонажа и угол направления в радианах. Угол задается так же, как и направления в походках (т.е. от направления направо против часовой стрелки) CONDITION_TIMER Данные: float[2], int[2] Индескы данных: TIMER_PERIOD, TIMER_RND Период и текущее время таймера в секундах, вероятность выполнения условия по истечении времени таймера в процентах и текущее состояние условия. CONDITION_MOUSE_DIALOG_CLICK Данные: отсутствуют CONDITION_MINIGAME_STATE Данные: string, string Объекты: qdMiniGame Индескы данных: MINIGAME_NAME, MINIGAME_STATE_NAME Имя мини-игры и имя состояния, в котором она должна находиться для выполнения условия. CONDITION_OBJECT_STATE Данные: string, string Объекты: qdGameObjectAnimated, qdGameObjectState Индескы данных: OBJECT_NAME, OBJECT_STATE_NAME Имя объекта и имя состояния, в котором он должен находиться для выполнения условия. CONDITION_MOUSE_ZONE_CLICK Данные: string Объекты: qdGridZone Индескы данных: CLICK_ZONE_NAME Имя зоны на сетке, в которую надо кликнуть. CONDITION_MOUSE_OBJECT_ZONE_CLICK Данные: string, string Объекты: qdGridZone, qdGameObject Индескы данных: CLICK_ZONE_NAME, MOUSE_OBJECT_NAME Имя зоны на сетке, в которую надо кликнуть и имя объекта, который должен быть на мыши. CONDITION_OBJECT_STATE_WAS_ACTIVATED CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED Данные: string, string Объекты: qdGameObjectAnimated, qdGameObjectState Индескы данных: OBJECT_NAME, OBJECT_STATE_NAME Имя объекта и имя состояния. CONDITION_OBJECT_NOT_IN_STATE см. CONDITION_OBJECT_STATE CONDITION_OBJECTS_DISTANCE Данные: string, string, float Объекты: qdGameObject, qdGameObject Индескы данных: OBJECT_NAME, OBJECT2_NAME, OBJECTS_DISTANCE Имена объектов и расстояние по сетке. CONDITION_PERSONAGE_ACTIVE Данные: string Объекты: qdGameObjectMoving Индескы данных: PERSONAGE_NAME Имя персонажа, который должен быть активным для выполнения условия. CONDITION_OBJECT_STATE_WAITING Данные: string, string Объекты: qdGameObjectAnimated, qdGameObjectState Индескы данных: OBJECT_NAME, OBJECT_STATE_NAME Имя объекта и имя состояния. CONDITION_OBJECT_STATE_ANIMATION_PHASE Данные: string, string, float[2] Объекты: qdGameObjectAnimated, qdGameObjectState Индескы данных: OBJECT_NAME, OBJECT_STATE_NAME, ANIMATION_PHASE Имя объекта, имя состояния и диапазон фазы анимации. CONDITION_OBJECT_PREV_STATE Данные: string, string Объекты: qdGameObjectAnimated, qdGameObjectState Индескы данных: OBJECT_NAME, OBJECT_STATE_NAME Имя объекта и имя состояния. CONDITION_STATE_TIME_GREATER_THAN_VALUE Данные: float Время работы состояния. Объекты: qdGameObjectState CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME Данные: отсутствуют Объекты: qdGameObjectState, qdGameObjectState Состояния, время работы которых сравнивается. CONDITION_STATE_TIME_IN_INTERVAL Данные: float[2] Интервал, в котором должно находиться ремя работы состояния. Объекты: qdGameObjectState CONDITION_COUNTER_GREATER_THAN_VALUE CONDITION_COUNTER_LESS_THAN_VALUE Данные: int Число, с которым сравнивается значение счетчика. Объекты: qdCounter CONDITION_COUNTER_GREATER_THAN_COUNTER Данные: отсутствуют Объекты: qdCounter, qdCounter Счетчики, значения которых сравнивается. CONDITION_COUNTER_IN_INTERVAL Данные: int[2] Интервал, в котором должно находиться значение счетчика. Объекты: qdCounter CONDITION_OBJECT_ON_PERSONAGE_WAY Данные: float[1] Максимальное расстояние между объектам и персонажем по сетке. Объекты: qdGameObjectMoving, qdGameObject CONDITION_KEYPRESS Данные: int[1] vkey кнопки. CONDITION_ANY_PERSONAGE_IN_ZONE Объекты: qdGridZone CONDITION_MOUSE_RIGHT_CLICK Объекты: qdGameObject Индескы данных: OBJECT_NAME Объект, по которому надо кликнуть. Если нулевой - проверяется клик по объекту, которому принадлежит состояние, в котором выставлено это условие. CONDITION_MOUSE_RIGHT_OBJECT_CLICK Объекты: qdGameObject, qdGameObject Индескы данных: OBJECT_NAME, MOUSE_OBJECT_NAME Объект, по которому надо кликнуть и объект, который должен быть на мыши. CONDITION_MOUSE_RIGHT_ZONE_CLICK Объекты: qdGridZone Индескы данных: CLICK_ZONE_NAME Зона на сетке, в которую надо кликнуть. CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK Объекты: qdGridZone, qdGameObject Индескы данных: CLICK_ZONE_NAME, MOUSE_OBJECT_NAME Зона на сетке, в которую надо кликнуть и объект, который должен быть на мыши. CONDITION_OBJECT_HIDDEN Объекты: qdGameObject Объект, который должен быть скрыт CONDITION_MOUSE_HOVER Объекты: qdGameObject Объект, на который наводится мышь CONDITION_MOUSE_OBJECT_HOVER Объекты: qdGameObject, qdGameObject Объект, на который наводится мышь, объект который на мыши CONDITION_MOUSE_HOVER_ZONE Объекты: qdGridZone Зона, на которую наводится мышь CONDITION_MOUSE_OBJECT_HOVER_ZONE Объекты: qdGridZone, qdGameObject Зона, на которую наводится мышь, объект который на мыши CONDITION_MOUSE_CLICK_FAILED CONDITION_MOUSE_OBJECT_CLICK_FAILED CONDITION_MOUSE_CLICK_EVENT //CONDITION_MOUSE_OBJECT_CLICK_EVENT CONDITION_MOUSE_RIGHT_CLICK_EVENT //CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT Данных нет. CONDITION_MOUSE_OBJECT_CLICK_EVENT CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT Объекты: qdGameObject Объект, которым надо кликнуть для выполнения условия. Если нулевй, то достаточно клика любым объектом. CONDITION_MOUSE_STATE_PHRASE_CLICK Объекты: qdGameObjecState Состояние, по фразе которого надо кликнуть. CONDITION_OBJECT_IS_CLOSER Объекты: qdGameObject, qdGameObject, qdGameObject Расстояние от первого объекта до второго должно быть меньше, чем расстояние от первого до третьего. CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE Объекты: qdGameObjectAnimated, int Анимированный объект, который простаивает, и порог времени, который должен быть превышен временем ожидания заданного объекта. CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS Объекты: qdGameObjectAnimated, qdGameObjectAnimated Два объекта, баунды которых пероверяются на пересечение. */ class qdCondition { public: //! Типы условий. enum ConditionType { //! всегда true CONDITION_TRUE, //! всегда false CONDITION_FALSE, //! клик мышью по объекту CONDITION_MOUSE_CLICK, //! клик объектом на мыши по объекту CONDITION_MOUSE_OBJECT_CLICK, //! персонаж или объект в определенном месте сетки CONDITION_OBJECT_IN_ZONE, //! персонаж движется в определенном направлении CONDITION_PERSONAGE_WALK_DIRECTION, // 5 //! персонаж стоит и ориентирован в определенном направлении CONDITION_PERSONAGE_STATIC_DIRECTION, //! условие выпоняется с некоторой периодичностью CONDITION_TIMER, //! клик мышью по фразе в диалоге CONDITION_MOUSE_DIALOG_CLICK, //! мини-игра находится в определенном состоянии CONDITION_MINIGAME_STATE, //! объект находится в определенном состоянии CONDITION_OBJECT_STATE, // 10 //! клик мышью по зоне на сетке сцены CONDITION_MOUSE_ZONE_CLICK, //! клик объектом по зоне на сетке сцены CONDITION_MOUSE_OBJECT_ZONE_CLICK, //! состояние объекта активировалось CONDITION_OBJECT_STATE_WAS_ACTIVATED, //! состояние объекта не активировалось CONDITION_OBJECT_STATE_WAS_NOT_ACTIVATED, //! объект не находится в определенном состоянии CONDITION_OBJECT_NOT_IN_STATE, // 15 //! расстояние по сетке между двумя объектами меньше заданного CONDITION_OBJECTS_DISTANCE, //! персонаж активен CONDITION_PERSONAGE_ACTIVE, //! состояние объекта ждет активации CONDITION_OBJECT_STATE_WAITING, //! состояние в определенной фазе анимации CONDITION_OBJECT_STATE_ANIMATION_PHASE, //! предыдущее состояние объекта CONDITION_OBJECT_PREV_STATE, // 20 //! время работы состояния больше значения CONDITION_STATE_TIME_GREATER_THAN_VALUE, //! время работы одного состояния больше времени работы другого CONDITION_STATE_TIME_GREATER_THAN_STATE_TIME, //! время работы состояния в интервале CONDITION_STATE_TIME_IN_INTERVAL, //! значние счетчика больше числа CONDITION_COUNTER_GREATER_THAN_VALUE, //! значние счетчика меньше числа CONDITION_COUNTER_LESS_THAN_VALUE, // 25 //! значние счетчика больше значения другого счетчика CONDITION_COUNTER_GREATER_THAN_COUNTER, //! значние счетчика в интервале CONDITION_COUNTER_IN_INTERVAL, //! объект на пути персонажа CONDITION_OBJECT_ON_PERSONAGE_WAY, //! кнопка нажата CONDITION_KEYPRESS, //! в зоне хотя бы один персонаж CONDITION_ANY_PERSONAGE_IN_ZONE, // 30 //! правый клик мыши по объекту CONDITION_MOUSE_RIGHT_CLICK, //! правый клик объектом на мыши по объекту CONDITION_MOUSE_RIGHT_OBJECT_CLICK, //! правый клик мышью по зоне на сетке сцены CONDITION_MOUSE_RIGHT_ZONE_CLICK, //! правый клик объектом по зоне на сетке сцены CONDITION_MOUSE_RIGHT_OBJECT_ZONE_CLICK, //! объект скрыт CONDITION_OBJECT_HIDDEN, // 35 //! мышь наведена на объект CONDITION_MOUSE_HOVER, //! мышь наведена на объект, на мыши объект CONDITION_MOUSE_OBJECT_HOVER, //! мышь наведена на зону CONDITION_MOUSE_HOVER_ZONE, //! мышь наведена на зону, на мыши объект CONDITION_MOUSE_OBJECT_HOVER_ZONE, //! неудачный клик мыши CONDITION_MOUSE_CLICK_FAILED, // 40 //! неудачный клик объектом на мыши CONDITION_MOUSE_OBJECT_CLICK_FAILED, //! был клик мыши CONDITION_MOUSE_CLICK_EVENT, //! был клик объектом на мыши CONDITION_MOUSE_OBJECT_CLICK_EVENT, //! был клик правой кнопкой мыши CONDITION_MOUSE_RIGHT_CLICK_EVENT, //! был клик правой кнопкой объектом на мыши CONDITION_MOUSE_RIGHT_OBJECT_CLICK_EVENT, // 45 //! клик по фразе определённого состояния CONDITION_MOUSE_STATE_PHRASE_CLICK, //! расстояние до одного объекта меньше чем до другого CONDITION_OBJECT_IS_CLOSER, //! время простоя больше заданного порога CONDITION_ANIMATED_OBJECT_IDLE_GREATER_THAN_VALUE, //! баунды двух объектов пересекаются CONDITION_ANIMATED_OBJECTS_INTERSECTIONAL_BOUNDS, }; //! Индексы для обращения к данным в условиях. enum ConditionDataIndex { OBJECT_NAME = 0, MOUSE_OBJECT_NAME = 1, ZONE_NAME = 1, DIRECTION_ANGLE = 1, PERSONAGE_NAME = 0, TIMER_PERIOD = 0, TIMER_RND = 1, MINIGAME_NAME = 0, MINIGAME_STATE_NAME = 1, OBJECT_STATE_NAME = 1, CLICK_ZONE_NAME = 0, OBJECT2_NAME = 1, OBJECTS_DISTANCE = 2, ANIMATION_PHASE = 2, STATE_TIME = 2 }; qdCondition(); qdCondition(ConditionType tp); qdCondition(const qdCondition &cnd); ~qdCondition(); qdCondition &operator = (const qdCondition &cnd); ConditionType type() const { return _type; } void set_type(ConditionType tp); static const char *type2str(uint type); bool put_value(int idx, const char *str); bool is_click_condition() const { return (_type == CONDITION_MOUSE_CLICK || _type == CONDITION_MOUSE_DIALOG_CLICK || _type == CONDITION_MOUSE_ZONE_CLICK); } bool is_object_click_condition() const { return (_type == CONDITION_MOUSE_OBJECT_CLICK || _type == CONDITION_MOUSE_OBJECT_ZONE_CLICK); } // val_index - индекс, по которому пропишется значение // в qdConditionDataInt::_data или qdConditionDataFloat::_data bool put_value(int idx, int val, int val_index = 0); bool put_value(int idx, float val, int val_index = 0); bool get_value(int idx, const char *&str) const; bool get_value(int idx, int &val, int val_index = 0) const; bool get_value(int idx, float &val, int val_index = 0) const; bool put_object(int idx, qdNamedObject *obj); const qdNamedObject *get_object(int idx) ; const qdNamedObject *owner() const { return _owner; } void set_owner(const qdNamedObject *p) { _owner = p; } bool load_script(const xml::tag *p); bool save_script(Common::WriteStream &fh, int indent = 0) const; void quant(float dt); //! Загрузка данных из сэйва. bool load_data(Common::SeekableReadStream &fh, int save_version); //! Запись данных в сэйв. bool save_data(Common::WriteStream &fh) const; //! Инициализация условия, вызывается при старте и перезапуске игры. bool init(); bool is_inversed() const { return _is_inversed; } void inverse(bool inverse_mode = true) { _is_inversed = inverse_mode; } bool check(); bool is_in_group() const { return _is_in_group; } void add_group_reference() { _is_in_group = true; } void remove_group_reference() { _is_in_group = false; } static bool successful_click() { return _successful_click; } static bool successful_object_click() { return _successful_object_click; } static void clear_successful_clicks() { _successful_click = _successful_object_click = false; } private: ConditionType _type; const qdNamedObject *_owner = nullptr; typedef Std::vector data_container_t; data_container_t _data; typedef Std::vector objects_container_t; objects_container_t _objects; bool _is_inversed; bool _is_in_group; static bool _successful_click; static bool _successful_object_click; bool init_data(int data_index, qdConditionData::data_t data_type, int data_size = 0) { assert(data_index >= 0 && data_index < (int)_data.size()); _data[data_index].set_type(data_type); if (data_size) _data[data_index].alloc_data(data_size); return true; } }; } // namespace QDEngine #endif // QDENGINE_QDCORE_QD_CONDITION_H