Скриптові «вильоти»
Загальне рішення
Вирішення подібних помилок [1] - завдання нетривіальне. Тому їх виправленням слід займатися тільки тим, хто має хоча б базові знання скриптингу.
1 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...\gamedata\scripts\xr_danger.script:116: attempt до index field 'ignore_types' (a nil value)
Помилка [2]
Спроба взяти значення зі змінної ignore_types
(може бути будь-яка інша). Двигун гри очікував, що це таблиця, а виявилося nil
.
Підказка скриптеру
Необхідно змінити код таким чином, щоб там де очікується таблиця, була таблиця або щоб nil
не намагалися прочитати якісь значення.
Саме в цьому випадку скрипт записує налаштування ігнорування небезпеки в таблицю db.storage[npc:id()].danger.ignore_types, а намагається перевіряти по неіснуючій таблиці db.storage[npc:id()].ignore_types.
2 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...\gamedata\scripts\.script:34: attempt to call method 'section' (a nil value)
Помилка
У якогось об'єкта намагалися викликати метод section
(назва методу може бути будь-яким іншим). Виявилося, що цей об'єкт, такого методу немає.
Підказка скриптеру
Можливі варіанти:
- Це був об'єкт не того класу, як передбачалося (клієнтський замість серверного, чи навпаки, чи інші класи).
- Можливо була друкарська помилка в назві методу, і він просто називається не так.
- Можливо, неуважно був вивчений даний клас, і в нього просто немає і не повинно бути такого методу.
Наприклад, це можна перевірити конструкціями на зразок цієї:
if obj . section and type ( obj . section ) == ' function' then obj : section () end
Тобто. до виклику методу, перевірити, що з об'єкта існує таке полі, і має тип function
, тобто. його можна викликати. Але слід розуміти, що не варто обвішувати такими перевірками всі поспіль виклики скрізь. Купа перевірок займе багато часу та викличе гальма. Це годиться лише для налагодження – дізнались чи є метод чи ні. Якщо ні, значить і не треба намагатися його викликати, а якщо є, то можна викликати без жодних перевірок.
3 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...w of chernobyl\gamedata\scripts\<ім'я файлу>.script:<номер рядка>: attempt to perform arithmetic on a nil value
Помилка
Спроба виконання арифметичної операції за nil
.
Підказка скриптеру
Щоб виправити помилку, спочатку потрібно її знайти. Зверніть увагу на <номер строки>
, спроба виконання арифметичної операції над nil
відбувається саме в ній. Ще можуть бути вказані імена змінних, це також є підказкою.
4 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...\gamedata\scripts\<ім'я файлу>.script:<номер рядка>: attempt to compare number with nil
Помилка
Спроба порівняння числа зnil
Підказка скриптеру
Щоб виправити помилку, спочатку потрібно її знайти. Зверніть увагу на <номер строки>
спроба порівняння числа з nil
відбувається саме в ній. Ще можуть бути вказані імена змінних, це також є підказкою.
5 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...\gamedata\scripts\<ім'я файлу>.script:<номер рядка>: attempt to perform arithmetic on field '?' (a nil value)
Помилка
Аналог вильотів з варіантів 3 і 4. Спроби арифметичних дій над nil
, просто цей nil
немає власного імені та є елементом таблиці.
Подібні ж вильоти можуть бути і при інших спробах якихось дій, що передбачають, що змінна зберігає певне значення, коли в результаті виявляється, що там все ж таки nil
.
Підказка скриптеру
Щоб виправити помилку, спочатку потрібно її знайти. Тут або дані читаються не звідти, звідки мають, або десь мали їх туди записати, але не записали.
6 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: error in error handling
Помилка
Причину вильоту назвати досить важко, ймовірно, це щось глибоко движкове. Такий виліт може викликати передачу клієнтського об'єкта в функцію switch_offline , але не тільки це.
Підказка скриптеру
У разі передачі клієнтського об'єкта – усунути помилку. Але визначити причину в більшості випадків украй проблематично - спробуйте завантажити останнє збереження.
Можна припустити, що подібний виліт може виникати у ряді випадків, коли в движкові методи, які очікують на об'єкт певного класу, передається об'єкт не того класу, на який вони очікують. Якщо припущення правильно - перевірити правильність даних, переданих таким движковим методам.
7 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: attempt to call a nil value
Помилка
Відбувається при спробі викликати конструктор класу, якого немає або локальну функцію, якої немає.
Підказка скриптеру
Можливі варіанти:
- В імені конструктора/функції допущено друкарську помилку, і він просто не так називається.
- Викликане не є конструктором, функцією, або просто не існує.
8 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : D:\xray-svn\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: C stack overflow
Помилка
Зверніть також увагу на текст вище за рядок FATAL ERROR
з лога.
Рядок Arguments
у різних випадках може відрізнятися. Причина таких вильотів - передача некоректних значень функцій гри.
А загальний зміст - спроба зробити щось, що робити не можна у принципі, тобто. неможливе (як поділ на нуль, наприклад).
Суть помилки в тому, що якась функція викликана величезна кількість разів поспіль замість одного. Функції іноді викликаються рекурсивно, у циклі, але це має обмежені і розумні межі. У цьому випадку виліт через те, що ці межі зникли.
Рішення
Якщо проблема виникла одноразово, завантажте останнє збереження.
Насправді допомагає, т.к. періодично такі ситуації виникають випадково навіть з оригінальними GSC-скриптами.
Підказка скриптеру
Якщо проблема стабільна - відстежувати виклики підозрюваних функцій, знайти функцію, яка переповнює стек, і причину чому вона викликається нескінченне число разів. Можливо, неправильно вказані умови припинення циклу та/або припинення рекурсивного виклику функцією самої себе.
Щоб виправити помилку, необхідно знайти, де і чому вона відбувається. Для цього встановіть висновки чекпойнтів виклику функцій у лог, спочатку найзагальніших, з яких можна розпочати пошук. Потроху це й виведе на причину.
Наочний приклад:
function actor_item_take ( obj , item )
--log("events.actor_item_take")
Тут закоментований виклик лога, а коли був не закоментований - у лог повідомлялося про кожний виклик цієї функції. Так і робиться.
У лозі має бути видно, як якась із функцій викликається мільйон разів, хоча має бути викликана 1 раз – це і є причина вильоту.
Примітка:
Іноді та сама помилка, тобто. та сама причина, може призводити до іншого вильоту - Ran out of memory
. Це коли функції, що викликаються, встигають "зжерти" всю пам'ять раніше, ніж "зжеруть" весь стек.
9 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: Не так operator defined
Помилка
Спроба використати для якогось об'єкта, неіснуючий метод. Найчастіше плутанина із серверними та клієнтськими методами.
Підказка скриптеру
Див. варіант 2, там було про відсутній метод section
, тут ім'я методу не вказано, але сенс той самий. Як правило, об'єкт не того класу, або метод, що не існує у даного класу, або спроба викликати як метод те, що їм не є.
10 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...\gamedata\scripts\<ім'я файлу>.script:<номер рядка>: unfinished capture
Помилка
Єдина відома причина даного вильоту, це спроба використовувати для функції string.find
як шаблон "чарівний символ" круглу дужку, що відкривається, тобто. спроба знайти дужку таким чином:
local p = string.find ( str , " (" )
Підказка скриптеру
Для пошуку круглої дужки, що відкривається, використовуйте параметр plain ( local p
) для даної функції зі значенням true
, він вимикає можливість пошуку за шаблоном і в такому випадку проводиться пошук підрядки як є:
local p = string.find ( str , " ( " , 1 , true )
11 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description: Arguments : LUA error: ...ing\stalker\gamedata\scripts\inv_system.script:1674: attempt to call function 'GetCommand_TakeSlot' (a nil value)
Помилка
Здавалося б, причина зрозуміла - виклик функції, якої немає. Однак функція є, і називається саме так, і з нею все гаразд. Як і з самим файлом скрипта теж - у ньому немає синтаксичних помилок, двигун гри не лається на нього самого, заявляючи, що вінa nil value
Причина виявилася ось у чому - на початку скрипту, є таблиця такого вигляду:
tbl = {
string_key1 = number ,
string_key2 = number ,
...
А далі є ще одна таблиця – ось такого виду:
tb_funcs = {
[ tbl . string_key1 ] = function ( args ... )
...
end ,
...
Тобто. значення її – функції, а ключами є значення з першої таблиці.
Так у першій таблиці змінили ім'я одного з ключів. А в другій – забули це зробити. Вийшло що в другій таблиці, одна з функцій знаходиться по ключу, який взагалі дорівнює nil
.
А до чого тут та функція, через виклик якої, і стався виліт з нею в лог? Та взагалі ні до чого. Вона просто була в тому ж файлі нижче за текстом.
Підказка скриптеру
Висновок - коли робите в таблицях ключі виду масив/модуль/значення - переконайтеся, що це значення не дорівнює nil
, а то двигун гри про це нормально не скаже.
12 варіант
Тип №1
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...e.r_Закутки правди\gamedata\scripts\uyman358.script:947: attempt to call field 'get_anomaly_data' (a nil value)
Помилка [3] [4]
Для новачків: скрипт (у даному випадку: uyman358.script ) не може викликати вказану в рядку (в даному випадку: 947 ) функцію (в даному випадку 'get_anomaly_data'
:).
Для досвідчених: спроба виклику цієї функції (в даному випадку: 'get_anomaly_data'
). Двигун гри очікував, що це таблиця, а виявилося nil
.
Припустимо, у таблиці лежать числа. Спроба взяти з таблиці значення пройде без проблем, а спроба виклику призведе до вильоту, т.к. Числа це не функції, їх не можна викликати.
Підказка скриптеру
Для новачків: перевірити в скрипті, вказаному в рядку, правильність імені функції, а також її наявність.
Для досвідчених: необхідно змінити код таким чином, щоб там де очікується функція, була функція або щоб nil
не намагалися прочитати якісь значення.
Тип №2
Expression: fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ....- Народна Солянка\gamedata\scripts\xr_logic.script:1490: attempt to call field '?' (a nil value)
Помилка [5]
Тут мало бути ім'я функції чи змінної, та його немає (у разі: '?'
). Це означає, що її, наприклад, викликали за числовим індексом з таблиці чи ще якось, причини можуть бути різні.
А загальний зміст - те, з чим намагалися зробити вказану дію, не має імені.
Наприклад, у типу 1:
uyman358.script:947: attempt to call field 'get_anomaly_data' (a nil value)
Вказано ім'я get_anomaly_data
. Помилка відбулася при спробі дії з саме цією змінною, її ім'я вказується завжди, коли двигун може вказати ім'я, з яким сталася помилка. Але нерідко буває, що змінна немає імені. Ось тоді він і пише'?'
13 варіант
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: ...ow of chernobyl\gamedata\scripts\bind_stalker.script:341: attempt to call 'give_info' global (a nil value)
Помилка
У файлі _g.script не знайдено зазначену глобальну функцію (в даному випадку: give_info
)
Рішення
Перевірити правильність імені функції, а також її наявність у _g.script .
14 варіант
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: not enough memory
Помилка [6] [7] [8]
LuaJIT може використовувати пам'ять тільки в молодших 2 Гб, а у великих модах туди складаються великі текстури, великі локації та все інше таке ж велике. У результаті через якийсь час молодші 2 Гб виявляються забиті і, хоча пам'яті ще повно, LuaJIT виділити собі пам'ять не може.
Рішення [9]
- Спробуйте завантажити останні збереження або йти на іншу локацію.
У деяких випадках це допомагає через те, що при старті LuaJIT встигає відхопити собі пам'ять раніше, ніж її захоплять текстури, і якийсь час LuaJIT ще пропрацює.
або
- Використовуйте 64-бітний двигун OGSR Engine .
Він виділяє для LuaJIT пам'ять наперед. За нинішніми мірками йому потрібні крихітки - близько сотні мегабайт.
Expression: fatal error Function : CScriptEngine::lua_error File : E:priquel\sources\engine\xrServerEntities\script_engine.cpp Line : 180 Description : <no expression> Arguments : LUA error: not enough memory
Помилка [10] [11] [12]
Версія гри відрізняється, див. рядок File:
(в даному випадку: ЧН )
Рішення
Використовувати треба двигун X-Ray Engine by Abramcumner
15 варіант
Expression: fatal error Function : CScriptEngine::lua_error File : D:\xray-svn\xr_3da\xrGame\script_engine.cpp Line : 74 Description : <no expression> Arguments : LUA error: ...\gamedata\scripts\_g.script:20: bad argument #2 to 'format' (string expected, got no value)
Expression: fatal error Function : CScriptEngine::lua_error File : E:priquel\sources\engine\xrServerEntities\script_engine.cpp Line : 180 Description : <no expression> Arguments : LUA error: d:\games\stalker\cs\gamedata\scripts\_g.script:975: bad argument #2 to 'format' (string expected, got nil)
Помилка [13]
Для новачків: якийсь скрипт не може викликати якусь функцію, тому що виклик функції написаний неправильно, а саме, відсутнє ім'я функції. Має бути так имя_скрипта.имя_функции_в_скрипте
, а воно ось так имя_скрипта.
.
Для досвідчених: ім'я скрипта (в даному випадку:) _g
, номер рядка (в даному випадку:) 20
і номер аргументу після символу #
(в даному випадку 2
🙂 можуть бути іншими. Помилка полягає в тому, що функція string.format
(може бути й інша) очікувала отримати у другому аргументі у зазначеному рядку файлу - рядок, а отримала nil
.
Підказка скриптеру
Для новачків: перевіряйте, що в скриптах змінювали останній раз, а саме — правильність виклику функції (наявність імені функції після імені скрипта).
Для досвідчених: необхідно дати їй рядок, або не давати те, що може не бути рядком, або перед подачею string.format
перевіряти значення.