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

Скриптование


Svoboда

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

Artos,

проверка типа:if type(object) == 'userdata' and type(object.id) ~= 'nil' then ... - может привести к фатальной ошибке

Если точнее, то в этой строке часть type(object) == 'userdata' ошибки не вызовет, поскольку это проверка объекта Lua и обращения к движковому объекту нет, а вот вторая часть type(object.id) ~= 'nil', или точнее вот это object.id, как раз и вызовет безголовый вылет, поскольку здесь идёт обращение к свойству id, а при этом делается попытка прочитать его из движкового объекта, которого уже нет.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Gun12,

Если движкового объекта уже нет, то проверка type(object) == 'userdata' возвратит false, поэтому до второй части - and type(object.id) ~= 'nil' - даже не дойдёт.

Ты не прав, это всё ещё 'userdata', но это именно объект Lua. В этом объекте хранится указатель на собственно движковый объект, и вот по этому указателю уже ничего нет.

 

Проверь эту ситуацию сам. Запомни где-то ссылку скажем на серверный объект аптечки из инвентаря ГГ, потом аптечку съешь, потом проверь свойства этого объекта и что с ним можно и что нельзя делать.

 

Кстати, я в очередной раз встречаю некоторое непонимание разницы между ссылкой и самим значением. Имя переменной (в примере выше object) - это фактически ссылка. У ссылки типа нет, тип есть у значения. Даже неинициализированная ссылка на самом деле имеет значение. Это nil. Ещё раз: nil - это с точки зрения Lua не отсутствие значения, а специальное значение, которое в частности присваивается ссылке по умолчанию. Соответственно, проверяя тип переменной, мы на самом деле проверяем тип того, на что она ссылается. Ссылается на nil - получаем строку "nil".

Теперь к чему это всё. Вот ты сохранил ссылку на объект. Пока ты эту ссылку не перепишешь другим объектом, с этим объектом ничего не сделается и в том числе не изменится его тип. Lua попросту не умеет менять тип значения. Тип не меняется, просто ссылку можно переназначить на объект другого типа. Но в этом случае мы договорились, что мы ссылку не трогаем. Поэтому тип не изменится, в частности не станет nil, поскольку, как я уже сказал, для этого надо явно переписать ссылку специальным значением с типом "nil".

 

Так что в примере выше всё будет плохо. Первая проверка сработает, на второй будет вылет.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Zander_driver,

В одной строке проверяете и сам объект, и его секцию. А если никакого костюма не надето? объект = nil, и тут же произойдет попытка получить nil:section() для следующей проверки.

Не так. По правилам языка, в конструкции

if obj and obj:do_something() then ...

вторая проверка будет проверяться только если сработает первая.

 

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

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*,

смотри здесь. В конце поста таблица с именами.

Вообще-то странно, что игра виснет. По идее, сразу после создания ящика в него можно безопасно спавнить.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

abramcumner,

Потому что проблема с сидом совершенно в другом: сид не находится в реестре сидов. А не находится, потому что задаешь его после регистрации

Перехвати событие on_before_register и установи сид там.

Если используешь последние наработки с событиями, то сделать это просто.

 

Ну или переключить онлайн/оффлайн.

К сожалению, ничего из указанного не поможет. SID не пропишется в глобальный список до следующей загрузки игры или перехода на другой уровень. Эту проблему можно решить только правками движка. Функцию для ТЧ, которая прописывает объекту SID с регистрацией, я уже сделал, при ближайшем апдейте она будет доступна.

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

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

abramcumner,

Попробуй на досуге.

Зачем, я тебе верю. Я в своё время искал событие, предшествующее регистрации в реестре сидов, но выходит недостаточно внимательно. Впрочем, использовать функцию думается всё равно удобнее.

 

Собственно on_before_register не зря так назван.

