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

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

Такая проблема возникла:

Expression    : fatal error
Function      : CScriptEngine::lua_error
File          : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp
Line          : 73
Description   : <no expression>
Arguments     : LUA error: ...e.r. - life in fear\gamedata\scripts\xr_logic.script:453: attempt to call method 'id' (a nil value)

 

Тут ясно, что вылет происходит при установки схемы. Я сделал вывод в лог текста вызываемой функции printf(), изменив _g.script. В итоге я понял, что во всем виновата схема 'heli_hunter'. Вот более точный лог:

...
! Unknown command:  setup_gulag_and_logic_on_spawn_obj=gar_depo_bandit_st2,_strn_id=253
! Unknown command:  [smart_terrain_gar_depo_bandit]_gulag:_object_setup_online:_obj=gar_depo_bandit_st2_need_setup_logic=true_need_setup_restrictors=true
! Unknown command:  _bp:_enable_scripts:_object_'gar_depo_bandit_st2'_has_NO_external_configuration_file,_using_'misc\gulag_tasks.ltx'
! Unknown command:  DEBUG:_set_scheme:_scheme='heli_hunter'_section='<nil>'
! Unknown command:  DEBUG:_add_to_binder:_scheme='heli_hunter'

FATAL ERROR

[error]Expression    : fatal error
[error]Function      : CScriptEngine::lua_error
[error]File          : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp
[error]Line          : 73
[error]Description   : <no expression>
[error]Arguments     : LUA error: ...e.r. - life in fear\gamedata\scripts\xr_logic.script:453: attempt to call method 'id' (a nil value)

 

 

Но тут не ясно. Схема у меня не изменена. В xr_logic, modules и xr_motivator никаких изменений по поводу этой схемы нет. Добавлены несколько АИ-схем, но в них тоже нет упоминания о 'heli_hunter' (может бы они вызвали какие-то коллизии?). Теперь сижу, гадаю. Отключать схему не хотелось бы, ведь она оригинальная.

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

SkyLoader, сколь можно повторять, что если цитируешь строки лога с указанием номера строки скрипта вызыввшего ошибку - следует хотя бы ее показывать! (тем более если скрипт модифицирован).

Предположительно 453 - строка: local npc_id = npc:id() из функции assign_storage_and_bind ... т.е. на вход функции передан аргумент, который не имеет метода id. По идее такого не должно быть ни в одной из штатных схем.

Думается мне, что и схема 'heli_hunter' тут не виновата, т.к. вызывается после многих других и с теми же самыми аргументами, т.е. если бы об'ект был бы невалидным - то и ошибка бы ранее проявилась бы.

Ну а как отловить? Конечно просмотр строк в логе, выведенные с восстановленным printf дает подспорье, но разработчики позаботились только о малом и не ясно что же за аргумент npc фигурирует в кодах.

1. Перед 'heli_hunter', если смотреть в исходный xr_logic.script подключается 'on_death' (xr_death), и раз эта схема не выявляет ошибку - следует посмотреть в ней что же за аргумент npc задан. Для этого всего то нужно добавить соотв.строку вывода в лог ...

2. Вполне может быть, что между этими схемами что-то еще "портит/подменяет" аргумент. Строки в логе о гулаговых проверках заставляют задуматься, а не тут ли собака зарылась?

3. Ну и ... а если это не до, а после? СтОит добавить строку вывода в лог по выходу из подключения схемы 'heli_hunter', чтобы не грешить на нее и искать далее, т.е. за нею. Может уже 'combat_ignore' будет виновником ...

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

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

Artos, ой, извиняюсь, забыл код строки вылета привести :)

 

1. id выводился нормально за пределами ф-ции.

 

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

 

Кстати, давно еще писал про зависание биндера, видимо из-за этой же проблемы. Биндер больше не зависает. Теперь буду искать, в какой схеме такой ужас происходит. Спасибо за ответ.

 

P.S. Видимо все-таки я такой невезучий, у которого случаются баги и вылеты, которых ни у кого не было.

Изменено пользователем SkyLoader
Ссылка на комментарий

