pulse-rb 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,18 @@
1
1
  -- [adapters/windui.lua]
2
2
  -- Wind UI adapter for Pulse components.
3
- -- Injected by the compiler when ui_library = "windui" in layout.rblua.
4
- -- Provides _UIAdapter, _PulseNotify, and Pulse.UI (dynamic element builder).
5
- --
6
- -- Activation: set ui_library = "windui" in src/ui/layout.rblua
7
3
  -- Docs: footagesus.github.io/treehub-web/docs/windui
8
4
  -- Version: 1.6.64-fix (pinned)
9
5
 
6
+ -- Executor loadstring() environments are sandboxed — each chunk has its OWN environment
7
+ -- table, separate from _G. Global reads in this chunk go through getfenv(1), not _G.
8
+ -- The compiler passes the bundle table (_P) as an argument; we write every key into
9
+ -- this chunk's own environment so names like "Pulse" resolve correctly below.
10
+ local _P = ...
11
+ if type(_P) == "table" then
12
+ local _env = (getfenv and getfenv(1)) or _ENV or _G
13
+ for _k, _v in pairs(_P) do _env[_k] = _v end
14
+ end
15
+
10
16
  local _WINDUI_URL = "https://github.com/Footagesus/WindUI/releases/download/1.6.64-fix/main.lua"
11
17
  local _PULSE_LOGO = "https://pulse-rb.vercel.app/img/logo.svg"
12
18
 
package/dist/index.js CHANGED
@@ -56,13 +56,13 @@ var RB_VERSION, RB_HOME, IRONBREW2_DIR, IRONBREW2_REPO, ALWAYS_EXCLUDE, VALID_UI
56
56
  var init_constants = __esm({
57
57
  "src/constants.ts"() {
58
58
  init_cjs_shims();
59
- RB_VERSION = "1.3.0";
59
+ RB_VERSION = "1.3.2";
60
60
  RB_HOME = path.join(os.homedir(), ".rb");
61
61
  path.join(RB_HOME, "bin");
62
62
  IRONBREW2_DIR = path.join(RB_HOME, "ironbrew2");
63
63
  IRONBREW2_REPO = "https://github.com/Trollicus/ironbrew-2.git";
64
64
  ALWAYS_EXCLUDE = /* @__PURE__ */ new Set(["types.lua"]);
65
- VALID_UI_LIBS = /* @__PURE__ */ new Set(["linoria", "windui"]);
65
+ VALID_UI_LIBS = /* @__PURE__ */ new Set(["windui"]);
66
66
  OBFUSCATION_PRESETS = ["Low", "Medium", "Strong"];
67
67
  CDN_BASE_URL = "https://pub-2072661efb7e45a1ac7f2aea691b0627.r2.dev";
68
68
  }
@@ -768,7 +768,7 @@ function parseLayoutOptions(body) {
768
768
  toggle_key: "RightControl",
769
769
  size: [950, 600],
770
770
  compat_exclude: [],
771
- ui_library: "linoria",
771
+ ui_library: "windui",
772
772
  theme: "Dark",
773
773
  folder: "Hub",
774
774
  notify_title: "Hub",
@@ -830,7 +830,7 @@ function parseLayoutOptions(body) {
830
830
  }
831
831
  case "ui_library": {
832
832
  const lib = val.replace(/^["']|["']$/g, "");
833
- if (lib === "linoria" || lib === "windui") opts.ui_library = lib;
833
+ if (lib === "windui") opts.ui_library = lib;
834
834
  break;
835
835
  }
836
836
  case "theme":
@@ -1185,13 +1185,13 @@ end)
1185
1185
  if (m && VALID_UI_LIBS.has(m[1])) return m[1];
1186
1186
  }
1187
1187
  const layoutFile = path.join(this.srcDir, "ui", "layout.rblua");
1188
- if (!fs.existsSync(layoutFile)) return "linoria";
1188
+ if (!fs.existsSync(layoutFile)) return "windui";
1189
1189
  try {
1190
1190
  const [inner] = findLayoutBlock(fs.readFileSync(layoutFile, "utf8"));
1191
- if (inner) return parseLayoutOptions(inner).ui_library ?? "linoria";
1191
+ if (inner) return parseLayoutOptions(inner).ui_library ?? "windui";
1192
1192
  } catch {
1193
1193
  }
1194
- return "linoria";
1194
+ return "windui";
1195
1195
  }
1196
1196
  resolveUi(ui) {
1197
1197
  if (!ui) ui = this.getUiLibrary();
@@ -1269,7 +1269,6 @@ end)
1269
1269
  for (const f of rglob(PULSE_UI_DIR, [".lua", ".rblua"]).sort((a, b) => path.basename(a).toLowerCase().localeCompare(path.basename(b).toLowerCase()))) {
1270
1270
  const stem = path.basename(f, path.extname(f));
1271
1271
  if (stem.startsWith("windui_") && ui !== "windui") continue;
1272
- if (stem.startsWith("linoria_") && ui !== "linoria") continue;
1273
1272
  uiFiles.push(f);
1274
1273
  }
1275
1274
  }
@@ -1295,7 +1294,7 @@ end)
1295
1294
  `);
1296
1295
  parts.push(`for _k,_v in pairs(_P) do _G[_k]=_v end
