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

Вылеты без логов - в чём причины и как с ними бороться


Полтергейст

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

(изменено)

Если вы столкунулись с вылетом без лога, постарайтесь вспомнить следующее:
1. Что изменяли в последний раз
2. Во время чего вылет произошёл
3. На какой локации
4. Случайно ли он проявляется или только при приближении к определённому месту/объекту
5. Попробуйте отследить имя последнего перешедшего в онлайн объекта
6. Попробуйте поискать в своих правках ошибки, подходящие под нижеперечисленную классификацию.

Известные причины вылетов без лога:


1. Ошибка в вызове функции из диалога: после имени функции скобки писать не нужно.
При таком написании будет вылет без лога:
<action>file.func()</action>
Пример правильного написания:
<action>file.func</action>
(file - имя файла скрипта, func - имя функции)
Во втором случае вылета не будет даже если функции file.func не существует, НО это справедливо только для тега action.
В теге precondition вызов несуществующей функции
<precondition>file.func</precondition>
приведёт к вылету без лога.

2. Пустые значения в конфигах. Вылет будет, если оставить значение какого-либо параметра, считываемого движком, пустым. Например, если в конфиге оружия оставить строку такого вида:
inv_name =

3. Попытка прописать несуществующие кости модели в некоторых параметрах. Например, в grenade_bone для оружия. Тут, думаю, всё ясно.

4. Попытка прописать спавн несуществующего предмета в профиль NPC (файлы character_desc_*.xml). Вылет без лога будет, если в секции spawn (тег supplies) прописать название несуществующей секции.

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

6. Партиклы. Вылеты могут быть, если задать слишком высокие параметры при редактровании партикла. Также вылет может случиться, если в данный момент отыгрывается слишком много партиклов. Например, такая ситуация может быть, если в онлайне слишком много аномалий и/или артефактов.

7. Нельзя прописывать наличие подствольника оружию, в классе которого он не предусмотрен. Например, для класса CWeaponLR300 (имя скриптового сета - WP_LR300).




1. Неправильный тип данных
Такое случается при попытке чтения (из пакета или ltx-файла) одного типа данных функциями, предназначеными для другого.
Пример: если движок запросил bool-значение (true или false), а вместо него получил nil, число или строку, то игра вылетит с пустым логом.
Также не следует указывать аргументы при вызове движковых функций, не принимающих никаких аргументов.

2. Неправильное использование класса net_packet()
По сути, это частный случай первого пункта.
При сохранении - может возникнуть при попытке сохранить nil-значение с помощью функции для сохранения числа, строки или чего-то ещё.
При загрузке - важно не перепутать написание. В функциях чтения аргументы указывать нельзя.
Пример неправильного написания:

packet:r_stringZ(self.wounded)

Пример правильного написания:

self.wounded = packet:r_stringZ()

3. "Самоудаление" объекта. Тут нужно просто запомнить, что вызывать alife():release(self, true) из методов класса самого объекта нельзя, если эти методы вызываются движком. К примеру, есть у нас сталкер и нам нужно его удалить. И если вызов alife():release(self, true) окажется в любом из методов класса se_stalker, вызываемых симуляцией, то случится вылет без лога. То же самое касается всех остальных объектов, у которых перегружен серверный класс.

Обойти этот баг можно с помощью специальной таблицы объектов "к удалению", удаляемых при каждом обновлении игрока.
В bind_stalker.script пишем следующее:

objs_to_remove = {}
--' Таблица удаляемых объектов
--' Формат: objs_to_remove[se_obj.id] = se_obj

function actor_binder:update(delta)
...
--' Удаление
for id, se_obj in pairs(objs_to_remove) do
    alife():release(se_obj, true)
end
objs_to_remove = {}
...
end


4. Если игра вылетает без лога ещё до главного меню, нужно искать ошибки в скриптах, которые прописаны в параметрах class_registrators, game_type_clsid_factory и ui_type_clsid_factory в конфиге script.ltx. Вылет происходит даже при ошибках синтаксиса в этих скриптах.

5. Неправильные операции с действиями планировщиков (action_planner)
Если при добавлении какого-то действия в планировщик, получаемый методом motivation_action_manager, добавить такое условие

action:add_precondition(world_property, stalker_ids.property_in_anomaly)
то получим вылет с пустым логом. Такая ошибка возникает из-за вложенности планировщиков. "Внутренние" планировщики (в таблице stalker_ids они обозначены как константы с именами, в которых есть слово "planner") для скриптеров доступны только как обычные действия, а не как планировщики, поскольку функции cast_action_to_planner и cast_planner_to_action были вырезаны, хоть и упоминаются в lua_help. Некоторые свойства, номера которых есть в таблице stalker_ids, для скриптов тоже недоступны, поэтому добавлять их в качестве условий тоже нельзя.

 