Вроде где то мелькало, но кто знает как называется в движке клиентский класс ящика-инвенторя?

Появилась необходимость зарегистрировать его в class_registrator.script, чтобы отслеживать момент его инициализации.

 

Собственно вот:

cs_register (object_factory, "?CMincer?", "se_inv_box.se_inv_box", "O_INVBOX", "inventory_box")

 

Цель - спавню в одной функции ящик, и сразу пытаюсь спавнить в него вещи. Игра на этом не вылетает но ломается, следовательно нужно эти два процесса растянуть по времени. Таймеры использовать не очень хочется, поэтому хочу через колбеки серверного класса сделать. Может есть менее громоздкий способ определить, что серверный объект моего ящика готов для спавна вещей в него?

 

Игра ЧН 10 патч.

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

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

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

*Shoker*,

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

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

 

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

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

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

 

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

*Shoker*, вспоминаем (если нет соотв. биндера) простейший способ получить клиентский об'ект при спавне по факту его появления в игре (онлайне):

Спавним свой об'ект:

local soObj = alife():create(sSection, vPos, idLv, idGv)

и по уже полученному игровому идентификатору (ID == soObj.id) ставим коллбэк:

if game_graph():vertex(soObj.m_game_vertex_id):level_id() == alife():level_id() then --/ на текущей локации?
  level.client_spawn_manager():add(soObj.id, 65535, Callback_NetSpawn, sSection)
end

- если уверен, что спавнишь на текущую локацию - проверку можно не делать.

Ну и собственно сама функция коллбэка:

function Callback_NetSpawn(uo, idObj, oObj)
  printf("Object="..oObj:name().."~is_ready")
  --/ ... свой код
end

Обязательным условием является выход об'екта в онлайн после его спавна, так что и соотв. логика и/или флажки должны учитываться и при необходимости изменяться/устанавливаться.

По сути, это эквивалент биндеровских 'net_spawn' ...

 

А попытки зарегистрировать недоступный в ТЧ и ЧН клиентский об'ект CInventoryBox - бессмысленны. Может и получишь после извратов "нечто" ... но это уже будет не инвентарным ящиком. :crazy:

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

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

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

malandrinus, спасибо огромное за разбор, этот пост пропустил, может ссылку на него добавить в object_factory?

А так не знаю точно, но если я пытаюсь сразу в созданный объект заспавнить вещь, то игра не виснет, а точнее виснут скрипты, у меня например в ЧН глючит начальный интро-ролик а потом игра вылетает с руганью на отсутствие пстора актёра. Ежели спавнить вещи потом, то всё нормально.

 

Artos, спасибо, я это помню, просто я делаю "динамические" тайники, и у меня все "ящики" спавнятся скопом на всех локациях в момент старта игры и сразу же заполняются. Так что данный вариант не подходит.

 

Жалко что класс не экспортирован, я примерно что то такое где то тут и слышал. В данный момент реализовал таймером заполнение.

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

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

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

*Shoker*, если у тебя завязка по всем локациям, но требуется именно на старте игры - то ничего не мешает и без таймера обойтись.

Спавнишь ящики по событию появления актора в игре, а заполняешь ящики по первому апдейту актора, вот тебе и таймер ...

Хотя странное название "динамические" для "все "ящики" спавнятся скопом на всех локациях в момент старта игры и сразу же заполняются" ... самое место подобному в all.spawn'е.

И стОит разобраться бы с багом "почему подвисают скрипты", дабы не копить ошибки и потом их разгребать.

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

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

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

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

А ломается именно при первой попытке сразу заспавнить вещь в созданный ящик.

 

Спавн ящиков происходит из колбека start_game_callback в_g.script, возможно поэтому такие неприятности, ещё не проверял.

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

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

*Shoker*, зачем же так "грубо"? В момент start_game_callback еще многие скрипты, схемы, конфиги и пр. не инициализированы.

Что мешает подобное делать в первом апдейте актора (см. флажек bCheckStart), что происходит когда все "готово" и только раз при начале игры. Да и других вариантов немало ... Не стОит "лезть в пекло поперек батьки". ;-)

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

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