1297
1296
  `);
1298
- parts.push(`local _A=loadstring(game:HttpGet("${base}/adapters/${ui}.lua"))()
1297
+ parts.push(`local _A=loadstring(game:HttpGet("${base}/adapters/${ui}.lua"))(_P)
1299
1298
  `);
1300
1299
  parts.push(`local signal,computed,defineComponent,on=_P.signal,_P.computed,_P.defineComponent,_P.on
1301
1300
  `);
@@ -1945,7 +1944,7 @@ async function cmdInit(args) {
1945
1944
  "pulse-rb": `^${RB_VERSION}`,
1946
1945
  "@rb-pulse/core": `^${RB_VERSION}`,
1947
1946
  "@rb-pulse/ui": `^${RB_VERSION}`,
1948
- "@rb-pulse/roblox": `^${RB_VERSION}`
1947
+ "@rbxts/types": "^1.0.0"
1949
1948
  }
1950
1949
  };
1951
1950
  fs.writeFileSync(pathe.join(dest, "package.json"), JSON.stringify(pkgJson, null, 2) + "\n", "utf8");
@@ -1990,7 +1989,7 @@ var init_init = __esm({
1990
1989
  skipLibCheck: true,
1991
1990
  target: "ESNext",
1992
1991
  moduleResolution: "bundler",
1993
- types: ["@rb-pulse/core"]
1992
+ types: ["@rb-pulse/core", "@rbxts/types"]
1994
1993
  },
1995
1994
  include: ["src/**/*.ts"],
1996
1995
  exclude: ["node_modules"]
@@ -2933,7 +2932,7 @@ async function cmdPublish(_args) {
2933
2932
  { remote: `${VERSION_PATH}/bundle.lua`, content: bundleContent }
2934
2933
  ];
2935
2934
  const pulseUiDir = pathe.join(PULSE_DIR2, "ui");
2936
- for (const adapter of ["windui", "linoria"]) {
2935
+ for (const adapter of ["windui"]) {
2937
2936
  const p = pathe.join(ADAPTERS, `${adapter}.lua`);
2938
2937
  if (!fs.existsSync(p)) continue;
2939
2938
  const parts = [fs.readFileSync(p, "utf8").trimEnd()];
@@ -3091,7 +3090,7 @@ var main = citty.defineCommand({
3091
3090
  preset: { type: "string", default: "Medium", description: "Obfuscation preset: Low | Medium | Strong" },
3092
3091
  copy: { type: "boolean", default: false, description: "Copy standard build to clipboard after build" },
3093
3092
  dev: { type: "boolean", default: false, description: "Also emit a dev build (script.dev.lua)" },
3094
- ui: { type: "string", description: "Override UI library (linoria | windui)" }
3093
+ ui: { type: "string", description: "Override UI library (windui)" }
3095
3094
  },
3096
3095
  async run({ args }) {
3097
3096
  const { cmdBuild: cmdBuild2 } = await Promise.resolve().then(() => (init_build(), build_exports));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-rb",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "rb CLI — Pulse framework build tool for Roblox script projects",
5
5
  "bin": {
6
6
  "rb": "./bin/rb.js"
@@ -33,13 +33,15 @@
33
33
  "zod": "^4.4.3"
34
34
  },
35
35
  "devDependencies": {
36
+ "@rbxts/types": "^1.0.924",
36
37
  "@types/fs-extra": "^11.0.4",
37
38
  "@types/luaparse": "^0.2.9",
38
39
  "@types/node": "^22.0.0",
39
40
  "tsup": "^8.3.0",
40
41
  "tsx": "^4.19.0",
41
42
  "typescript": "^5.8.3",
42
- "vitest": "^2.1.0"
43
+ "vitest": "^2.1.0",
44
+ "@rb-pulse/core": "1.3.2"
43
45
  },
44
46
  "engines": {
45
47
  "node": ">=18.0.0"
@@ -1,11 +1,10 @@
1
- defineComponent('PlayerESP', () => {
2
- const enabled = signal(false)
3
- const showName = signal(true)
4
- const showBox = signal(true)
1
+ defineComponent('PlayerESP', (): WidgetDef[] => {
2
+ const enabled = signal<boolean>(false)
3
+ const showName = signal<boolean>(true)
4
+ const showBox = signal<boolean>(true)
5
5
 
6
- on.heartbeat({ when: enabled, every: 0.05 }, () => {
7
- // Draw ESP — use Pulse.Draw helpers
8
- // Pulse.Draw.box(character, { color: [255, 0, 0] })
6
+ on.heartbeat({ when: enabled, every: 0.05 }, (): void => {
7
+ // Draw ESP — use Pulse.UI helpers or drawing APIs here
9
8
  })
10
9
 
11
10
  return [
@@ -1,14 +1,14 @@
1
- defineComponent('FOVChanger', () => {
2
- const enabled = signal(false)
3
- const fov = signal(70)
1
+ defineComponent('FOVChanger', (): WidgetDef[] => {
2
+ const enabled = signal<boolean>(false)
3
+ const fov = signal<number>(70)
4
4
 
5
- const applyFov = () => {
5
+ const applyFov = (): void => {
6
6
  const cam = (workspace as any).CurrentCamera
7
7
  if (cam) cam.FieldOfView = enabled() ? fov() : 70
8
8
  }
9
9
 
10
10
  on.signal(enabled, applyFov)
11
- on.signal(fov, applyFov)
11
+ on.signal(fov, applyFov)
12
12
 
13
13
  return [
14
14
  toggle('FOV Changer').bind(enabled),
@@ -1,21 +1,14 @@
1
- // SpeedHack SolidJS-style reactive component.
2
- // signal() is like SolidJS createSignal; on.* hooks are like createEffect.
1
+ defineComponent('SpeedHack', (): WidgetDef[] => {
2
+ const enabled = signal<boolean>(false)
3
+ const speed = signal<number>(16)
3
4
 
4
- defineComponent('SpeedHack', () => {
5
- const enabled = signal(false)
6
- const speed = signal(16)
7
-
8
- on.heartbeat({ when: enabled }, () => {
9
- const char = _PulseGetChar()
10
- if (!char) return
11
- const h = char.FindFirstChild('Humanoid') as any
5
+ on.heartbeat({ when: enabled }, (): void => {
6
+ const h = _PulseGetHumanoid() as any
12
7
  if (h) h.WalkSpeed = speed()
13
8
  })
14
9
 
15
- on.respawn(() => {
16
- const char = _PulseGetChar()
17
- if (!char) return
18
- const h = char.FindFirstChild('Humanoid') as any
10
+ on.respawn((): void => {
11
+ const h = _PulseGetHumanoid() as any
19
12
  if (h) h.WalkSpeed = enabled() ? speed() : 16
20
13
  })
21
14
 
@@ -1,4 +1,4 @@
1
+ node_modules/
1
2
  build/
2
3
  *.log
3
- __pycache__/
4
4
  .rb-deploy
@@ -1,13 +1,12 @@
1
1
  // Pulse layout — configures the script window.
2
2
  // Based on Next.js root layout convention.
3
- // uiLibrary: 'windui' | 'linoria'
4
3
 
5
4
  export default {
6
5
  title: '{NAME}',
7
6
  author: '',
8
7
  toggleKey: 'RightControl',
9
8
  size: [850, 560] as [number, number],
10
- uiLibrary: 'windui' as 'windui' | 'linoria',
9
+ uiLibrary: 'windui' as const,
11
10
  theme: 'Indigo',
12
11
  icon: 'code-2',
13
12
  folder: '{NAME}',
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "noEmit": true,
5
+ "skipLibCheck": true,
6
+ "target": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "types": ["@rb-pulse/core"]
9
+ },
10
+ "include": ["*.ts"]
11
+ }
@@ -1,233 +0,0 @@
1
- -- [adapters/linoria.lua]
2
- -- Linoria UI adapter for Pulse components.
3
- -- Injected by the compiler when src/ui/ exists. Provides _UIAdapter to layout
4
- -- and page files. _Library / _ThemeManager / _SaveManager are available as
5
- -- upvalues to all subsequent files (Settings.lua, etc.) via flat compilation.
6
-
7
- local _LIB_URL = "https://raw.githubusercontent.com/violin-suzutsuki/LinoriaLib/main/Library.lua"
8
- local _THEME_URL = "https://raw.githubusercontent.com/violin-suzutsuki/LinoriaLib/main/addons/ThemeManager.lua"
9
- local _SAVE_URL = "https://raw.githubusercontent.com/violin-suzutsuki/LinoriaLib/main/addons/SaveManager.lua"
10
-
11
- -- Safe filesystem wrappers — some executors error instead of returning nil
12
- do
13
- local _mf = makefolder or function() end
14
- makefolder = function(p) pcall(_mf, p) end
15
-
16
- local _wf = writefile or function() end
17
- writefile = function(p, d) pcall(_wf, p, d) end
18
-
19
- local _rf = readfile or function() return "" end
20
- readfile = function(p)
21
- local ok, r = pcall(_rf, p)
22
- return ok and r or ""
23
- end
24
-
25
- local _iff = isfolder or function() return false end
26
- isfolder = function(p)
27
- local ok, r = pcall(_iff, p)
28
- return ok and r or false
29
- end
30
-
31
- local _isf = isfile or function() return false end
32
- isfile = function(p)
33
- local ok, r = pcall(_isf, p)
34
- return ok and r or false
35
- end
36
-
37
- local _df = delfile or function() end
38
- delfile = function(p) pcall(_df, p) end
39
- end
40
-
41
- local function _loadLib(url, name)
42
- local ok, src = pcall(game.HttpGet, game, url)
43
- if not ok then error("[AOT-R] HTTP failed for " .. name .. ": " .. tostring(src)) end
44
- if type(src) ~= "string" or #src < 50 then
45
- error("[AOT-R] Empty response for " .. name)
46
- end
47
- local fn, err = loadstring(src)
48
- if not fn then error("[AOT-R] Compile failed for " .. name .. ": " .. tostring(err)) end
49
- local ok2, result = pcall(fn)
50
- if not ok2 then error("[AOT-R] Init failed for " .. name .. ": " .. tostring(result)) end
51
- return result
52
- end
53
-
54
- local _Library = _loadLib(_LIB_URL, "Library")
55
- local _ThemeManager = _loadLib(_THEME_URL, "ThemeManager")
56
- local _SaveManager = _loadLib(_SAVE_URL, "SaveManager")
57
-
58
- -- ── Adapter ───────────────────────────────────────────────────────────────────
59
-
60
- local _UIS = game:GetService("UserInputService")
61
- local _UIAdapter = {}
62
-
63
- function _UIAdapter:CreateWindow(title, w, h, opts)
64
- -- opts table from layout (theme/folder/notify_title) — Linoria handles
65
- -- folder via ThemeManager/SaveManager in the settings page, not here.
66
- return _Library:CreateWindow({
67
- Title = title,
68
- Center = true,
69
- AutoShow = true,
70
- TabPadding = 8,
71
- MenuFadeTime = 0.2,
72
- })
73
- end
74
-
75
- function _UIAdapter:RegisterTheme(_t) end -- no-op for Linoria builds
76
-
77
- function _UIAdapter:GetThemeNames() return nil end -- Linoria manages its own themes
78
-
79
- function _UIAdapter:SetToggleKey(keyCode)
80
- _Library.ToggleKey = keyCode
81
- end
82
-
83
- -- ── Widget constructors ───────────────────────────────────────────────────────
84
-
85
- function _UIAdapter:addToggle(gb, id, opts)
86
- -- opts: { label, signal, tip }
87
- gb:AddToggle(id, {
88
- Text = opts.label,
89
- Default = opts.signal(),
90
- Tooltip = opts.tip or "",
91
- Callback = function(v) opts.signal(v) end,
92
- })
93
- -- reverse: signal changes → update Linoria widget
94
- opts.signal:onChange(function(v)
95
- local t = Toggles and Toggles[id]
96
- if t then t:SetValue(v) end
97
- end)
98
- end
99
-
100
- function _UIAdapter:addSlider(gb, id, opts)
101
- -- opts: { label, signal, min, max, tip, rounding? }
102
- gb:AddSlider(id, {
103
- Text = opts.label,
104
- Default = opts.signal(),
105
- Min = opts.min,
106
- Max = opts.max,
107
- Rounding = opts.rounding or 1,
108
- Compact = false,
109
- Tooltip = opts.tip or "",
110
- Callback = function(v) opts.signal(v) end,
111
- })
112
- opts.signal:onChange(function(v)
113
- local t = Options and Options[id]
114
- if t then t:SetValue(v) end
115
- end)
116
- end
117
-
118
- function _UIAdapter:addDropdown(gb, id, opts)
119
- -- opts: { label, signal, options, tip }
120
- gb:AddDropdown(id, {
121
- Text = opts.label,
122
- Values = opts.options,
123
- Default = opts.signal(),
124
- Tooltip = opts.tip or "",
125
- Callback = function(v) opts.signal(v) end,
126
- })
127
- opts.signal:onChange(function(v)
128
- local t = Options and Options[id]
129
- if t then t:SetValue(v) end
130
- end)
131
- end
132
-
133
- function _UIAdapter:addMultiDropdown(gb, id, opts)
134
- -- opts: { label, signal, options, tip }
135
- gb:AddDropdown(id, {
136
- Text = opts.label,
137
- Values = opts.options,
138
- Default = {},
139
- Multi = true,
140
- Tooltip = opts.tip or "",
141
- Callback = function(v) opts.signal(v) end,
142
- })
143
- opts.signal:onChange(function(v)
144
- local t = Options and Options[id]
145
- if t then t:SetValue(v) end
146
- end)
147
- end
148
-
149
- function _UIAdapter:addButton(gb, opts)
150
- -- opts: { label, action, tip? }
151
- gb:AddButton(opts.label, opts.action)
152
- end
153
-
154
- function _UIAdapter:addKeybind(gb, id, opts)
155
- -- opts: { label, key, action }
156
- gb:AddLabel(opts.label):AddKeyPicker(id, {
157
- Default = opts.key,
158
- SyncToggleState = false,
159
- Mode = "Toggle",
160
- Text = opts.label,
161
- Callback = function()
162
- -- Skip if the player is typing in any TextBox (chat, search, etc.)
163
- if _UIS:GetFocusedTextBox() then return end
164
- opts.action()
165
- end,
166
- })
167
- end
168
-
169
- function _UIAdapter:addLabel(gb, text)
170
- gb:AddLabel(text)
171
- end
172
-
173
- function _UIAdapter:addParagraph(gb, title, desc)
174
- gb:AddLabel(title)
175
- if desc and desc ~= "" then
176
- gb:AddLabel(desc)
177
- end
178
- end
179
-
180
- function _UIAdapter:addSeparator(gb)
181
- gb:AddBlank(6)
182
- end
183
-
184
- -- Notify — adapter-agnostic function called by the defaults runner.
185
- _PulseNotify = function(msg, duration)
186
- pcall(function() _Library:Notify(msg, duration or 5) end)
187
- end
188
-
189
- -- Register Linoria teardown with the Pulse destroy system.
190
- -- _PulseDestroy() will call this before unmounting components.
191
- _PulseOnDestroy(function()
192
- pcall(function()
193
- if _Library.Unload then
194
- _Library:Unload()
195
- elseif _Library.GUI then
196
- _Library.GUI:Destroy()
197
- end
198
- end)
199
- end)
200
-
201
- -- ── Mount a component's _ui table into a groupbox ────────────────────────────
202
-
203
- function _UIAdapter:mount(component, gb)
204
- if not component then return end
205
- local ui = component._ui
206
- if not ui then return end
207
- for _, w in ipairs(ui) do
208
- local t = w.type
209
- local sig = component[w.signal] -- Signal callable (nil for button/label/separator)
210
- if t == "toggle" then
211
- self:addToggle(gb, w.id, { label = w.label, signal = sig, tip = w.tip })
212
- elseif t == "slider" then
213
- self:addSlider(gb, w.id, { label = w.label, signal = sig,
214
- min = w.min, max = w.max, tip = w.tip })
215
- elseif t == "dropdown" then
216
- self:addDropdown(gb, w.id, { label = w.label, signal = sig,
217
- options = w.options, tip = w.tip })
218
- elseif t == "multidropdown" then
219
- self:addMultiDropdown(gb, w.id, { label = w.label, signal = sig,
220
- options = w.options, tip = w.tip })
221
- elseif t == "button" then
222
- self:addButton(gb, { label = w.label, action = w.action })
223
- elseif t == "keybind" then
224
- self:addKeybind(gb, w.id, { label = w.label, key = w.key, action = w.action })
225
- elseif t == "label" then
226
- self:addLabel(gb, w.label)
227
- elseif t == "paragraph" then
228
- self:addParagraph(gb, w.title, w.desc)
229
- elseif t == "separator" then
230
- self:addSeparator(gb)
231
- end
232
- end
233
- end
@@ -1,55 +0,0 @@
1
- -- [pulse/ui/linoria_settings.lua]
2
- -- Framework-managed Settings tab for Linoria builds.
3
- -- Injected automatically by the compiler when ui_library = "linoria".
4
- -- Do not copy this file into src/ — edit it here in rb/pulse/ui/.
5
- do
6
- local SettingsTab = _GetTab("Settings")
7
-
8
- _ThemeManager:SetLibrary(_Library)
9
- _SaveManager:SetLibrary(_Library)
10
-
11
- _SaveManager:IgnoreThemeSettings()
12
- _SaveManager:SetIgnoreIndexes({ "MenuKeybind" })
13
-
14
- -- Folder names come from folder = "..." in layout.rblua
15
- _ThemeManager:SetFolder(_PULSE_FOLDER)
16
- _SaveManager:SetFolder(_PULSE_FOLDER .. "/configs")
17
-
18
- _ThemeManager:ApplyToTab(SettingsTab)
19
- _SaveManager:BuildConfigSection(SettingsTab)
20
-
21
- local gb_menu = SettingsTab:AddLeftGroupbox("Menu Settings")
22
- gb_menu:AddButton("Destroy UI", function() _PulseDestroy() end)
23
- gb_menu:AddLabel("Menu bind"):AddKeyPicker("MenuKeybind", {
24
- Default = _PULSE_TOGGLE_KEY,
25
- NoUI = false,
26
- Text = "Menu keybind",
27
- })
28
- _Library.ToggleKeybind = Options.MenuKeybind
29
-
30
- -- Performance — rendered directly (multi-dropdown requires a direct Linoria call)
31
- local gb_perf = SettingsTab:AddRightGroupbox("Performance")
32
- gb_perf:AddLabel("Removes objects every 1 second.")
33
- gb_perf:AddLabel("Safe to toggle mid-session.")
34
- gb_perf:AddBlank(4)
35
- gb_perf:AddToggle("Perf_enabled", {
36
- Text = "Enabled",
37
- Default = false,
38
- Tooltip = "Start/stop all selected cleanups",
39
- Callback = function(v) Performance.enabled(v) end,
40
- })
41
- Performance.enabled:onChange(function(v)
42
- local t = Toggles and Toggles["Perf_enabled"]
43
- if t then t:SetValue(v) end
44
- end)
45
- gb_perf:AddDropdown("Perf_selected", {
46
- Text = "Remove",
47
- Values = {"Dead Titans","Decor","HQ Decor","Rocks","Grass","Trees","Civilians","Buildings"},
48
- Default = {"Dead Titans"},
49
- Multi = true,
50
- Tooltip = "Objects removed every second while Enabled is on",
51
- Callback = function(v) Performance.selected(v) end,
52
- })
53
-
54
- _SaveManager:LoadAutoloadConfig()
55
- end