Перейти к контенту

Справочник по функциям и классам


Рекомендуемые сообщения

malandrinus

Все же информация о наличии бага в исходном классе CTime скорее всего ошибочна.

  Аргументы (Показать)

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Функция get_value ничего с объектом не делает, только читает из него данные. Ошибку я увидел сперва безо всякого применения этой функции, а использовал её только потом, чтобы увидеть, что именно происходит.

Кстати, а что такое zone_informer? Не "Zones Editor" часом имеешь в виду? Если так, то у нас в команде его никто не использует, тестеры и подавно. Он даже не включён в код мода.

Изменено пользователем malandrinus
  Полезный утиль (Показать)
Ссылка на комментарий

Однако именно включение данного вызова в код проверки дельты времени в каждый цикл апдейта как раз и дает 100%-ную повторяемость проявления бага.

Вот код, эквивалентный твоему, и которым ловлю баг:

  ловушка на апдейте актора (Показать)
Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

В ТЧ есть функция game_object.invulnerable(), которая не внесена в lua_help. Работает и на чтение, и на изменение - только что проверял.

 

Ссылка на комментарий

Недавно столкнулся с одной неприятной особенностью параметра m_smart_terrain_id, который есть у всех классов, наследуемых от cse_alife_monster_abstract. Я пробовал переделать скрипт smart_terrain.script так, чтобы регистрировать в них эксклюзивных NPC с помощью присвоения m_smart_terrain_id и последующего вызова register_npc из смарта. Появилась куча проблем с двойными регистрациями: несмотря на то, что я непосредственно перед регистрацией в смарт какого-нибудь NPC отключаю ему автопоиск смартов вызовом brain():can_choose_alife_tasks(false), он каким-то образом уже оказывается зарегистрированным в другом смарте ещё до этого вызова. А причина оказалась простой: у NPC, только что заспавненных скриптом, при запросе значения из этого параметра вызывается обновление планировщика brain():update(). Даже если я использую функцию smart_terrain_id() для запроса значения - тот же результат. Пример:

 

  тестовый код для класса se_monster (Показать)
Изменено пользователем Полтергейст
Ссылка на комментарий

Ошибочку обнаружил в описании "Пространство имён level":

  Цитата
bool map_has_object_spot(int <id>, string <тип метки>) -- проверить наличие метки

в действительности возвращает не bool, а 0 или число.

Ссылка на комментарий

Заметил странность при работе с функцией level.vertex_in_direction.

У меня она возвращает переданный ранее в нее вертекс(то есть ни о каком расстоянии по направлению не может быть и речи), если в векторе направления x - отрицательное. Для положительных x работает нормально.

Ссылка на комментарий

Real Wolf, в теме скриптования есть посты на странице 223 в самом начале и пост 4489 про получение левел вертекса по позиции.

В целом - не в тему, хотя там есть пояснение с картинкой. Если в направлении нужного нам лв будет разрыв аи-сетки (камень, дерево, стена и т.п.) то возвратится граничный лв. Прикол в том, что если лв, от которого считаем, и есть граничный, и направление в сторону разрыва, то вернется он сам. Не умеет level.vertex_in_direction перескакивать через пустоту в аи-сетке.

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

Ребят, подскажите плз или дайте ссылку на то, как пользоваться функцией level.add_dialog_to_render(CUIDialogWnd*) (ЗП) нид срочно прикрепить к окну инвентаря элемент, просто создать кастомстатик не выход, так как в любом случае окно инвентаря накладывается поверх кастомстатика элемента

 

Добавлено через 34 мин.:

Разобрался как этой функцией запустить и вывести на экран оконный класс, довольно легко, но это можно сделать и более легкими путями. В общем все равно элемент остается под окном инвентаря, я так понял что можно мне нужный элемент приарттачить(хз как правильно пишется слово:)) к окну инвентаря, но не пойму как это сделать, будьте добры, подскажите плз

Изменено пользователем Viнt@rь
Ссылка на комментарий

В оригинальном ЗП никак не приаттачить к окну. Решение есть - использовать X-Ray Extensions. В нем есть функция получения окна для дальнейшей работы с ним. Но работает эта идея только в полноэкранном режиме. К тому же есть там одна тонкость в получении - получить окно можно только на следующем апгрейде после получения инфопоршня об открытии

Freedom

Ссылка на комментарий
  Viнt@rь писал(а):
В общем все равно элемент остается под окном инвентаря,

А выводить свое окно после открытия инвентаря или на апдейте не пробовали?

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