При создании действий (action_base) нужно прописывать им такие условия, чтобы каждому набору условий соответствовало только одно действие, иначе могут быть вылеты или просто глючное поведение NPC. Еще одной причиной вылета могут быть "тупики" - тот случай, когда есть только одно действие, способное в данный момет изменить какое-то свойство (свойство, которое задается методом add_effect), но его выполнение невозможно из-за заданных условий.

6. Переполнение стека. Чаще всего причина таких вылетов - вызов каких-то функций, которые зависают. После нескольких таких вызовов игра вываливается с ошибкой "C stack overflow", указывающей на произвольный скрипт с любым номером строки, хотя иногда бывают и безлоговые вылеты.  Например, вызов метода actual из планировщика motivation_action_manager может приводить к таким зависаниям, хоть и не при каждом вызове.

7. При попытке использования функций cse_alife_smart_zone.register_npc() и cse_alife_smart_zone.unregister_npc() появляются "плавающие" (через раз) вылеты. В смартах вызовы этих функций вырезаны разработчиками и не используются, но если вдруг вам захочется поэксперементировать с ними, не забывайте о их глючности.

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

9. В некоторых случаях вылет без лога происходит при использовании функции wounded(bool) для клиентских объектов (game_object). Чтобы этого не происходило, не следует вызывать её слишком рано, например, из функции net_spawn(...). Также не следует пытаться менять состояние раненности мёртвым NPC.

10. Вылет без лога случается, если установить состояние тела равным move.crouch и ментальное состояние anim.free. Например, вот такой код

--' npc - game_object
npc:set_mental_state(anim.free)
npc:set_body_state(move.crouch)
вызовет вылет без лога. При установке состояний через state_mgr от оригинальной игры такого вылета не может произойти (установка такой комбинации заблокирована), но если устанавливать состояние напрямую (как показано выше), то вылет будет.

11. Нельзя прописывать недопустимые соответствия серверных и клиентских классов в class_registrator.script. Это может вызвать вылеты без лога, зависания и порчу сохранений. В некоторых случаях могут быть вылеты с логом, в котором упоминаются имена несуществующих секций (в т.ч. содержащие недопустимые символы).

12. Вылет при поытке вызвать level.object_by_id(id), где id > 65535. Подобный вылет возможен и для alife():object(id).

 

 

13. Иногда может происходить вылет "Abnormal program termination" (автосохранение при этом оставалось рабочим), предположительно из-за большого количества NPC. У меня такой вылет происходил  при переходе с Радара на другую локацию, перед этим на Радаре было заспавнено очень много зомби (около 100). По этому вылету пока что могу посоветовать только уменьшение количества респавна.




Конкретные примеры (вырезки кода, вызывающие вылеты) и советы по устранению вылетов приветствуются.

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




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

Изменено пользователем Полтергейст
исправлено и дополнено описание вылетов action_planner

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


Ссылка на сообщение
(изменено)
Что то не очень как то понятно:по моему опыту вылет при удалении\дропе может быть разве что в том случае, если движок "потерял" серверную юзердату удаляемого объекта

Если объект удаляет сам себя (функция удаления вызывается из методов его класса), то вылет будет без лога. Проверено на функциях can_switch_* вчера.

 

А у меня к таким операциям лог прилагается - видимо эксклюзивно

Попробуйте в xr_camper заменить строку

action:add_precondition (world_property(stalker_ids.property_danger,false))

на

action:add_precondition (world_property(stalker_ids.property_danger_grenade,false))

- лога не будет.

 

Ну уж туда то зачем лазить? Классов дефолтных и так 'вагон и маленькая тележка' - куда свои то создавать?

Ну почему, мне как-то раз понадобилось повесить скрипты на гранаты (на их серверные объекты) и тут как раз глюкнул akelpad в момент сохранения - подрезал конец документа и заполнил его 5-ю копиями одной строки. Результат очевиден :)

 

P.S. Битые сохранения и попытки использовать функции класса net_packet(), не соответствующие типу данных (к примеру, packet:r_stringZ() для считывания числа или bool) тоже относятся к первому пункту (неправильное использование класса net_packet())

Изменено пользователем Полтергейст

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


Ссылка на сообщение
если новосозданному НПС присвоить имя пути по которому уже кто-то ходит!

Не всегда так. К примеру, в схеме xr_patrol (работы patrol и raid) по одному пути ходят несколько npc. И вылетов от это нет. И вообще, непонятно, зачем для walker делать такой запрет - ну ходят двое по одному пути, ну и что?

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


Ссылка на сообщение
если вписывал своё уже в кустом дата "А то, какое у них название, где расположена точка - значения не имеет" - то получал гарантированный вылет без лога, вот так мне не везло, до тех пор пока названия им не поменял.