Если поглядеть это место в коде, то там много чего регистрируется, не только sid-ы. Смарты регистрируются, родительские объекты, присоединёные инвентарные, объект прописывается на апдейты и в алайфе и ещё что-то непонятное.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Callisto,

Объясните мне пожалуйста (желательно на пальцах), как с помощью AddDialogToRender вывести текстуру на экран и чтоб она была там постоянно. (ТЧ)

в справочнике есть статья. Там частично об этом.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Struck,

нужно получить точный(!) clsid оружия из которого было произведено убийство

Вряд ли это реализуемо с той абсолютной точностью, как ты хочешь. Смерть в движке - это финал целой цепочки событий, по сути моделирование реальной ситуации. От события к событию передаётся не вся информация, а в скриптовую часть передаётся и того меньше. Даже в колбеке на хит движок не передаёт информации об оружии по той простой причине, что хит мог и не быть вызван оружием. А смерть в свою очередь вызывается не хитом, а его последствием, падением здоровья ниже нуля. Сам движок к моменту смерти уже точно не знает, от какого оружия погиб перс, только хранит виновника гибели.

 

Так что ничего лучше описанного Artos-ом алгоритма с активным стволом пока нет, и скорее всего не будет. С гранатами можно попытаться приблизительно определить: вести учёт всех гранат, кидаемых всеми неписями и игроком (тоже непростая задача), по типу урона определять, что это была граната и для виновника гибели использовать в этом случае не активный ствол, который непись/актор мог уже сменить, а последнюю кинутую гранату. Уродливо, громоздко, всё равно неточно, но мне ничего другого в голову не приходит.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Struck,

Мне нужно отследить факт того что объект мы подняли с земли.

Не думаю, что есть простое решение. К моменту колбека на передачу потеряна уже вся информация о предыдущем владельце, причём и на серверной и на клиентской стороне. Напрашиваются всякие мерзкие варианты со слежением за владельцем для всех объектов. Для этого надо с начала загрузки сейва следить за всеми событиями передачи, тогда можно сказать точно, у кого был объект. В общем-то это реализуемо, видел подобное в пределах инвентаря, когда надо было определять, где был объект: в слоте, рюкзаке, на поясе. Однако, при такой реализации будут и проблемы, к примеру с ящиками, для которых нет колбека на получение предмета. Придётся также следить за потерей предметов. Но как тогда быть со спавном прямо в ящики? В общем морока ещё та.

 

 

Zander_driver,

Использую данный дебаг-модуль в разработке своего мода. ...

периодически стали происходить вылеты при синхронизации.

Напрашивается вывод о проблемах с памятью: фрагментация или просто исчерпание. Могу предложить просто чистить лог при старте нового сейва командой

get_console():execute("clear_log")

При этом всё, что ушло в альтернативный лог, там останется. Да и вообще, обычно не так уж интересно, что происходило до загрузки текущего сейва.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos,

при передаче от одного к другому иль взятии из ящика - предмет на период в пару апдейтов становится бесхозным и т.о. актор иль НПС всегда обретают именно бесхозные предметы.

Это не так. Процесс смены владельца является мгновенным, если рассматривать его по отдельности для клиентской или серверной стороны. Т.е. к примеру после выполнения функции transfer_item на серверной стороне владелец уже сменился. Другое дело, что в течении упомянутых нескольких апдейтов имеется рассинхронизация с владельцем на клиентской стороне. Тем не менее, бесхозным предмет не становится ни на сервере, ни на клиентской стороне. К моменту получения колбека на передачу этой рассинхронизации уже нет.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Добавлю от себя к дискуссии по окнам. Я лично столкнулся с определённой проблемой, которая заключается в том, что не всегда удаётся определить родительское окно для данного. Точнее, не всегда удаётся его сохранить. Поскольку штатных методов для определения родительского окна нет, то его приходится хранить от момента прикрепления к нему дочернего до отсоединения. Уже не помню подробностей, но в ряде случаев по так и не выясненным причинам ссылку на родительское окно не удавалось сохранить. Доходило до совсем уж мистических вещей, а а итоге всё заканчивалось вылетом или лишним неудаляемым окном при следующей перезагрузке. Помучившись, я пришёл к тому, что добавил в класс окна метод DetachFromParent, который позволяет скрипту не знать родительское окно при операции отсоединения.

 

