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). По этому вылету пока что могу посоветовать только уменьшение количества респавна.