pulse-rb 1.2.24

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.
Files changed (54) hide show
  1. package/README.md +225 -0
  2. package/adapters/linoria.lua +233 -0
  3. package/adapters/windui.llms.txt +366 -0
  4. package/adapters/windui.lua +505 -0
  5. package/bin/rb.js +2 -0
  6. package/dist/index.js +3285 -0
  7. package/package.json +59 -0
  8. package/pulse/dev/debuggui.lua +1206 -0
  9. package/pulse/dev/devconfig.lua +81 -0
  10. package/pulse/dev/ui/9_DevPanel.lua +384 -0
  11. package/pulse/helpers/aim.lua +193 -0
  12. package/pulse/helpers/cache.lua +68 -0
  13. package/pulse/helpers/cleaner.lua +110 -0
  14. package/pulse/helpers/conn.lua +33 -0
  15. package/pulse/helpers/cooldown.lua +47 -0
  16. package/pulse/helpers/draw.lua +122 -0
  17. package/pulse/helpers/hitbox.lua +63 -0
  18. package/pulse/helpers/input.lua +24 -0
  19. package/pulse/helpers/log.lua +228 -0
  20. package/pulse/helpers/loop.lua +58 -0
  21. package/pulse/helpers/memory.lua +48 -0
  22. package/pulse/helpers/narrate.lua +160 -0
  23. package/pulse/helpers/notify.lua +51 -0
  24. package/pulse/helpers/perf.lua +48 -0
  25. package/pulse/helpers/remote.lua +128 -0
  26. package/pulse/helpers/restore.lua +59 -0
  27. package/pulse/helpers/store.lua +39 -0
  28. package/pulse/helpers/team.lua +83 -0
  29. package/pulse/helpers/testmode.lua +80 -0
  30. package/pulse/helpers/trace.lua +111 -0
  31. package/pulse/helpers/track.lua +85 -0
  32. package/pulse/helpers/vec.lua +52 -0
  33. package/pulse/helpers/world.lua +51 -0
  34. package/pulse/runtime.lua +343 -0
  35. package/pulse/ui/linoria_settings.lua +55 -0
  36. package/pulse/ui/windui_settings.lua +87 -0
  37. package/templates/AGENTS.md +177 -0
  38. package/templates/CLAUDE.md +424 -0
  39. package/templates/deploy_config.example +17 -0
  40. package/templates/example_esp.rblua +69 -0
  41. package/templates/example_fov.rblua +20 -0
  42. package/templates/example_speed.rblua +25 -0
  43. package/templates/gitignore +4 -0
  44. package/templates/globals.lua +66 -0
  45. package/templates/layout.rblua +28 -0
  46. package/templates/module.lua +7 -0
  47. package/templates/module.rblua +32 -0
  48. package/templates/page_home.rblua +9 -0
  49. package/templates/remote.lua +6 -0
  50. package/templates/remotes.lua +14 -0
  51. package/vscode/language-configuration.json +35 -0
  52. package/vscode/package.json +35 -0
  53. package/vscode/src/extension.js +397 -0
  54. package/vscode/syntaxes/rblua.tmLanguage.json +126 -0