Так и не понял, что там с названиями. С чего и на что они менялись? Если оно из gulag_tasks взято, то обязательно надо добавлять к нему имя смарта, иначе вылет будет.

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


Ссылка на сообщение
(изменено)

Похоже это глюки скрипта move_mgr. Вот только не пойму, почему глюки из-за walker, а не camper - там схемы той строк 10. Будем разбираться :)

 

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Вылет без лога может случаиться, если вызвать метод update() из серверного объекта мёртвого NPC. Скорее всего для brain():update() будет то же самое, но надо будет ещё потестировать для более точных данных.

 

Ещё один источник проблем - функции cse_alife_smart_zone.register_npc() и cse_alife_smart_zone.unregister_npc(). Причём вылеты от них бывают не при каждом вызове, а "плавающие" (через раз). В смартах они не используются (видимо, именно поэтому разрабы их убрали), но на всякий случай оставлю это тут.

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Флуд почищен, список причин вылетов обновлён.

 

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

Дело в том, что я пытался прописать всем NPC (людям) в рестрикторы все аномалии, находящиеся на этом уровне, с помощью функции alife():add_in_restriction(npc, restrictor_id). При net_destroy, соответственно, удалял их с помощью alife():remove_in_restriction(npc, restrictor_id). Также был учтён баг с удалением рестриктора, прописанного кому-то. При самой игре вылета нет, но если сохраниться возле какого-нибудь NPC и потом загрузиться, то вылет был. Возможно, из-за того, что была попытка прописать всё это в рестрикторы дважды, либо весь этот список как-то неправильно сохраняется.

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Вылет без лога произойдёт, если попытаться использовать функцию wounded(...) для изменения состояния раненности NPC. Даже перенос её вызова в update(...) может не помочь - у меня вылетает и в первом update, и в net_spawn. Такие же проблемы могут быть при использовании некоторых других функций, но пока что с ними не сталкивался.

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Вылет без лога случается, если установить состояние тела равным move.crouch и ментальное состояние anim.free. Например, вот такой код

npc:set_mental_state(anim.free)
npc:set_body_state(move.crouch)

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

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Снайпер с пулеметом

Кстати, о моем вылете: он происходит только после обыска тайника стрелка. Если вылезти на базу вояк - вылет без лога, а если тем путем, каким вошел - то выдает

Это битые сохранения. Ошибки ищите в функциях STATE_Read/STATE_Write для серверных объектов, save/load в биндерах клиентских объектов, а также в функциях работы с пакетами (в скриптах того мода, который установлен).

 

Могут быть подобные вылеты, связанные с попытками задать недопустимые соответствия серверных/клиентских классов (таблицу возможных соответствий для ТЧ я выложил в справочнике по функциям и классам) в class_registrator.script. В таких случаях возможно даже зависание игры, естественно, без лога.

 

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

Class = WP_LR300

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

Изменено пользователем Полтергейст

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


Ссылка на сообщение
(изменено)

Ндр

пока не попаду еще раз, как только начинает умирать- зависание, а после вылет. Лог пуст. Опытным путем установил, что не в скриптах дело...

А откуда такие выводы? Скрипты (в особенности xr_motivator) оригинальные?

Возможно, после смерти npc по какой-то причине продолжает вызываться hit_callback при попадании. При вызове death_callback(...) все коллбеки должны отключаться (как в оригинале).

 

Снайпер с пулеметом, в названиях костей опечаток нет? Анимация idle для модели прописана?

P.s. про функции сохранения/загрузки читай в справочнике функций и классов (конкретно - класс object_binder, классы cse_alife_*)

Изменено пользователем Полтергейст

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


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

ВНИМАНИЕ! Если у вас игра ДО появления главного меню без всяких причин стала вылетать без лога, или с логом, в конце которого есть строки такого содержания

 

 

stack trace:

 

001B:07FF8824 xrGameSpy.dll, xrGS_GetGameID()

001B:023F12D4 xrGame.dll

001B:022E5EA0 xrGame.dll

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

stalkersc.available.gamespy.com

возможно, после этого игра заработает.

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


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

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

local particle = utils.cfg_get_string(self.st.ini, self.st.section_logic, "particle", self.object, false, "", nil)
if particle ~= nil then
     self.particle = particles_object(particle)
     self.particle:play_at_pos(self.object:position())
end

он выполняется на каждом обновлении биндера. Это приводило к тому, что при каждом выполнении кода объект партикла создавался заново, если задано имя партикла. Добавление проверки на наличие self.particle полностью избавило от этой проблемы.

  • Спасибо 1
  • Нравится 1

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


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

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

AMK-Team.ru

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