Прошу совета у опытных скриптеров.

Суть проблемы - погибает квестовый персонаж, заспавненный через скрипт, в офф-лайфе, несмотря на присвоенную секцию Сахарова. В зоне а-лайфа нет никаких проблем - настоящий "Дункан МакКлау", хоть ядерную бомбу на него скидывай - ему хоть бы что. Но стоит уйти на другую локу, как мой непись морозится и выкашивается (если я правильно понимаю) скриптом - remove_zavis.script . Он коротенький, поэтому приведу его полностью -

function remove_obj(obj)
    local npc_id = obj:id()
    if IAmAStalker[obj:clsid()] or IAmAMonster[obj:clsid()] then
      abort("xr_logic: ОБНАРУЖЕН ОБЪЕКТ С ПОВРЕЖДЕННЫМ PSTOR: '%s' БУДЕТ ПРОИЗВЕДЕНА ПОПЫТКА ВОССТАНОВЛЕНИЯ", tostring(obj:name()))      
      
    local npc = level.object_by_id(npc_id)
    if npc then
        local h = hit()
        h.power = 3
        h.impulse = 3
        h.draftsman = npc
        h.direction = vector():set(0,0,0)
        -- h:bone("bip01_spine")
        h.type = hit.fire_wound
        npc:hit(h)
        if obj and IAmAStalker[obj:clsid()] then
            amk.make_suicide(npc)
        end
    end
      -- amk.dump_table(amk.read_stalker_params(npc))
      -- убиваем зависшего
      -- switch_offline(obj)
      -- прибираем трупик
      if obj then
        local npc_name = obj:name()
        alife():release(obj,true)
        if not obj then
          local text1 = "зависший "..npc_name.." id: "..npc_id.." удалён"
          get_console():execute("load ~#I#: pstor_load_all:"..string.format(text1))
        end
        -- return
      end
    end
end

 

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

---

Есть ли возможность сделать исключение в remove_zavis.script на некоторых, нужных мне, неписей, заспавненных через скрипт? Пусть он их "не трогает".

---

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

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

Buusty

А не проще разобраться почему непись зависает и удаляется этим скриптом? Потому как костыль сделать можно, но ты уверен что этот костыль не приведет к вылетам

Freedom

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

Buusty

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

На вход функции передается некий клиентский обект, сужу по примененному сразу же методу obj:id(). Но какого рожна:

а) если это сталкер или монстр - вызывается функция аборт(!), т.е. принудительного прерываниея игры?

б) если игра прерывается абортом - то какого рожна идут далее коды? Наносится некий 'слабеникий' хит, об'ект убивается (npc:kill(npc)) ...

в) в конце концов вообще шедевр "скриптера" - удаляется серверным методом клиентский об'ект(!?): alife():release(obj,true)

Это кто ж писал такое, занимаясь скриптовым садомазохизмом? :fool::crazy: (иных слов нет).

 

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

Как сказал _Призрак_, нужно и искать причины такого неравнодущия скриптов к твоему неписю, т.е. причины зависаний иль еще чего и мотивы, которые и направляют сам об'ект на удаление. Без этого мазать зеленкою болячки можно долго и безрезультативно.

 

Ну а то что непись имеет секцию Сахарова - это не делает его бессмертным именно в оффлайне. Простейшими функциями с ним можно сделать все что угодно (убить/удалить/покалечить/...), ведь в офлайне только смартовые скрипты рулят и к смертям/здоровбю не имеют отношения. Скорее всего именно логика в оффлайне виновата и приводит к зависонам этого непися.

 

В общем пока мало информации. СтОит его как-то пометить и выводить его состояние и похождение в лог - тогда что-то можно сказать.

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

А воообще, если есть и другие подобные приведенной функции коды - удивительно как вообще там у вас неписи по Зоне хотят и игра не валится ... :crazy:

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

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

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