@@ -0,0 +1,51 @@
1
+ -- ── Pulse.World ──────────────────────────────────────────────────────────────
2
+ -- Safe workspace/service navigation — no nil-index crashes.
3
+ -- Usage:
4
+ -- local folder = Pulse.World.find("Titans", "Alive")
5
+ -- local list = Pulse.World.children("Titans", "Alive")
6
+ -- local svc = Pulse.World.service("TweenService")
7
+ -- local child = Pulse.World.await(model, "HumanoidRootPart", 5)
8
+
9
+ Pulse.World = (function()
10
+ local W = {}
11
+
12
+ -- Navigate workspace by a sequence of child names.
13
+ -- Returns the final Instance, or nil if any step is missing.
14
+ function W.find(...)
15
+ local node = workspace
16
+ for _, name in ipairs({...}) do
17
+ if not node then return nil end
18
+ local ok, child = pcall(function() return node:FindFirstChild(name) end)
19
+ if not ok or not child then return nil end
20
+ node = child
21
+ end
22
+ return node
23
+ end
24
+
25
+ -- Like find(), but returns the children of the final node.
26
+ -- Returns {} if the path doesn't exist.
27
+ function W.children(...)
28
+ local node = W.find(...)
29
+ if not node then return {} end
30
+ local ok, list = pcall(function() return node:GetChildren() end)
31
+ return ok and list or {}
32
+ end
33
+
34
+ -- Safely get a game service by name.
35
+ function W.service(name)
36
+ local ok, svc = pcall(game.GetService, game, name)
37
+ return ok and svc or nil
38
+ end
39
+
40
+ -- Wait for a named child to appear (wraps WaitForChild with a timeout).
41
+ -- Returns the child Instance or nil on timeout / error.
42
+ function W.await(parent, name, timeout)
43
+ if typeof(parent) ~= "Instance" then return nil end
44
+ local ok, result = pcall(function()
45
+ return parent:WaitForChild(name, timeout or 10)
46
+ end)
47
+ return ok and result or nil
48
+ end
49
+
50
+ return W
51
+ end)()
@@ -0,0 +1,343 @@
1
+ -- ============================================================
2
+ -- Pulse Runtime v0.1.0
3
+ -- Injected automatically by rb build before all user modules.
4
+ -- Do not require() this file — the compiler handles injection.
5
+ -- Pulse.* helpers are injected from rb/pulse/helpers/ after this.
6
+ -- ============================================================
7
+
8
+ -- ── Signal ───────────────────────────────────────────────────────────────────
9
+ -- Reactive atom. Call with no args to read, one arg to write.
10
+ -- signal:onChange(fn) → returns unsubscribe function.
11
+
12
+ local function Signal(default)
13
+ local _value = default
14
+ local _subs = {}
15
+
16
+ local s = {}
17
+
18
+ function s:get() return _value end
19
+
20
+ function s:set(new)
21
+ if new == _value then return end
22
+ _value = new
23
+ for i = #_subs, 1, -1 do
24
+ local ok, err = pcall(_subs[i], new)
25
+ if not ok then
26
+ local msg = "signal subscriber error: " .. tostring(err)
27
+ if Pulse.Log then
28
+ Pulse.Log.error("signal", msg, { signal = s._name or "?" })
29
+ else
30
+ warn("[Pulse] " .. msg)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ function s:onChange(fn)
37
+ table.insert(_subs, fn)
38
+ return function()
39
+ for i, sub in ipairs(_subs) do
40
+ if sub == fn then table.remove(_subs, i) return end
41
+ end
42
+ end
43
+ end
44
+
45
+ setmetatable(s, {
46
+ __call = function(_, ...)
47
+ if select("#", ...) == 0 then return s:get() end
48
+ s:set(...)
49
+ end
50
+ })
51
+
52
+ return s
53
+ end
54
+
55
+ -- ── Computed ─────────────────────────────────────────────────────────────────
56
+ -- Derived cached value. Re-evaluates when :invalidate() is called,
57
+ -- or when any Signal passed via :track(signal) changes.
58
+
59
+ local function Computed(fn)
60
+ local _cache = nil
61
+ local _dirty = true
62
+ local _unsubs = {}
63
+
64
+ local c = {}
65
+
66
+ function c:get()
67
+ if _dirty then
68
+ _cache = fn()
69
+ _dirty = false
70
+ end
71
+ return _cache
72
+ end
73
+
74
+ function c:track(signal)
75
+ table.insert(_unsubs, signal:onChange(function()
76
+ _dirty = true
77
+ end))
78
+ return c
79
+ end
80
+
81
+ function c:destroy()
82
+ for _, unsub in ipairs(_unsubs) do pcall(unsub) end
83
+ _unsubs = {}
84
+ end
85
+
86
+ setmetatable(c, { __call = function() return c:get() end })
87
+ return c
88
+ end
89
+
90
+ -- ── PulseEvent ───────────────────────────────────────────────────────────────
91
+ -- Lightweight event bus. fire(...) notifies all listeners.
92
+ -- connect(fn) → returns disconnect function.
93
+
94
+ local function PulseEvent(name)
95
+ local _listeners = {}
96
+ local e = {}
97
+ e._isPulseEvent = true
98
+ e._name = name or "?"
99
+
100
+ function e:connect(fn)
101
+ table.insert(_listeners, fn)
102
+ return function()
103
+ for i, l in ipairs(_listeners) do
104
+ if l == fn then table.remove(_listeners, i) return end
105
+ end
106
+ end
107
+ end
108
+
109
+ function e:fire(...)
110
+ for i = #_listeners, 1, -1 do
111
+ local ok, err = pcall(_listeners[i], ...)
112
+ if not ok then
113
+ local msg = "event listener error: " .. tostring(err)
114
+ if Pulse.Log then
115
+ Pulse.Log.error("event", msg, { event = e._name })
116
+ else
117
+ warn("[Pulse] event '" .. e._name .. "' error: " .. tostring(err))
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ setmetatable(e, { __call = function(_, ...) e:fire(...) end })
124
+ return e
125
+ end
126
+
127
+ -- ── Component ────────────────────────────────────────────────────────────────
128
+ -- Behavior service with lifecycle, connection tracking, and task management.
129
+
130
+ local _Registry = {} -- flat: { "Aimbot" = component, ... }
131
+ local _NamespaceReg = {} -- nested: { "Shifter" = { "Combat" = component } }
132
+
133
+ local function Component(name)
134
+ local c = {}
135
+ c._isComponent = true
136
+ c._name = name
137
+ c._connections = {}
138
+ c._tasks = {}
139
+ c._watchers = {}
140
+ c._mounted = false
141
+
142
+ -- Connection management
143
+ function c:bind(key, connection)
144
+ if self._connections[key] then
145
+ pcall(function() self._connections[key]:Disconnect() end)
146
+ end
147
+ self._connections[key] = connection
148
+ end
149
+
150
+ function c:unbind(key)
151
+ if self._connections[key] then
152
+ pcall(function() self._connections[key]:Disconnect() end)
153
+ self._connections[key] = nil
154
+ end
155
+ end
156
+
157
+ function c:unbindAll()
158
+ for _, conn in pairs(self._connections) do
159
+ pcall(function() conn:Disconnect() end)
160
+ end
161
+ self._connections = {}
162
+ end
163
+
164
+ -- Signal watching (auto-cleaned on unmount)
165
+ function c:watch(signal, fn)
166
+ local unsub = signal:onChange(fn)
167
+ table.insert(self._watchers, unsub)
168
+ return unsub
169
+ end
170
+
171
+ -- Delayed tasks (auto-cancelled on unmount)
172
+ function c:task(delay, fn)
173
+ local cancelled = false
174
+ table.insert(self._tasks, function() cancelled = true end)
175
+ task.delay(delay, function()
176
+ if cancelled then return end
177
+ local ok, err = pcall(fn)
178
+ if not ok then
179
+ local msg = "after-block error: " .. tostring(err)
180
+ if Pulse.Log then
181
+ Pulse.Log.error("component", msg, { component = name })
182
+ else
183
+ warn("[Pulse] " .. name .. " " .. msg)
184
+ end
185
+ end
186
+ end)
187
+ end
188
+
189
+ -- Respawn listener (bound to connection tracker)
190
+ function c:onRespawn(fn)
191
+ local key = "__respawn_" .. name
192
+ local existing = self._connections[key]
193
+ if existing then
194
+ pcall(function() existing:Disconnect() end)
195
+ end
196
+ self._connections[key] = game:GetService("Players").LocalPlayer
197
+ .CharacterAdded:Connect(fn)
198
+ end
199
+
200
+ -- Lifecycle
201
+ function c:mount()
202
+ if self._mounted then return end
203
+ self._mounted = true
204
+ if Pulse.Log then Pulse.Log.trace("component", name .. " mounted") end
205
+ end
206
+
207
+ function c:unmount()
208
+ if not self._mounted then return end
209
+ self._mounted = false
210
+ self:unbindAll()
211
+ for _, unsub in ipairs(self._watchers) do pcall(unsub) end
212
+ self._watchers = {}
213
+ for _, cancel in ipairs(self._tasks) do pcall(cancel) end
214
+ self._tasks = {}
215
+ if Pulse.Log then Pulse.Log.trace("component", name .. " unmounted") end
216
+ end
217
+
218
+ -- Register: support "Shifter.Combat" style namespace
219
+ local parts = {}
220
+ for part in name:gmatch("[^%.]+") do table.insert(parts, part) end
221
+
222
+ _Registry[name] = c
223
+
224
+ local node = _NamespaceReg
225
+ for i, part in ipairs(parts) do
226
+ if i == #parts then
227
+ node[part] = c
228
+ else
229
+ node[part] = node[part] or {}
230
+ node = node[part]
231
+ end
232
+ end
233
+
234
+ return c
235
+ end
236
+
237
+ -- ── Store ────────────────────────────────────────────────────────────────────
238
+ -- Shared state with signals + actions.
239
+ -- Built by transpiler-generated setup calls; this is the constructor.
240
+
241
+ local _Stores = {}
242
+
243
+ local function Store(name)
244
+ local s = {}
245
+ s._isStore = true
246
+ s._name = name
247
+ s._signals = {}
248
+ s._actions = {}
249
+
250
+ -- Add a signal slice
251
+ function s:addSignal(key, default)
252
+ local sig = Signal(default)
253
+ sig._name = name .. "." .. key
254
+ self[key] = sig
255
+ self._signals[key] = sig
256
+ end
257
+
258
+ -- Register an action (only way to write store state from outside)
259
+ function s:addAction(key, fn)
260
+ self[key] = fn
261
+ self._actions[key] = fn
262
+ end
263
+
264
+ _Stores[name] = s
265
+ return s
266
+ end
267
+
268
+ -- ── Framework character globals ──────────────────────────────────────────────
269
+ -- Always available in on-blocks via transpiler-generated local mirrors.
270
+ -- Live lookups — never cached, always correct across respawn.
271
+
272
+ local _Players = game:GetService("Players")
273
+ local _RunService = game:GetService("RunService")
274
+ local _UIS = game:GetService("UserInputService")
275
+ local _VIM = game:GetService("VirtualInputManager")
276
+ local _LocalPlayer = _Players.LocalPlayer
277
+
278
+ -- ── Destroy ──────────────────────────────────────────────────────────────────
279
+ -- _PulseDestroy() — stop all components, tear down UI, clear _G entry.
280
+ -- _PulseOnDestroy(fn) — register a teardown callback (UI adapter uses this).
281
+
282
+ local _destroyCallbacks = {}
283
+
284
+ local function _PulseRegisterDestroy(fn)
285
+ table.insert(_destroyCallbacks, fn)
286
+ end
287
+
288
+ local function _PulseDestroyAll()
289
+ -- Teardown callbacks first (UI must be destroyed before connections drop)
290
+ for _, cb in ipairs(_destroyCallbacks) do pcall(cb) end
291
+ _destroyCallbacks = {}
292
+ -- Unmount every component: disconnects all Roblox connections + cancels tasks
293
+ for _, comp in pairs(_Registry) do
294
+ pcall(function() comp:unmount() end)
295
+ end
296
+ _G.__AOT_R_DESTROY = nil
297
+ end
298
+
299
+ -- ── Pulse namespace ──────────────────────────────────────────────────────────
300
+ -- Pulse.* helpers are injected from rb/pulse/helpers/ immediately after this.
301
+
302
+ local Pulse = {}
303
+
304
+ -- ── Global exports ───────────────────────────────────────────────────────────
305
+
306
+ Signal = Signal
307
+ Computed = Computed
308
+ PulseEvent = PulseEvent
309
+ Component = Component
310
+ Store = Store
311
+ Components = _NamespaceReg -- Components.Aimbot.enabled()
312
+ Pulse = Pulse -- Pulse.Log / .Draw / .Cache / .Track / .World / .Aim / .Memory / …
313
+
314
+ -- Internal accessors used by transpiler-generated code.
315
+ -- Read _LocalPlayer.Character directly every call — no stale cache after respawn.
316
+ _PulseGetChar = function()
317
+ return _LocalPlayer.Character
318
+ end
319
+ _PulseGetHRP = function()
320
+ local c = _LocalPlayer.Character
321
+ return c and c:FindFirstChild("HumanoidRootPart")
322
+ end
323
+ _PulseGetHumanoid = function()
324
+ local c = _LocalPlayer.Character
325
+ return c and c:FindFirstChild("Humanoid")
326
+ end
327
+ _PulseGetAlive = function()
328
+ local c = _LocalPlayer.Character
329
+ local h = c and c:FindFirstChild("Humanoid")
330
+ return h ~= nil and h.Health > 0
331
+ end
332
+
333
+ -- RS / UIS shortcuts used in transpiler-generated bind calls
334
+ _PulseRS = _RunService
335
+ _PulseUIS = _UIS
336
+
337
+ -- Destroy API — used by Settings page button and re-execution guard
338
+ _PulseOnDestroy = _PulseRegisterDestroy
339
+ _PulseDestroy = _PulseDestroyAll
340
+
341
+ -- Ordered list of { type, id, value } entries populated by transpiler-generated code.
342
+ -- Consumed by the compiler-generated defaults runner at end of script.
343
+ _PULSE_DEFAULTS = {}
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,87 @@
1
+ -- [pulse/ui/windui_settings.lua]
2
+ -- Framework-managed Settings tab for Wind UI builds.
3
+ -- Injected automatically by the compiler when ui_library = "windui".
4
+ -- Do not copy this file into src/ — edit it here in rb/pulse/ui/.
5
+ do
6
+ -- ── Appearance ────────────────────────────────────────────────────────────
7
+ local gb_appear = _GetGroupbox("Settings", "left", "Appearance")
8
+
9
+ -- Theme list: live from WindUI (picks up custom themes from layout too),
10
+ -- with a static fallback for all 16 built-in names if GetThemes() is unavailable.
11
+ local _themeValues = _UIAdapter:GetThemeNames()
12
+ or { "Amber","CottonCandy","Crimson","Dark","Emerald","Indigo","Light",
13
+ "Mellowsi","Midnight","MonokaiPro","Plant","Rainbow","Red","Rose","Sky","Violet" }
14
+ gb_appear._container:Dropdown({
15
+ Title = "Theme",
16
+ Values = _themeValues,
17
+ Value = _PULSE_DEFAULT_THEME,
18
+ Flag = "Settings_theme",
19
+ Callback = function(v) _UIAdapter:SetTheme(v) end,
20
+ })
21
+
22
+ -- ── Config ────────────────────────────────────────────────────────────────
23
+ local gb_cfg = _GetGroupbox("Settings", "left", "Configuration")
24
+
25
+ _UIAdapter:addParagraph(gb_cfg,
26
+ "Config is stored in your executor's filesystem.",
27
+ "Save writes the current state. Load restores the last saved state."
28
+ )
29
+
30
+ gb_cfg._container:Button({
31
+ Title = "Save Config",
32
+ Icon = "save",
33
+ Callback = function()
34
+ if _UIAdapter.Config then
35
+ local ok, err = pcall(function() _UIAdapter.Config:Save() end)
36
+ _PulseNotify(ok and "Config saved." or ("Save failed: " .. tostring(err)), 3)
37
+ else
38
+ _PulseNotify("Config manager unavailable.", 3)
39
+ end
40
+ end,
41
+ })
42
+
43
+ gb_cfg._container:Button({
44
+ Title = "Load Config",
45
+ Icon = "folder-open",
46
+ Callback = function()
47
+ if _UIAdapter.Config then
48
+ local ok, err = pcall(function() _UIAdapter.Config:Load() end)
49
+ _PulseNotify(ok and "Config loaded." or ("Load failed: " .. tostring(err)), 3)
50
+ else
51
+ _PulseNotify("Config manager unavailable.", 3)
52
+ end
53
+ end,
54
+ })
55
+
56
+ -- ── Menu Settings ─────────────────────────────────────────────────────────
57
+ local gb_menu = _GetGroupbox("Settings", "right", "Menu Settings")
58
+
59
+ _UIAdapter:addButton(gb_menu, {
60
+ label = "Destroy UI",
61
+ action = function() _PulseDestroy() end,
62
+ tip = "Unloads the script and removes all UI",
63
+ })
64
+
65
+ _UIAdapter:addKeybind(gb_menu, "Settings_MenuKeybind", {
66
+ label = "Menu Toggle",
67
+ key = _PULSE_TOGGLE_KEY,
68
+ action = function() _UIAdapter:ToggleWindow() end,
69
+ })
70
+
71
+ -- ── Auto-load saved config on startup ─────────────────────────────────────
72
+ task.spawn(function()
73
+ task.wait(1.5)
74
+ if _UIAdapter.Config then
75
+ local ok = pcall(function() _UIAdapter.Config:Load() end)
76
+ if ok then Pulse.Log.info("settings", "config auto-loaded") end
77
+ end
78
+ end)
79
+
80
+ -- ── Re-select first tab (Home) — Settings is injected last so WindUI
81
+ -- leaves it active; defer one frame so all tabs are fully built.
82
+ task.defer(function()
83
+ if _UIAdapter._firstTab then
84
+ pcall(function() _UIAdapter._firstTab:Select() end)
85
+ end
86
+ end)
87
+ end