Обнаружил в игре такой баг (проверял на патче 1.0006): при спавне какого-нибудь объекта скриптом, функция on_register серверного объекта может вызваться дважды. Этим и объясняются "странности" с параметром m_smart_terrain_id: в том примере объект регистрировался в каком-то смарте до второго вызова on_register, если ему вызовом :can_choose_alife_tasks(false) не было запрещено это сделать.

 

 

Обходить баг и выводить в консоль имена объектов, которые вызывают on_register дважды, можно как-то так (пример для se_monster):

  Вывод сообщения + обход бага (Показать)
Ссылка на комментарий
  Цитата
function r_line(ini_file*, string, number, string&, string&); --возвращает полностью "линию" т.е. key1 = value1

 

Возвращает ли эта функция несколько значений которым равен ключ? тоесть

key1 = value1, value2, value3...

 

и еще: параметры number, string&, string& для чего здесь?

 

глядя на пример использования: result, idx, value = ltx:r_line(section,i,"",s) возникает вопрос, что функция возвращает в result и почему передаваемые параметры по типам не совпадают с тем что написано в описании функции, что выше в цитате

Изменено пользователем Viнt@rь
Ссылка на комментарий

Есть такое волшебное средство как поиск...

С этого поста и далее по тексту есть пояснения не только твоего вопроса

  • Нравится 1

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

Классы и функции, используемые для оффлайн передвижения

 

Классы:

 

  Показать

 

Как это всё работает:

 

Каждому NPC соответствует свой объект класса CALifeMonsterBrain (или наследуемого от него CALifeHumanBrain), который можно получить так:

local brain = se_obj:brain()

где se_obj - серверный объект NPC.

Вызов brain:can_choose_alife_tasks(true/false) включает или отключает автоматический выбор точки, в которую NPC пойдёт (подробности ниже).

Далее, можно получить объект класса CALifeMonsterMovementManager, соответствующий данному серверному объекту:

local movement_mgr = brain:movement()

По непонятным причинам вызов movement_mgr:start_type() приводит к зависанию.

Сам по себе этот объект не позволяет управлять передвижением NPC, зато с помощью него можно получить объекты классов CALifeMonsterPatrolPathManager и CALifeMonsterDetailPathManager:

local patrol_mgr = movement_mgr:patrol()
local detail_mgr = movement_mgr:detail()

Класс CALifeMonsterPatrolPathManager позволяет задать имя пути методом path(path_name), а также точку, с которой начинать движение по пути, вызовом start_vertex_index(vertex_index). Однако это ни на что не влияет, т.к. тип пути и другие параметры невозможно установить из-за того, что нижеперечисленные методы (не важно, с аргументами или без) просто зависают при вызове и вызывают вылеты "Error in error handling" или "C stack overflow":

 

  Показать

 

Реально же управлять оффлайн-передвижением позволяют классы CALifeMonsterDetailPathManager и CALifeSmartTerrainTask. Чтобы послать NPC в заданную точку пути, необходимо сначала создать объект класса CALifeSmartTerrainTask:

local my_task = CALifeSmartTerrainTask(path_name, point_index)

где path_name - имя пути, point_index - индекс точки пути. В ТЧ объект этого класса не может быть создан для произвольной точки, не привязанной к какому-либо пути. Чтобы узнать положение уже созданного объекта CALifeSmartTerrainTask в пространстве, можно использовать значения, возвращаемые при вызове level_vertex_id(), position() и game_vertex_id().

Далее нужно установить эту точку для NPC в качестве целевой. Это делается методом target() класса CALifeMonsterDetailPathManager:

detail_mgr:target(my_task)

В lua_help описаны ещё 2 варианта использования этого метода:

  Цитата
function target(const number&, const number&, const vector&);

function target(const number&);

Если в первом требуется передать game_vertex_id, level_vertex_id и координаты точки, то непонятно, в каком порядке передавать game_vertex_id и level_vertex_id. В каком бы порядке я их не передавал, игра вываливалась c ошибкой "There is no proper graph point neighbour".

Во втором непонятно, что за число туда передавать. Возможно это game_vertex_id, я не проверял.

Далее, метод completed() возвращает true, если NPC дошёл до точки, иначе false. А вот с методом failed() не совсем понятно. Нередко он возвращает true тогда, когда completed() тоже возвращает true.

Метод actual() возвращает true, если completed() и failed() возвращают false.

Метод speed () недоступен из-за опечатки, т.к. в конце его имени стоит символ табуляции. Судя по названию, должен возвращать скорость передвижения.

 

