sensivity 2.5.41 → 2.5.43
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.
- package/cli +54 -0
- package/cli.js +54 -0
- package/launcher.js +25 -280
- package/package.json +15 -8
- package/public/css/style.css +252 -966
- package/public/index.html +7 -15
- package/public/js/app.js +62 -482
- package/public/js/config_schema.js +10 -28
- package/sens.node +0 -0
- package/server.obf.js +1 -1
- package/public/assets/logo.png +0 -0
package/public/index.html
CHANGED
|
@@ -10,16 +10,12 @@
|
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
|
|
13
|
-
<div id="bg-brand" aria-hidden="true">
|
|
14
|
-
<span class="brand-mark m1">SENSIVITY<br>BEST PRIVATE</span>
|
|
15
|
-
<span class="brand-mark m2">SENSIVITY<br>BEST PRIVATE</span>
|
|
16
|
-
<span class="brand-mark m3">SENSIVITY<br>BEST PRIVATE</span>
|
|
17
|
-
<span class="brand-mark m4">SENSIVITY<br>BEST PRIVATE</span>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
13
|
<div id="license-overlay">
|
|
21
14
|
<div id="license-box">
|
|
22
|
-
<
|
|
15
|
+
<svg class="logo-icon" viewBox="0 0 24 24">
|
|
16
|
+
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z"/>
|
|
17
|
+
<path d="M9 12l2 2 4-4"/>
|
|
18
|
+
</svg>
|
|
23
19
|
<h1>Sensivity <span>License</span></h1>
|
|
24
20
|
<p class="subtitle">Enter your key to unlock</p>
|
|
25
21
|
<input type="text" id="license-key" placeholder="SENSIVITY-XXXX-XXXX-XXXX-XXXX-XXXXXXXX" onkeydown="if(event.key==='Enter')submitLicense()">
|
|
@@ -32,19 +28,15 @@
|
|
|
32
28
|
<div id="sidebar"></div>
|
|
33
29
|
<div id="content">
|
|
34
30
|
<div id="topbar"></div>
|
|
35
|
-
<div id="
|
|
36
|
-
<div id="pages"></div>
|
|
37
|
-
<aside id="esp-preview-shell"></aside>
|
|
38
|
-
</div>
|
|
31
|
+
<div id="pages"></div>
|
|
39
32
|
</div>
|
|
40
33
|
</div>
|
|
41
|
-
<div id="debug-toast" role="status" aria-live="polite"></div>
|
|
42
34
|
<div id="statusbar">
|
|
43
35
|
<span class="s-dot" id="status-dot"></span>
|
|
44
36
|
<span class="s-text" id="status-text">Ready</span>
|
|
45
37
|
<span class="s-url" id="s-url" style="flex:1;font-size:10px;color:var(--text3);text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:none"></span>
|
|
46
|
-
<button class="s-btn" id="cheat-btn" onclick="toggleCheat()" disabled>Start</button>
|
|
47
|
-
<button class="s-btn
|
|
38
|
+
<button class="s-btn" id="cheat-btn" onclick="toggleCheat()" disabled>Start Cheat</button>
|
|
39
|
+
<button class="s-btn" style="background:var(--bg4);color:var(--text2);margin-left:4px;padding:5px 10px;font-size:10px" onclick="killSensivity()">Kill</button>
|
|
48
40
|
</div>
|
|
49
41
|
|
|
50
42
|
<svg style="display:none" id="icons-sprite" xmlns="http://www.w3.org/2000/svg">
|
package/public/js/app.js
CHANGED
|
@@ -1,527 +1,107 @@
|
|
|
1
1
|
const SOCKET = (typeof io !== 'undefined') ? io() : null;
|
|
2
2
|
let state = {}, currentSection = 0, currentSub = 0;
|
|
3
3
|
let licenseAccepted = false, cheatRunning = false, listeningKeybind = null;
|
|
4
|
-
let espSyncTimer = null;
|
|
5
|
-
let startWatchTimer = null, startPending = false;
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
{ label: 'AIMBOT', ids: ['aim'] },
|
|
9
|
-
{ label: 'TOOLS', ids: ['misc'] },
|
|
10
|
-
{ label: 'VISUALS', ids: ['visuals'] },
|
|
11
|
-
{ label: 'PLAYERS', ids: ['playerlist', 'vehiclelist'] },
|
|
12
|
-
{ label: 'WORLD', ids: ['world', 'settings'] }
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
function svgIcon(id, size) {
|
|
16
|
-
size = size || 18;
|
|
17
|
-
return `<svg width="${size}" height="${size}"><use href="#ic-${id}"></use></svg>`;
|
|
18
|
-
}
|
|
5
|
+
function svgIcon(id, size) { size = size || 18; return `<svg width="${size}" height="${size}"><use href="#ic-${id}"></use></svg>`; }
|
|
19
6
|
|
|
20
7
|
function initState() {
|
|
21
8
|
if (!SCHEMA) return;
|
|
22
|
-
SCHEMA.sections.forEach(s => (s.subs || []).forEach(sub => (sub.children || []).forEach(ch => (ch.controls || []).forEach(c => {
|
|
23
|
-
if (!(c.key in state)) state[c.key] = c.type === 'color_checkbox' ? { value: c.def, color: [...(c.color || [1,
|
|
24
|
-
}))));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function sectionById(id) {
|
|
28
|
-
return SCHEMA.sections.findIndex(s => s.id === id);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function currentSubData() {
|
|
32
|
-
const s = SCHEMA.sections[currentSection];
|
|
33
|
-
return ((s && s.subs) || [])[currentSub] || ((s && s.subs) || [])[0];
|
|
9
|
+
SCHEMA.sections.forEach(s => { (s.subs || []).forEach(sub => { (sub.children || []).forEach(ch => { (ch.controls || []).forEach(c => {
|
|
10
|
+
if (!(c.key in state)) state[c.key] = c.type === 'color_checkbox' ? { value: c.def, color: [...(c.color || [1,1,1,1])] } : c.def;
|
|
11
|
+
});});});});
|
|
34
12
|
}
|
|
35
13
|
|
|
36
14
|
function renderSidebar() {
|
|
37
15
|
const el = document.getElementById('sidebar');
|
|
38
16
|
if (!SCHEMA) return;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (index < 0) return '';
|
|
43
|
-
const s = SCHEMA.sections[index];
|
|
44
|
-
return `<button class="tab-btn${index === currentSection ? ' active' : ''}" onclick="setSection(${index})" title="${s.label}">
|
|
45
|
-
<span class="tab-ico">${svgIcon(s.icon, 18)}</span>
|
|
46
|
-
<span class="tab-label">${s.label}</span>
|
|
47
|
-
</button>`;
|
|
48
|
-
}).join('');
|
|
49
|
-
return items ? `<div class="nav-group"><div class="nav-heading">${group.label}</div>${items}</div>` : '';
|
|
50
|
-
}).join('');
|
|
51
|
-
|
|
52
|
-
el.innerHTML = `
|
|
53
|
-
<div class="brand"><img src="/assets/logo.png" alt="Sensivity"><span>SENSIVITY</span></div>
|
|
54
|
-
<div class="nav-scroll">${grouped}</div>`;
|
|
17
|
+
el.innerHTML = SCHEMA.sections.map((s, i) =>
|
|
18
|
+
`<button class="tab-btn${i===currentSection?' active':''}" onclick="setSection(${i})" title="${s.label}">${svgIcon(s.icon,19)}</button>`
|
|
19
|
+
).join('');
|
|
55
20
|
}
|
|
56
21
|
|
|
57
22
|
function renderTopbar() {
|
|
58
|
-
const s = SCHEMA.sections[currentSection];
|
|
59
|
-
const subs = s.subs || [];
|
|
60
|
-
const sub = currentSubData();
|
|
23
|
+
const s = SCHEMA.sections[currentSection], subs = s.subs || [], sub = subs[currentSub] || subs[0];
|
|
61
24
|
document.getElementById('topbar').innerHTML = `
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<span class="top-primary">${s.label}</span>
|
|
66
|
-
<span class="top-secondary">${sub ? sub.label : ''}</span>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
<div class="sub-tabs">
|
|
70
|
-
${subs.map((x, i) => `<button class="sub-tab${i === currentSub ? ' active' : ''}" onclick="setSub(${i})">${x.label}</button>`).join('')}
|
|
71
|
-
</div>
|
|
72
|
-
<div class="profile-dot"><img src="/assets/logo.png" alt=""></div>`;
|
|
25
|
+
${sub&&sub.icon?`<span class="tb-icon">${svgIcon(sub.icon,16)}</span>`:''}
|
|
26
|
+
<span class="title">${s.label}</span><span class="sep">/</span><span class="sub">${sub?sub.label:''}</span>
|
|
27
|
+
${subs.length>1?`<select onchange="setSub(this.value)">${subs.map((x,i)=>`<option value="${i}"${i===currentSub?' selected':''}>${x.label}</option>`).join('')}</select>`:''}`;
|
|
73
28
|
}
|
|
74
29
|
|
|
75
30
|
function renderPage() {
|
|
76
|
-
const sub =
|
|
31
|
+
const sub = (SCHEMA.sections[currentSection].subs||[])[currentSub];
|
|
77
32
|
const pg = document.getElementById('pages');
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (workspace) workspace.classList.toggle('has-preview', showPreview);
|
|
81
|
-
if (!sub || !sub.children || !sub.children.length) {
|
|
82
|
-
pg.innerHTML = '<div class="child empty-state">No settings</div>';
|
|
83
|
-
renderEspPreviewShell(false);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const children = sub.children.map(ch => `<div class="child"><h3>${ch.label}</h3>${(ch.controls || []).map(ctrl).join('')}</div>`).join('');
|
|
88
|
-
pg.innerHTML = children;
|
|
89
|
-
renderEspPreviewShell(showPreview);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function prettyLabel(key) {
|
|
93
|
-
return String(key).replace(/^Enable\s+/i, '').replace(/\s+ESP$/i, ' ESP');
|
|
33
|
+
if (!sub||!sub.children||!sub.children.length) { pg.innerHTML='<div class="child" style="grid-column:1/-1;text-align:center;padding:40px;color:var(--text3)">No settings</div>'; return; }
|
|
34
|
+
pg.innerHTML = sub.children.map(ch=>`<div class="child"><h3>${ch.label}</h3>${(ch.controls||[]).map(ctrl).join('')}</div>`).join('');
|
|
94
35
|
}
|
|
95
36
|
|
|
96
37
|
function ctrl(c) {
|
|
97
|
-
const v = state[c.key];
|
|
98
|
-
|
|
99
|
-
const id = 'c_' + c.key.replace(/[^a-zA-Z0-9]/g, '_');
|
|
100
|
-
switch (c.type) {
|
|
38
|
+
const v = state[c.key], vs = c.type==='color_checkbox'?v?.value:v, id = 'c_'+c.key.replace(/[^a-zA-Z0-9]/g,'_');
|
|
39
|
+
switch(c.type) {
|
|
101
40
|
case 'checkbox':
|
|
102
|
-
return `<div class="ctrl"><label>${
|
|
41
|
+
return `<div class="ctrl"><label>${c.key}</label><label class="tgl"><input type="checkbox" id="${id}"${vs?' checked':''} onchange="set('${c.key}','checkbox',this.checked)"><span class="track"><span class="knob"></span></span></label></div>`;
|
|
103
42
|
case 'slider_int':
|
|
104
|
-
return `<div class="ctrl
|
|
43
|
+
return `<div class="ctrl"><label>${c.key}</label><div class="rng"><input type="range" id="${id}" min="${c.min||0}" max="${c.max||100}" value="${vs||0}" oninput="sliderUp('${c.key}','slider_int',this)"><span class="rng-val">${vs||0}</span></div></div>`;
|
|
105
44
|
case 'slider_float':
|
|
106
|
-
return `<div class="ctrl
|
|
45
|
+
return `<div class="ctrl"><label>${c.key}</label><div class="rng"><input type="range" id="${id}" min="${c.min||0}" max="${c.max||100}" step="${c.step||0.1}" value="${vs||0}" oninput="sliderUp('${c.key}','slider_float',this)"><span class="rng-val">${parseFloat(vs||0).toFixed(1)}</span></div></div>`;
|
|
107
46
|
case 'dropdown':
|
|
108
|
-
return `<div class="ctrl"><label>${
|
|
109
|
-
case 'color_checkbox':
|
|
110
|
-
const clr = v?.color
|
|
111
|
-
return `<div class="ctrl
|
|
112
|
-
}
|
|
47
|
+
return `<div class="ctrl"><label>${c.key}</label><select id="${id}" onchange="set('${c.key}','dropdown',this.selectedIndex)">${(c.items||[]).map((x,i)=>`<option value="${i}"${i===vs?' selected':''}>${x}</option>`).join('')}</select></div>`;
|
|
48
|
+
case 'color_checkbox':{
|
|
49
|
+
const clr = v?.color||[1,1,1,1], hex = '#'+clr.slice(0,3).map(x=>('0'+Math.round(x*255).toString(16)).slice(-2)).join('');
|
|
50
|
+
return `<div class="ctrl"><label>${c.key}</label><label class="tgl"><input type="checkbox"${v?.value?' checked':''} onchange="set('${c.key}','color_checkbox',{value:this.checked,color:(state['${c.key}']?.color||[1,1,1,1])})"><span class="track"><span class="knob"></span></span></label><span class="clr-btn" style="background:${hex}"><span class="swatch" style="background:${hex}"></span><input type="color" value="${hex}" onchange="colorUp('${c.key}',this.value)"></span></div>`;}
|
|
113
51
|
case 'keybind':
|
|
114
|
-
return `<div class="ctrl"><label>${
|
|
115
|
-
|
|
116
|
-
return `<div class="ctrl action-row"><label>${c.label || prettyLabel(c.key)}</label><button class="key-btn action-btn" id="${id}" onclick="runAction('${c.action || c.key}')">${c.button || 'Run'}</button></div>`;
|
|
117
|
-
}
|
|
118
|
-
return '';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function set(k, t, v) {
|
|
122
|
-
if (t === 'color_checkbox') {
|
|
123
|
-
state[k] = state[k] || { value: false, color: [1, 1, 1, 1] };
|
|
124
|
-
if (typeof v === 'object') state[k] = v;
|
|
125
|
-
} else state[k] = v;
|
|
126
|
-
if (shouldAutoEnablePlayerEsp(k, t, state[k])) {
|
|
127
|
-
state['Enable ESP'] = true;
|
|
128
|
-
emit('Enable ESP', 'checkbox', true);
|
|
129
|
-
}
|
|
130
|
-
emit(k, t, state[k]);
|
|
131
|
-
queuePlayerEspSync(k);
|
|
132
|
-
rerender();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function sliderUp(k, t, el) {
|
|
136
|
-
const v = t === 'slider_int' ? parseInt(el.value) : parseFloat(el.value);
|
|
137
|
-
state[k] = v;
|
|
138
|
-
el.previousElementSibling.textContent = t === 'slider_int' ? v : v.toFixed(1);
|
|
139
|
-
updateRangeFill(el);
|
|
140
|
-
emit(k, t, v);
|
|
141
|
-
queuePlayerEspSync(k);
|
|
142
|
-
if (shouldShowEspPreview()) updateEspPreview();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function colorUp(k, hex) {
|
|
146
|
-
const r = parseInt(hex.slice(1, 3), 16) / 255, g = parseInt(hex.slice(3, 5), 16) / 255, b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
147
|
-
const cur = state[k] || { value: false, color: [1, 1, 1, 1] };
|
|
148
|
-
cur.color = [r, g, b, cur.color[3] || 1];
|
|
149
|
-
state[k] = cur;
|
|
150
|
-
emit(k, 'color_checkbox', cur);
|
|
151
|
-
queuePlayerEspSync(k);
|
|
152
|
-
rerender();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function emit(k, t, v) {
|
|
156
|
-
if (SOCKET && SOCKET.connected) SOCKET.emit('setConfig', { key: k, type: t, value: v });
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function runAction(action) {
|
|
160
|
-
if (!SOCKET || !SOCKET.connected) {
|
|
161
|
-
showPanelDebug('Panel connection unavailable');
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
SOCKET.emit('performAction', { action });
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function rangePercent(c, value) {
|
|
168
|
-
const min = Number(c.min || 0);
|
|
169
|
-
const max = Number(c.max || 100);
|
|
170
|
-
const val = Number(value || 0);
|
|
171
|
-
if (max <= min) return 0;
|
|
172
|
-
return Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100)).toFixed(2);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function updateRangeFill(el) {
|
|
176
|
-
const min = Number(el.min || 0);
|
|
177
|
-
const max = Number(el.max || 100);
|
|
178
|
-
const val = Number(el.value || 0);
|
|
179
|
-
const pct = max <= min ? 0 : Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100));
|
|
180
|
-
el.style.setProperty('--range-percent', pct.toFixed(2) + '%');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function visualPlayerControls() {
|
|
184
|
-
const visuals = SCHEMA.sections.find(s => s.id === 'visuals');
|
|
185
|
-
const player = visuals && (visuals.subs || []).find(sub => sub.id === 'vplayer');
|
|
186
|
-
if (!player) return [];
|
|
187
|
-
return (player.children || []).flatMap(ch => ch.controls || []);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function shouldAutoEnablePlayerEsp(key, type, value) {
|
|
191
|
-
if (key === 'Enable ESP' || type !== 'color_checkbox') return false;
|
|
192
|
-
if (!visualPlayerControls().some(c => c.key === key)) return false;
|
|
193
|
-
return !!(value && value.value) && !state['Enable ESP'];
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function queuePlayerEspSync(changedKey) {
|
|
197
|
-
const controls = visualPlayerControls();
|
|
198
|
-
if (!controls.some(c => c.key === changedKey)) return;
|
|
199
|
-
clearTimeout(espSyncTimer);
|
|
200
|
-
espSyncTimer = setTimeout(() => {
|
|
201
|
-
controls.forEach(c => {
|
|
202
|
-
if (state[c.key] !== undefined) emit(c.key, c.type, state[c.key]);
|
|
203
|
-
});
|
|
204
|
-
}, 35);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function setSection(i) {
|
|
208
|
-
currentSection = i;
|
|
209
|
-
currentSub = 0;
|
|
210
|
-
rerender();
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function setSub(i) {
|
|
214
|
-
currentSub = parseInt(i, 10);
|
|
215
|
-
rerender();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function rerender() {
|
|
219
|
-
renderSidebar();
|
|
220
|
-
renderTopbar();
|
|
221
|
-
renderPage();
|
|
52
|
+
return `<div class="ctrl"><label>${c.key}</label><button class="key-btn${listeningKeybind===c.key?' listening':''}" id="${id}" onclick="keyStart('${c.key}')">${vkName(vs||0)}</button></div>`;
|
|
53
|
+
}return '';
|
|
222
54
|
}
|
|
223
55
|
|
|
224
|
-
function
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
for (let i = 112; i <= 135; i++) m[i] = 'F' + (i - 111);
|
|
230
|
-
return m[vk] || ('VK' + vk);
|
|
231
|
-
}
|
|
56
|
+
function set(k,t,v){ if(t==='color_checkbox'){state[k]=state[k]||{value:false,color:[1,1,1,1]};if(typeof v==='object')state[k]=v;}else state[k]=v; emit(k,t,state[k]); rerender(); }
|
|
57
|
+
function sliderUp(k,t,el){ const v=t==='slider_int'?parseInt(el.value):parseFloat(el.value); state[k]=v; el.nextElementSibling.textContent=t==='slider_int'?v:v.toFixed(1); emit(k,t,v); }
|
|
58
|
+
function colorUp(k,hex){ const r=parseInt(hex.slice(1,3),16)/255,g=parseInt(hex.slice(3,5),16)/255,b=parseInt(hex.slice(5,7),16)/255; const cur=state[k]||{value:false,color:[1,1,1,1]}; cur.color=[r,g,b,cur.color[3]||1]; state[k]=cur; emit(k,'color_checkbox',cur); rerender(); }
|
|
59
|
+
function emit(k,t,v){ if(SOCKET&&SOCKET.connected) SOCKET.emit('setConfig',{key:k,type:t,value:v}); }
|
|
60
|
+
function setSection(i){ currentSection=i;currentSub=0;rerender(); } function setSub(i){ currentSub=parseInt(i);rerender(); }
|
|
232
61
|
|
|
233
|
-
function
|
|
234
|
-
if (listeningKeybind === key) {
|
|
235
|
-
listeningKeybind = null;
|
|
236
|
-
rerender();
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
listeningKeybind = key;
|
|
240
|
-
rerender();
|
|
241
|
-
}
|
|
62
|
+
function rerender(){ renderSidebar();renderTopbar();renderPage(); }
|
|
242
63
|
|
|
243
|
-
function
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
b.textContent = 'Checking...';
|
|
249
|
-
m.textContent = '';
|
|
250
|
-
m.className = 'msg';
|
|
251
|
-
if (SOCKET) SOCKET.emit('checkLicense', k);
|
|
64
|
+
function vkName(vk){
|
|
65
|
+
const m={0:'None',1:'LMB',2:'RMB',4:'MMB',5:'XB1',6:'XB2',8:'Back',9:'Tab',13:'Enter',16:'Shift',17:'Ctrl',18:'Alt',20:'Caps',27:'Esc',32:'Space',33:'PgUp',34:'PgDn',37:'Left',38:'Up',39:'Right',40:'Down',44:'PrtSc',45:'Ins',46:'Del',160:'LShift',161:'RShift',162:'LCtrl',163:'RCtrl',164:'LAlt',165:'RAlt'};
|
|
66
|
+
for(let i=48;i<=57;i++)m[i]=String(i-48); for(let i=65;i<=90;i++)m[i]=String.fromCharCode(i);
|
|
67
|
+
for(let i=96;i<=105;i++)m[i]='Num'+String(i-96); for(let i=112;i<=135;i++)m[i]='F'+(i-111);
|
|
68
|
+
return m[vk]||('VK'+vk);
|
|
252
69
|
}
|
|
253
70
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
e.preventDefault();
|
|
257
|
-
set(listeningKeybind, 'keybind', e.keyCode);
|
|
258
|
-
listeningKeybind = null;
|
|
259
|
-
rerender();
|
|
260
|
-
});
|
|
71
|
+
function keyStart(key){ if(listeningKeybind===key){listeningKeybind=null;rerender();return;} listeningKeybind=key;rerender(); }
|
|
72
|
+
function submitLicense(){ const k=document.getElementById('license-key').value.trim(); if(!k)return; const b=document.getElementById('license-btn'),m=document.getElementById('license-msg'); b.disabled=true;b.textContent='Checking...';m.textContent='';m.className='msg'; if(SOCKET)SOCKET.emit('checkLicense',k); }
|
|
261
73
|
|
|
262
|
-
document.addEventListener('
|
|
263
|
-
|
|
264
|
-
e.preventDefault();
|
|
265
|
-
set(listeningKeybind, 'keybind', { 0: 1, 1: 4, 2: 2 }[e.button] || 0);
|
|
266
|
-
listeningKeybind = null;
|
|
267
|
-
rerender();
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
function toggleCheat() {
|
|
271
|
-
if (!SOCKET) return;
|
|
272
|
-
const eventName = cheatRunning ? 'stopCheat' : 'startCheat';
|
|
273
|
-
if (eventName === 'startCheat') beginPanelStartWatch();
|
|
274
|
-
else clearPanelStartWatch();
|
|
275
|
-
SOCKET.emit(eventName);
|
|
276
|
-
if (!SOCKET.connected && typeof SOCKET.connect === 'function') {
|
|
277
|
-
showPanelDebug('Panel reconnecting before start');
|
|
278
|
-
SOCKET.connect();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
74
|
+
document.addEventListener('keydown',function(e){ if(!listeningKeybind)return; e.preventDefault(); set(listeningKeybind,'keybind',e.keyCode); listeningKeybind=null;rerender(); });
|
|
75
|
+
document.addEventListener('mousedown',function(e){ if(!listeningKeybind)return; e.preventDefault(); set(listeningKeybind,'keybind',{0:1,1:4,2:2}[e.button]||0); listeningKeybind=null;rerender(); });
|
|
281
76
|
|
|
282
|
-
function
|
|
283
|
-
|
|
284
|
-
clearTimeout(startWatchTimer);
|
|
285
|
-
clearPanelDebug();
|
|
286
|
-
updateStatus();
|
|
287
|
-
startWatchTimer = setTimeout(() => {
|
|
288
|
-
if (startPending && !cheatRunning) showPanelDebug('Program start did not confirm');
|
|
289
|
-
}, 90000);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function clearPanelStartWatch() {
|
|
293
|
-
startPending = false;
|
|
294
|
-
clearTimeout(startWatchTimer);
|
|
295
|
-
startWatchTimer = null;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function showPanelDebug(message) {
|
|
299
|
-
const el = document.getElementById('debug-toast');
|
|
300
|
-
if (!el) return;
|
|
301
|
-
el.textContent = message;
|
|
302
|
-
el.classList.add('show');
|
|
303
|
-
}
|
|
77
|
+
function toggleCheat(){ if(!SOCKET||!SOCKET.connected)return; SOCKET.emit(cheatRunning?'stopCheat':'startCheat'); }
|
|
78
|
+
function updateStatus(){ const d=document.getElementById('status-dot'),t=document.getElementById('status-text'),b=document.getElementById('cheat-btn'); if(cheatRunning){ d.className='s-dot live';t.textContent='Cheat running';b.textContent='Stop';b.className='s-btn stop';}else{ d.className='s-dot';t.textContent='Ready';b.textContent='Start Cheat';b.className='s-btn';} }
|
|
304
79
|
|
|
305
|
-
|
|
306
|
-
const el = document.getElementById('debug-toast');
|
|
307
|
-
if (!el) return;
|
|
308
|
-
el.textContent = '';
|
|
309
|
-
el.classList.remove('show');
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function updateStatus() {
|
|
313
|
-
const d = document.getElementById('status-dot'), t = document.getElementById('status-text'), b = document.getElementById('cheat-btn');
|
|
314
|
-
if (startPending && !cheatRunning) {
|
|
315
|
-
d.className = 's-dot live';
|
|
316
|
-
t.textContent = 'Sensivity Starting...';
|
|
317
|
-
b.textContent = 'Starting...';
|
|
318
|
-
b.className = 's-btn';
|
|
319
|
-
b.disabled = true;
|
|
320
|
-
} else if (cheatRunning) {
|
|
321
|
-
d.className = 's-dot live';
|
|
322
|
-
t.textContent = 'Running';
|
|
323
|
-
b.textContent = 'Stop';
|
|
324
|
-
b.className = 's-btn stop';
|
|
325
|
-
b.disabled = false;
|
|
326
|
-
} else {
|
|
327
|
-
d.className = 's-dot';
|
|
328
|
-
t.textContent = 'Ready';
|
|
329
|
-
b.textContent = 'Start';
|
|
330
|
-
b.className = 's-btn';
|
|
331
|
-
b.disabled = !licenseAccepted;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function colorToHex(color) {
|
|
336
|
-
return '#' + (color || [1, 1, 1]).slice(0, 3).map(x => ('0' + Math.round(Math.max(0, Math.min(1, x)) * 255).toString(16)).slice(-2)).join('');
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function ctrlValue(key) {
|
|
340
|
-
const v = state[key];
|
|
341
|
-
return v && typeof v === 'object' && 'value' in v ? v.value : v;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function ctrlColor(key, fallback) {
|
|
345
|
-
return colorToHex((state[key] && state[key].color) || fallback || [1, 1, 1, 1]);
|
|
346
|
-
}
|
|
80
|
+
if(SOCKET){ SOCKET.on('connect',()=>{fetch('/api/url').then(r=>r.json()).then(d=>{if(d.url)document.getElementById('s-url').textContent=d.url}).catch(()=>{});}); SOCKET.on('licenseResult',(r)=>{ const b=document.getElementById('license-btn'),m=document.getElementById('license-msg'); b.disabled=false;b.textContent='Authenticate'; if(r.ok){ licenseAccepted=true; m.textContent=r.message||'Accepted';m.className='msg ok'; document.getElementById('cheat-btn').disabled=false; setTimeout(()=>{document.getElementById('license-overlay').style.display='none';rerender();},300); }else{ m.textContent=r.message||'Invalid key';m.className='msg err'; } }); SOCKET.on('configSync',(c)=>{Object.assign(state,c);rerender();}); SOCKET.on('status',(s)=>{cheatRunning=s.running;updateStatus();}); SOCKET.on('killed',()=>{document.body.innerHTML='<div style="display:flex;align-items:center;justify-content:center;height:100vh;color:var(--danger);font-size:18px;font-family:var(--font)">Sensivity Terminated</div>';}); SOCKET.on('ytTrigger',(d)=>{const el=document.getElementById('qr-overlay');if(d.active){el.classList.add('show');document.getElementById('qr-url').textContent=d.url;document.getElementById('qr-img').src='/api/qr.png?'+Date.now();}else{el.classList.remove('show');}}); }
|
|
347
81
|
|
|
348
|
-
function
|
|
349
|
-
const section = SCHEMA.sections[currentSection];
|
|
350
|
-
const sub = currentSubData();
|
|
351
|
-
return section && section.id === 'visuals' && sub && sub.id === 'vplayer';
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function renderEspPreviewCard() {
|
|
355
|
-
return `<div class="esp-preview-panel"><h3>Live Preview</h3><div class="esp-stage" id="esp-stage">${espPreviewMarkup()}</div></div>`;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function renderEspPreviewShell(showPreview) {
|
|
359
|
-
const shell = document.getElementById('esp-preview-shell');
|
|
360
|
-
if (!shell) return;
|
|
361
|
-
shell.innerHTML = showPreview ? renderEspPreviewCard() : '';
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
function updateEspPreview() {
|
|
365
|
-
const stage = document.getElementById('esp-stage');
|
|
366
|
-
if (stage) stage.innerHTML = espPreviewMarkup();
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function placementClass(key) {
|
|
370
|
-
const map = ['bottom', 'top', 'left-upper', 'right-upper', 'left-lower', 'right-lower'];
|
|
371
|
-
return map[Number(state[key] || 0)] || 'bottom';
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function espPreviewMarkup() {
|
|
375
|
-
const espOn = !!ctrlValue('Enable ESP');
|
|
376
|
-
const boxOn = !!ctrlValue('Enable Box ESP');
|
|
377
|
-
const skeletonOn = !!ctrlValue('Enable Skeleton ESP');
|
|
378
|
-
const headOn = !!ctrlValue('Enable Head ESP');
|
|
379
|
-
const lineOn = !!ctrlValue('Enable Line ESP');
|
|
380
|
-
const healthOn = !!ctrlValue('Enable Health Bar ESP');
|
|
381
|
-
const armorOn = !!ctrlValue('Enable Armor Bar ESP');
|
|
382
|
-
const tracerOn = !!ctrlValue('Enable Tracer ESP');
|
|
383
|
-
const offscreenOn = !!ctrlValue('Enable Offscreen ESP');
|
|
384
|
-
const nameOn = !!ctrlValue('Enable Name ESP');
|
|
385
|
-
const idOn = !!ctrlValue('Enable ID ESP');
|
|
386
|
-
const distOn = !!ctrlValue('Enable Distance ESP');
|
|
387
|
-
const weaponOn = !!ctrlValue('Enable Weapon ESP');
|
|
388
|
-
const boxColor = ctrlColor('Enable Box ESP');
|
|
389
|
-
const skelColor = ctrlColor('Enable Skeleton ESP');
|
|
390
|
-
const headColor = ctrlColor('Enable Head ESP');
|
|
391
|
-
const lineColor = ctrlColor('Enable Line ESP');
|
|
392
|
-
const healthColor = ctrlColor('Enable Health Bar ESP', [0, 1, 0, 1]);
|
|
393
|
-
const armorColor = ctrlColor('Enable Armor Bar ESP', [0, 0.45, 1, 1]);
|
|
394
|
-
const tracerColor = ctrlColor('Enable Tracer ESP');
|
|
395
|
-
const offscreenColor = ctrlColor('Enable Offscreen ESP', [1, 0, 0, 1]);
|
|
396
|
-
const boxType = Number(state['Box Type'] || 0);
|
|
397
|
-
const boxLine = Number(state['Box Line Type'] || 0);
|
|
398
|
-
const skeletonLine = Number(state['Skeleton Line Type'] || 0);
|
|
399
|
-
const linePlacement = Number(state['Line Placement'] || 0);
|
|
400
|
-
const boxThickness = Number(state['Box Line Thickness'] || 1);
|
|
401
|
-
const skeletonThickness = Number(state['Skeleton Line Thickness'] || 1);
|
|
402
|
-
const headSize = Number(state['Head Size'] || 10);
|
|
403
|
-
const lineThickness = Number(state['Line Thickness'] || 1);
|
|
404
|
-
const tracerThickness = Number(state['Tracer Thickness'] || 2);
|
|
405
|
-
|
|
406
|
-
return `
|
|
407
|
-
<div class="esp-grid-bg"></div>
|
|
408
|
-
<div class="esp-horizon"></div>
|
|
409
|
-
<div class="esp-crosshair"></div>
|
|
410
|
-
<div class="esp-target ${espOn ? 'is-on' : 'is-off'}">
|
|
411
|
-
${boxOn ? `<div class="esp-box ${boxType ? 'corner' : 'full'} ${boxLine ? 'solid' : 'dashed'}" style="--esp-color:${boxColor};--esp-thick:${Math.max(1, Math.min(6, boxThickness))}px"></div>` : ''}
|
|
412
|
-
${healthOn ? `<div class="esp-bar health" style="--esp-color:${healthColor}"><span></span></div>` : ''}
|
|
413
|
-
${armorOn ? `<div class="esp-bar armor" style="--esp-color:${armorColor}"><span></span></div>` : ''}
|
|
414
|
-
${headOn ? `<div class="esp-head" style="--esp-color:${headColor};--head-size:${Math.max(8, Math.min(42, headSize))}px"></div>` : ''}
|
|
415
|
-
${skeletonOn ? `<div class="esp-skeleton ${skeletonLine ? 'solid' : 'dashed'}" style="--esp-color:${skelColor};--esp-thick:${Math.max(1, Math.min(6, skeletonThickness))}px"><span class="spine"></span><span class="arms"></span><span class="leg left"></span><span class="leg right"></span></div>` : ''}
|
|
416
|
-
${nameOn ? `<span class="esp-text ${placementClass('Name Placement')}" style="--esp-color:${ctrlColor('Enable Name ESP')}">Player_24</span>` : ''}
|
|
417
|
-
${idOn ? `<span class="esp-text ${placementClass('ID Placement')}" style="--esp-color:${ctrlColor('Enable ID ESP')}">ID 182</span>` : ''}
|
|
418
|
-
${distOn ? `<span class="esp-text ${placementClass('Distance Placement')}" style="--esp-color:${ctrlColor('Enable Distance ESP')}">128m</span>` : ''}
|
|
419
|
-
${weaponOn ? `<span class="esp-text ${placementClass('Weapon Placement')}" style="--esp-color:${ctrlColor('Enable Weapon ESP')}">Rifle</span>` : ''}
|
|
420
|
-
</div>
|
|
421
|
-
${lineOn ? `<div class="esp-line place-${linePlacement}" style="--esp-color:${lineColor};--esp-thick:${Math.max(1, Math.min(8, lineThickness))}px"></div>` : ''}
|
|
422
|
-
${tracerOn ? `<div class="esp-tracer" style="--esp-color:${tracerColor};--esp-thick:${Math.max(1, Math.min(8, tracerThickness))}px"></div>` : ''}
|
|
423
|
-
${offscreenOn ? `<div class="esp-offscreen" style="--esp-color:${offscreenColor}"></div>` : ''}
|
|
424
|
-
<div class="esp-caption">${espOn ? 'ESP Enabled' : 'ESP Disabled'}</div>`;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (SOCKET) {
|
|
428
|
-
SOCKET.on('connect', () => {
|
|
429
|
-
fetch('/api/url').then(r => r.json()).then(d => {
|
|
430
|
-
if (d.url) document.getElementById('s-url').textContent = d.url;
|
|
431
|
-
}).catch(() => {});
|
|
432
|
-
});
|
|
433
|
-
SOCKET.on('licenseResult', (r) => {
|
|
434
|
-
const b = document.getElementById('license-btn'), m = document.getElementById('license-msg');
|
|
435
|
-
b.disabled = false;
|
|
436
|
-
b.textContent = 'Authenticate';
|
|
437
|
-
if (r.ok) {
|
|
438
|
-
licenseAccepted = true;
|
|
439
|
-
m.textContent = r.message || 'Accepted';
|
|
440
|
-
m.className = 'msg ok';
|
|
441
|
-
document.getElementById('cheat-btn').disabled = false;
|
|
442
|
-
setTimeout(() => {
|
|
443
|
-
document.getElementById('license-overlay').style.display = 'none';
|
|
444
|
-
rerender();
|
|
445
|
-
}, 300);
|
|
446
|
-
} else {
|
|
447
|
-
m.textContent = r.message || 'Invalid key';
|
|
448
|
-
m.className = 'msg err';
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
SOCKET.on('configSync', (c) => { Object.assign(state, c); rerender(); });
|
|
452
|
-
SOCKET.on('actionResult', (r) => {
|
|
453
|
-
if (r && r.config) Object.assign(state, r.config);
|
|
454
|
-
if (r && r.ok) {
|
|
455
|
-
clearPanelDebug();
|
|
456
|
-
} else {
|
|
457
|
-
showPanelDebug((r && r.message) || 'Action failed');
|
|
458
|
-
}
|
|
459
|
-
rerender();
|
|
460
|
-
});
|
|
461
|
-
SOCKET.on('status', (s) => {
|
|
462
|
-
cheatRunning = s.running;
|
|
463
|
-
const debugMessage = s.debug || s.error || s.message || '';
|
|
464
|
-
if (s.starting) {
|
|
465
|
-
startPending = true;
|
|
466
|
-
clearPanelDebug();
|
|
467
|
-
} else if (cheatRunning) {
|
|
468
|
-
clearPanelStartWatch();
|
|
469
|
-
clearPanelDebug();
|
|
470
|
-
} else if (debugMessage) {
|
|
471
|
-
clearPanelStartWatch();
|
|
472
|
-
showPanelDebug(debugMessage);
|
|
473
|
-
} else if (startPending) {
|
|
474
|
-
showPanelDebug('Program inactive after start');
|
|
475
|
-
}
|
|
476
|
-
updateStatus();
|
|
477
|
-
});
|
|
478
|
-
SOCKET.on('disconnect', () => {
|
|
479
|
-
if (startPending) showPanelDebug('Panel connection lost during start');
|
|
480
|
-
});
|
|
481
|
-
SOCKET.on('connect_error', () => {
|
|
482
|
-
if (startPending) showPanelDebug('Panel connection failed during start');
|
|
483
|
-
});
|
|
484
|
-
SOCKET.on('killed', () => { document.body.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100vh;color:var(--danger);font-size:18px;font-family:var(--font)">Sensivity Terminated</div>'; });
|
|
485
|
-
SOCKET.on('ytTrigger', (d) => {
|
|
486
|
-
const el = document.getElementById('qr-overlay');
|
|
487
|
-
if (d.active) {
|
|
488
|
-
el.classList.add('show');
|
|
489
|
-
document.getElementById('qr-url').textContent = d.url;
|
|
490
|
-
document.getElementById('qr-img').src = '/api/qr.png?' + Date.now();
|
|
491
|
-
} else {
|
|
492
|
-
el.classList.remove('show');
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function killSensivity() {
|
|
498
|
-
if (!SOCKET || !SOCKET.connected) return;
|
|
499
|
-
SOCKET.emit('killSensivity');
|
|
500
|
-
}
|
|
82
|
+
function killSensivity(){ if(!SOCKET||!SOCKET.connected)return; SOCKET.emit('killSensivity'); }
|
|
501
83
|
|
|
502
84
|
function drawQR(url) {
|
|
503
|
-
const c
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
ctx.
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
ctx.fillRect((x + m) * s, (y + m) * s, s, s);
|
|
85
|
+
const c=document.getElementById('qr-canvas'),ctx=c.getContext('2d');
|
|
86
|
+
const s=8,m=4,qrSize=21;
|
|
87
|
+
c.width=c.height=(qrSize+2*m)*s;
|
|
88
|
+
ctx.fillStyle='#fff';ctx.fillRect(0,0,c.width,c.height);
|
|
89
|
+
// Simple QR drawing using pattern generator
|
|
90
|
+
const hash=Array.from(url).reduce((a,c)=>((a<<5)-a)+c.charCodeAt(0),0);
|
|
91
|
+
ctx.fillStyle='#000';
|
|
92
|
+
for(let y=0;y<qrSize;y++)for(let x=0;x<qrSize;x++){
|
|
93
|
+
const v=(hash>>((x*y)%31))&1;
|
|
94
|
+
// Simple finder patterns in corners
|
|
95
|
+
const fx=x<7&&y<7, f2=x>qrSize-8&&y<7, f3=x<7&&y>qrSize-8;
|
|
96
|
+
if(fx||f2||f3){
|
|
97
|
+
const ix=fx?x:f2?x-(qrSize-7):x, iy=fx?y:f2?y:y-(qrSize-7);
|
|
98
|
+
if(!(ix===0||ix===6||iy===0||iy===6||(ix>=2&&ix<=4&&iy>=2&&iy<=4)||ix===1||ix===5||iy===1||iy===5)){
|
|
99
|
+
ctx.fillRect((x+m)*s,(y+m)*s,s,s);
|
|
519
100
|
}
|
|
520
|
-
} else if
|
|
521
|
-
ctx.fillRect((x
|
|
101
|
+
} else if(v&&x>0&&y>0){
|
|
102
|
+
ctx.fillRect((x+m)*s,(y+m)*s,s,s);
|
|
522
103
|
}
|
|
523
104
|
}
|
|
524
105
|
}
|
|
525
106
|
|
|
526
|
-
initState();
|
|
527
|
-
rerender();
|
|
107
|
+
initState(); rerender();
|