diff --git a/src/editor/engine/lua/LuaSharedSandbox.js b/src/editor/engine/lua/LuaSharedSandbox.js index ead6242..12a5f53 100644 --- a/src/editor/engine/lua/LuaSharedSandbox.js +++ b/src/editor/engine/lua/LuaSharedSandbox.js @@ -129,11 +129,17 @@ export class LuaSharedSandbox { // Регистрируем coroutine в __rbxl_coroutines с id для возобновления. // Скрипт оборачиваем в coroutine. task.wait()→coroutine.yield(sec) возвращает // delay из resume → планируем следующий resume через scheduleResume. + // Fallback Parent = workspace для скриптов без target (или с невалидным + // target). Это спасает массу Roblox-скриптов которые делают + // script.Parent.Parent — если бы Parent был nil, упало бы сразу. + const parentExpr = primId != null + ? `(__rbxl_get_part_by_id(${Number(primId)}) or workspace)` + : 'workspace'; const wrapped = ` do local script = { Name = ${JSON.stringify(scriptName)}, - Parent = ${primId != null ? `__rbxl_get_part_by_id(${Number(primId)})` : 'nil'}, + Parent = ${parentExpr}, ClassName = "Script", Disabled = false, Source = nil, diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index e133e7b..9d53d21 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -191,7 +191,23 @@ function makeInstanceMethods() { while (p) { if (p.ClassName === cls) return p; p = p.Parent; } return undefined; }, - WaitForChild: function (name) { return this.FindFirstChild(name); }, + WaitForChild: function (name) { + // В Roblox WaitForChild блокирует пока ребёнок не появится. У нас + // нет yield с произвольных JS-функций, поэтому возвращаем либо + // существующего ребёнка, либо ленивый stub-Folder чтобы избежать + // падений типа "attempt to index a nil value" в импортированных + // скриптах. Stub автоматически добавляется в Children. + const existing = this.FindFirstChild(name); + if (existing) return existing; + try { + const stub = newInstance('Folder', String(name)); + stub.Parent = this; + if (this.Children) this.Children.push(stub); + return stub; + } catch (_) { + return undefined; + } + }, IsA: function (cls) { return this.ClassName === cls || cls === 'Instance'; }, GetFullName: function () { const parts = [];