Тут не в том дело "почему он морозится", ведь у большинства игроков (~70%) он сидит у костра и не погибает (и, впоследствии, не убирается уборщиком), а вот у некоторых почему то выкашивается этим скриптом. Здесь вобще рандомом каким-то пахнет. Похоже что наугад выбирается любой сталкер и попадает под раздачу. Это из серии "Погиб сталкер Вася Петров. Кабан. Кордон." СтОит переиграть с последнего сейва и уже погибает какой-нибудь "Ваня Пупкин" и где-нибудь на Янтаре от снорка.

Приходит игрок сдать квест, а квестовика этого может и не быть, или может труп застать...

Почему не гибнет, например Фанат, Волк....Что делает их "неприкасаемыми"? почему, если я спавню непися торговцем, то он стоит до конца игры "истуканчиком" и с ним никогда ничего подобного не происходит. А стОит сталкера скриптом заспавнить, как сразу же и лоторея происходит...

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

P.S. У меня вобще приходила в голову мысль, удалить этого непися принудительно и потом вновь заспавнить через рестриктор, когда ГГ пойдет сдавать ему квест, чтобы наверняка этот непись был на месте в нужное время. Но способ этот не очень мне нравится... Возможно, есть более простой и изящный способ выхода из этой ситуации...

Изменено пользователем Buusty
Ссылка на комментарий

Buusty, поиск "простой и изящной" панацеи от кривых скриптов/логики/... - не предмет данной темы. Тут именно ищется лекарство от "почему он морозится" иль т.п., дабы исправить коды и саму игру, а не "замазать чтобы не видно было косяков" ...

 

Удивляешься, что мол Фанат не гибнет(?) - ну так и делай как с Фанатом, заспавнив его в онлайне, и выпускай инфопоршнем "погулять в Зону" когда тебе понадобилось.

Иль даже спавн своего горемыки привяжи к инфопоршню - "простенько и со вусом". :crazy:

 

Не моддмейкер должен прогибаться под кривыми кодами, а коды подчиняться ему.

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

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

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

Возникла тут пара вопросов, что-то или упустил или забыл наверное...

1. Можно ли из игры, скриптом установить story_id объекта? До этого объект его не имеет.

2. Каким способом можно скриптом опять же, просканировать какие story_id свободны, кроме перебора всех серверных объектов?

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

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

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

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

Zander_driver, напоминаю, что указывать в топике версию игры (если это важно) - очень рекомендуется, дабы не флудить переспрашиваниями и/или недопонятками.

Хотя в вопросе скорее всего очевидно о чем речь, но ... все же напомню, тем более это может быть ключом к ответу на 2-ой вопрос:

К сожалению разработчики перемешали название story_id для разных понятий/значений:

а) story_id - численное значение сюжетного идентификатора, который присваивается об'екту в качестве свойства и запоминается как параметр в нет-пакете об'екта.

Справедливо для всех версий игры (ТЧ/ЧН/ЗП).

 

б) story_id - строковое значение сюжетного идентификатора, который задается в логике (кастомдате) об'екта и запоминается в качестве одноименного параметра в кастомдате об'екта. Обычно регистрируется в story_objects.script.

Справедливо для оригинальных версий игры ЧН и ЗП.

 

в) story_id - строковое значение квестового идентификатора, который соответствует числовому сюжетному идентификатору об'екта и берется из конфигурационного файла game_story_ids.ltx. Используется в основном менеджером заданий и в связанном с ним.

Справедливо для оригинальных версий игры ТЧ и ЧН.

 

1. В игре числовой story_id можно задать в любое время, используя функции работы с нет-пакетами.

Если присваивать story_id в момент спавна об'екта - более ничего не требуется ...

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

 

2. В оригинальной игре получить список (не)занятых числовых story_id невозможно и определить (не)занятость можно только проверкой (не)наличия в игре об'екта с соотв. идентификатором ( se_obj = alife():story_object(story_id) ).

Однако, если приспичило и не хочется заморачиваться на итерациях по всему диапазону доступных об'ектов - можно воспользоваться вариантом самих разработчиков, т.е. создать аналог story_objects.script, в котором и запоминать все появляющиеся и исчезающие 'числовые' идентификаторы по мере спавна/удаления об'ектов.

 