Также могу сказать, что есть не один вариант решения задачи с добавлением элементов на движковые диалоги. Варианты различаются: в какой момент добавлять, в какой момент удалять, в какой момент создавать и физически удалять добавляемое окно.

 

Можно попытаться создать добавляемое окно один раз и до конца игры. Вопрос, когда именно делать то и другое. Вопрос с созданием в сущности не так и важен, это можно попросту сделать при первом использовании, используя функцию в таком стиле:

local added_wnd
local function get_my_wnd()
added_wnd = added_wnd or create_my_wnd()
end

потом надо везде получать это окно только с помощью этой функции, и проблем не будет. Однако вопрос с удалением уже не так тривиален. К какому из событий игры привязаться, чтобы оно произошло с гарантией? На самом деле, есть куча сценариев, когда ни один из вариантов не является в полной мере надёжным. На мой взгляд метод биндера актора ~finalaze - самый подходящий, поскольку срабатывает при любом штатном сценарии завершения игры. Одна только проблема, иногда удалением в нём по невыясненным причинам даёт сбой.

 

Другой вариант, если присоединяемое окно - не банальный статик, а окно на основе скриптового класса, то можно попытаться отсоединить его в его же собственном методе ~finalize. Надо только убедиться, что он вызывается, а для этого надо ненароком не сохранить ссылку на себя в этом окне, чтобы сработал уборщик мусора.

 

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

 

Если окно создаётся один раз, то в этом случае вопрос с моментом присоединения тоже на самом деле неоднозначный. Как и в случае с физическим созданием я могу решить присоединить один раз и до конца игры. Всегда ли это срабатывает, уже не помню. А можно присоединять при открытии диалога и отсоединять при закрытии. В этом случае, как и для создания, важно, чтобы открытие/закрытие всегда срабатывало парой. Вот с этим тоже есть проблема. Опять же не помню подробностей, но для какого-то из движковых диалогов извещение об открытии/закрытии срабатывает нестабильно, поэтому насколько это подходящий вариант надо решать по ситуации.

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos,

в том-то и дело, что сам ~finalize срабатывал, однако вылетало при удалении окна, вызванном из него. При этом, удаление из иного места в том случае работало нормально. Впрочем, тогда системы так и не выяснил, посему достоверность информации неполная. Я могу предположить, что проблема с ~finalizeв том, что это метод, вызываемый при работе сборщика мусора, а для глобальных объектов типа актора сборщик срабатывает не во время игры, а где-то между завершением и загрузкой. Насколько в этот момент можно заниматься оконными операциями и вообще чем-то, сказать сложно.

С этой точки зрения никакой иной объект не имеет особенных преимуществ перед ~finalize биндера актора, поскольку все они окончательно удаляются в одно и тоже время.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos, обновления актора если и связаны с FPS рендера, то опосредованно, и уж точно их частота не одинаковая. Это совершенно точно. Более того, рендер и все его дела, в том числе и обновления с независимой частотой, как раз происходят в отдельном потоке Windows. Это в сущности единственный многопоточный момент в движке - отдельный поток для рендера.

 

Что же касается апдейтов актора и их связи с частотой апдейтов level.add_call. Я давно не занимался этими измерениями, но смутно помню, что частота апдейтов актора может быть равна или меньше частоте вызовов от level.add_call. Вроде как на старом компьютере и под патчем 1.0004 апдейты шли медленней, а сейчас (весьма быстрая машина и 1.0006) вроде как равны. Кроме того, частота апдейтов актора вообще говоря подчиняется общему правилу для апдейтов всех объектов, т.е. чем дальше от актора, тем медленней. Соответственно актор и его инвентарь обновляются с одной и той же, максимальной, частотой.

 