Теперь подробности о том, как всё это работает.

Оффлайн-передвижение в оригинальной игре завязано на smart_terrain (или просто "смарты") - объектах класса se_smart_terrain, наследуемого от cse_alife_smart_zone. У каждого серверного объекта NPC (людей или зверюшек) есть свойство m_smart_terrain_id - id смарта, в котором прописан NPC. У каждого смарта есть метод task(), который возвращает объект класса CALifeSmartTerrainTask.

 

Обновление оффлайн-передвижения происходит при вызове метода se_obj:brain():update(), где se_obj - серверный объект NPC. Также он вызывается движком при вызове se_obj:update(). Стоит отметить, что se_obj:update() периодически вызывается движком для всех NPC, а вот вызывать его искусственно (например, из биндера клиентского объекта) не стоит, будут ошибки "There is no proper graph point neighbour".

 

Алгоритм его работы примерно таков:

 

  Показать

 

 

Вот вроде бы и всё. Непонятно, зачем разрабы оставили этот алгоритм в самом движке, когда проще было бы делать всё вышеописанное скриптами. В ТЧ в оригинальной игре автовыбор смартов всегда включен, поэтому если вам нужно послать NPC в какую-то заданную точку (например, перевести через уровень), то автовыбор надо отключать, чтобы не возиться с созданием временных smart_terrain.

  • Нравится 2
  • Полезно 1
Ссылка на комментарий

Товарищи исследователи, может кто подскажет решение задачи. Есть точка (vector) и направление (vector) от неё, для моего случая это актор целящийся куда-либо из оружия. Хочется получить точку прицела на геометрии уровня/объекта, или указания что ничего нет по курсу.

Сойдут любые изощреные методы, включая вызов методов интефейсов Direct3D, работа с буфером вертексов или рендером движка. В теории должен быть самый легальный метод для частного случая актора, ведь движок имеет возможность показывать дистанцию до цели. Но вдруг есть и универсальный метод?

 

Типичную дистанцию отсечки, и косвенно через неё точку выцеливания можно посчитать так (псевдо-код):

g_hud := GetProcAddr ('xr_3da.exe', '?g_hud@@3PAVCCustomHUD@@A');
table := g_hud [$0034]; // + 52 byte
target_id := table[$0000]; // DWORD if game object
target_dist := table[$0004]; // float32
// lua code:
point = device().cam_pos
dir = device().cam_dir
dir:mul(target_dist)
point:add(dir)

Изменено пользователем alpet

Плавайте поездами аэрофлота!

Ссылка на комментарий

В таблице экспорта xr_3da.exe есть метод RayPick. Вот сигнатура:

int CObjectSpace::RayPick(CObjectSpace *this, _vector3<float> *start, _vector3<float> *dir, float range, collide::rq_target tgt, collide::rq_result *R, CObject *ignore_object)

Назначение аргументов, в целом, очевидно: start - стартовая точка, dir - направление трассировки (нормализованный вектор), range - диапазон трассировки. ignore_object - игнорируемый при трассировке объект, tgt - флаги геометрии:

 

enum collide::rq_target
{
rqtNone = 0x0, - не определять ничего
rqtObject = 0x1, - определять динамические объекты
rqtStatic = 0x2, - определять статическую геометрию
rqtShape = 0x4,
rqtObstacle = 0x8,
rqtBoth = 0x3,
rqtDyn = 0xD,
};

Результат доступен через R, там будет лежать объект типа collide::rq_result:

 

struct collide::rq_result
{
CObject *O;
float range;
int element;
};

В случае статической геометрии объект O будет пустой. Если нужно получить больше информации по статической геометрии, можно поковырять методы CDB::COLLIDER.

Если стоит задача работать с трассировкой луча из скриптов, можно посмотреть xray-extensions. В одной из последних ревизий malandrinus экспортировал RayPick в скрипты.

Изменено пользователем KD87
  • Нравится 2
Ссылка на комментарий

Спасибо! То что нужно. Кстати может разработчики движка ещё предусмотрели, как быстро определить статус точки indoor / outdoor (в смысле в здании или на улице)?

Плавайте поездами аэрофлота!

Ссылка на комментарий

alpet, В игре это делается путём постоянного рейтрессинга. Если в направлении дождя видишь небо (т.е. ничего не видишь), значит на улице. Это легко проверить. Во время дождя, если в помещении пройти под дырочкой в крыше, то сразу зашумит, как будто стоишь на улице =)

  Полезный утиль (Показать)
Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
  • Куратор(ы) темы:

×
×
  • Создать...