Примечание: Сам движек у себя в игре во всех версиях игры знает и 'помнит' весь список числовых story_id, но как к нему подступиться штатными методами - мне, например, неизвестно ...

Также, story_id созданных уже в игре об'ектов, не попадают в базу движка, а попадают только после перезагрузки. Впрочем, кроме информативной записи в логе при удалении такого "незарегистрированного" идентификатора, это вроде как ни к чему более не приводит.

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

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

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

Здравствуйте.

Требуется помощь опытных скриптологов. Объясняю суть. Написал скрипты зависимости/потребности ГГ от чего либо(например зависимость от воды).

1)Сначала создал скрипт "зависимости":

function test_for_need_kur()
    amk.save_variable("kur",amk.load_variable("kur",0)+1)
    amk.g_start_timer("kur",0,0,5)
    kur_reduce_health()
end

function kur_reduce_health()
    local tmp = amk.load_variable("kur",0)
    if tmp > 96 then
        if db.actor.health > 0 then
            db.actor.health = - 0.1
        end
    end
end

function kur_item(oid, time)
    if alife():object(oid)==nil then
        local tmp = amk.load_variable("kur",0) - time*10
        if tmp < 0 then tmp = 0 end
        amk.save_variable("kur", tmp)
    end
end

2)Далее в amk.script после строки "function __do_timer_action(select_string,params_string)" вписал:

if select_string=="kur" then
azh.test_for_need_kur()
end

3) Затем в amk_mod.script в функции first_run пишу:

    amk.g_start_timer("kur",0,0,5)
end

4) Потом в том же файле после строк

    elseif section=="treasure_item" then
        stype="tr_item"

Пишу:

          elseif section == "voda" then
    stype = "sgr"

 

Собственно описываю, что делают скрипты: сначала через некоторое время у ГГ возникает потребность в воде и через каждые 5 мин. у него отнимается хп. НО, после применение этой самой воды счетчик жажды не сбрасывается, т.е. сколько бы воды я не выпил, у ГГ продолжает действовать жажда и отниматься хп.

Вроде секция

          elseif section == "voda" then
    stype = "sgr"

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

Может я делаю что-то не так?

Изменено пользователем ColR_iT
По компактнее, пожалуйста.
Ссылка на комментарий

Верес, сильно закучерявил свои функции и ... сам же запутался в них.

 

1. Я бы посоветовал давать имена своим функциям и переменным по-возможности более симантически понятными ... оптимизировать/укорачивать можно позже, если потребуется.

2. Запуск твоего таймера происходит, он тикает и даже здоровье отнимает у актора. Однако

с использованием "воды" у тебя полный провал. Если и верна секция твоего предмета "voda", то твое stype = "sgr" - однозначно неверно!

stype в функции check_sleep_item(obj) используется как кусок(!) к строке: "sleep_"..stype и соответственно у тебя стартует таймер с именем "sleep_sgr".

Но(!) в любом случае, как понимаю, у тебя этот таймер должен вызывать функцию kur_item(oid, time), а не нечто с "sgr" ...

Ну а далее, совсем непонятны в этой kur_item что же ты делаешь, т.к. ни аргумента time в нее не передается, и непонятно, должен иль нет быть твой предмет "вода" в это время в игре, т.е. выпивается ли (удален ли из игры).

 

Соответственно исправляй вызов нужной тебе функции, передавай ей на вход нужные и необходимые аргументы.

Если time все же потребен, то без правки амк-функции check_sleep_item тут не обойтись, т.к. она предназначена для передачи в таймер только одного (ID) аргумента.

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

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

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

Столкнулся с одним неприятным багом, скорее всего движковым.

Суть проблемы: иногда свойство stalker_ids.property_enemy принимает значение true (если запрашивать его через property_storage), но при этом метод best_enemy() возвращает nil, даже если выключить enemy_callback (проверку по combat_ignore). Как такое вообще может быть?

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

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

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

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

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

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

Войти

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

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

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

AMK-Team.ru

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