И более определённо я могу сказать насчёт природы вызовов level.add_call и также колбека fastcall. Они вызываются с одинаковой частотой и, насколько я знаю, эта частота просчёта игровой физики. Есть основания думать, что оба этих вызова исходно предназначались для скриптовой обвязки управления физическими объектами.

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

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos,

измерения я проводил года четыре назад. С тех пор сменилось несколько поколений компьютеров, и мне сейчас физически не воспроизвести те условия. В то время слайдшоу на ТЧ у меня начиналось при средненьких параметрах динамики и разрешении 1024х768. Сейчас я даже на ЧН/ЗП не могу обеспечить просадку FPS до заметно низких значений ни на каком разрешении экрана при самых выкрученных настройках. Или может имело значение, что тогда у меня был однопроцессорный компьютер. Я не знаю точно, чтобы узнать, надо лезть в движок и разбираться, как синхронизируются отрисовка кадров, такты просчёта физики и обновления игровой логики.

 

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

 

Что касается того, что fastcall и add_call связаны с физикой движка. Это можно понять по внутренним названиям функций и классов.

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Daemonion,

Я пытался в течение многих месяцев сделать так, чтобы стереозвук в Тени Чернобыля работал бы должным образом.

 

Как правило, игровой движок должен принимать моно файлы с при креплениями "_l" и "_r" и применять их для правого и левого каналов, чтобы получит стероеэффект.

 

Мои тесты показали, неоднократно, что движок не способен сделать это.

 

Первое. Движок на самом деле не может играть стереозвук по-настоящему. Файлы с именами "_l" и "_r" читаются только в отдельных случаях: музыка в меню, саундтрек уровня, видеоролики. Однако, даже в этом случае движок лишь имитирует стерео, играя звук из точек слева и справа от актора. Таким образом, каналы в любом случае смешиваются. Это можно заметить, если сделать каналы существенно различными, к примеру взять для музыки меню две совершенно разные мелодии.

 

Второе. Чтобы звуковая схема в sr_sound2d.script играла стереозвук надо в секции логики для этой схемы поставить параметр stereo = 1. Тогда только и будут читаться файлы обоих каналов.

 

Третье. Звуковая схема в sr_sound2d.script пытается имитировать стереозвук таким же образом, как это делается для музыки в главном меню и видеороликов, но почему-то делает это не совсем так, возможно просто ошибочно. Для проигрывания стереозвука там делается так:

 

self.snd_obj_l:play_at_pos (actor, pos_l, d / 1000.0, sound_object.s3d)

self.snd_obj_r:play_at_pos (actor, pos_r, d / 1000.0, sound_object.s3d)

В то время как сам движок использует sound_object.s2d

 

В итоге оба канала практически неразличимо смешиваются. Чтобы имитировать движковое поведение более точно и уменьшить смешивание надо сделать следующее:

1. Эти две строки в функции action_sound2d:play_sounds заменить на

self.snd_obj_l:play_at_pos (actor, vector():set(-0.5,0.0,0.3), d / 1000.0, sound_object.s2d)

self.snd_obj_r:play_at_pos (actor, vector():set( 0.5,0.0,0.3), d / 1000.0, sound_object.s2d)

 

2. В функции action_sound2d:update убрать фрагмент

if self.st.stereo == true then
 ....
end

Если этого не сделать, то звук будет сразу обрываться.

 

После этих изменений и добавления параметра stereo = 1 звук будет играться практически также, как в главном меню. Как я говорил, определённое смешивание каналов будет присутствовать всё равно.

 

First, the engine can't really play stereo. It automatically reads separate channels in "_l" and "_r" files only for the main menu music, level soundtrack, and videotutorials. Even in this case stereo is just an imitation. The engine plays two sounds from points to the left and to the right from the actor, so two sounds are somehow mixed. You can notice that if you will take for two channels two completely differents tunes.

 

Second. To make the scheme from sr_sound2d.script play stereo, one needs to add stereo = 1 parameter into the logic section for this scheme.

 

Third, the scheme from sr_sound2d.script tryes to imitate playing stereo the same way as the engine does, but with a little difference (and maybe just incorrectly). It plays two channels using this syntaxis:

 

self.snd_obj_l:play_at_pos (actor, pos_l, d / 1000.0, sound_object.s3d)

self.snd_obj_r:play_at_pos (actor, pos_r, d / 1000.0, sound_object.s3d)

 

But the engine internally uses the constant value equivalent to the sound_object.s2d

 

As a result, both channels are mixed almost completely. So, to imitate, what engine does in the main menu, one needs to do the following:

 

1. Replace these two lines in the function action_sound2d:play_sounds with

 

self.snd_obj_l:play_at_pos (actor, vector():set(-0.5,0.0,0.3), d / 1000.0, sound_object.s2d)

self.snd_obj_r:play_at_pos (actor, vector():set( 0.5,0.0,0.3), d / 1000.0, sound_object.s2d)

 

That will make mixing less noticable

 

2. In the function action_sound2d:update remove or comment out the fragment

if self.st.stereo == true then
 ....
end

 

If not do so, sound will stop shortly after beginning.

 

After that (and don't forget about stereo = 1 in a logic section) stereo will play the same way as it plays in the main menu. Again, there will be some channels mixing anyway.

 

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos, при чтении параметра функцией r_bool, true вернётся при любом значении из набора: "true", "yes", "on", "1". Соответственно, false при всех остальных значениях.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos,

к сожалению, быстрое сохранение так не отловить.

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Shoker,

Так при чём здесь анимации? Тебе кости надо скрывать/показывать. Вот только настраивать визуалы всех неписей - работёнка та ещё.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Shoker,

а модифицировать движок тоже не представляется возможным.

эм.. Религия не позволяет? =) Для ТЧ уже есть такие возможности. Не помню только, делал их для оружия или для любого объекта. Однако, при желании эту правку можно откопать и задействовать.

 

+ при скрытии костей ведь геометрия тоже пропадёт и в теле НПС будет дырка, а анимацией это эту дырку можно "сшить"

Теоретически да, если движок поддерживает не скелетную анимацию, в чём я не уверен. По моему не поддерживает. Чисто же движением костей ты такого эффекта не добьёшься.

 

Со скрытием костей же всё просто. Одну кость скрыть, другую показать (которая дыру заткнёт),

 

Хотя это всё конечно в теории. На практике придётся менять все стопятьсот моделей сталкеров. Вот поэтому такие фишки обычно присутствуют в играх, где тела неписей отдельно, а одежда отдельно. В движке третьего фола к примеру.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение

Artos,

 

ну если уж уважаемые конторы, типа Беседки, озаботились созданием расчленёнки, то почему бы и нем не побеседовать на эту тему? =)

 

Вообще конечно задачу можно решить по-разному. Можно было бы попытаться что-то покрутить с разрушаемыми объектами. Т.е. подменить объект при смерти на разрушаемый с визуалом сталкера. Но тогда пропадёт инвентарь.

 

Если же сформулировать решение с костями полностью. Мы в этом случае естественно имитируем процесс. Для решения общей задачи надо решить две подзадачи:

1. Надо убрать оторванную конечность. Это как раз и решается с помощью костей. Кость руки, к примеру, скрывается, а на её месте показывается кость с обрубком.

2. Надо создать отдельный объект конечности на уровне. Это естественно уже к костям отношения не имеет.

 

P.S.: хотя лично мне эта фишка с расчленёнкой всегда казалась сомнительной

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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