perfectionist-plugins 2.4.5 → 2.4.7
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/README.md +2 -2
- package/auto-accept.js +11 -101
- package/ban-blocker.js +33 -5
- package/dodge-helper.js +835 -560
- package/hide-unowned-skins.js +3 -21
- package/package.json +40 -40
- package/perfectionist-utils.js +56 -20
package/README.md
CHANGED
|
@@ -22,8 +22,8 @@ Built for [Pengu Loader](https://pengu.lol)
|
|
|
22
22
|
| 🛡️ **Ban Blocker** | Adds a **BLOCK** button to your teammates in champ select. While a teammate is blocked, the champion they are about to ban is prepicked for you on your own pick turn, so their ban can never land on it. |
|
|
23
23
|
| 🔓 **Unlock Profile Skins** | In the **Set profile background** window, every skin shows as unlocked, even event skins (Signature). Browse the full list and pick any skin you like. |
|
|
24
24
|
| 🎨 **Hide Unowned Skins** | In champ select, the skin carousel only shows the skins you own for the champion you picked. The arrows and dots only move through owned skins, and the ones that are left keep their normal spacing. |
|
|
25
|
-
| ✅ **Auto Accept** | Accepts the match for you when the ready check pops up.
|
|
26
|
-
| 🚪 **Dodge Helper** | Adds a
|
|
25
|
+
| ✅ **Auto Accept** | Accepts the match for you when the ready check pops up. |
|
|
26
|
+
| 🚪 **Dodge Helper** | Adds a **DODGE** button in ranked Solo/Duo and Flex and a **QUIT** button in other modes, with the LP and queue-penalty cost of the next dodge. |
|
|
27
27
|
| 🎁 **Auto Claimer** | Claims rewards for you the moment they become claimable: event tracks, missions and the TFT Battle Pass. Three optional extras: auto-buy shop items Riot lists for 1 BE, auto-open mystery loot (icons, ward skins), and auto-open chests with keys. |
|
|
28
28
|
| 📬 **Auto Read** | Marks quests, loot, Clash, TFT and client notices as read, so no badge or dot stays lit. |
|
|
29
29
|
|
package/auto-accept.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
const PLUGIN_ID = "auto-accept";
|
|
2
|
-
export const version = "1.1.
|
|
2
|
+
export const version = "1.1.3";
|
|
3
3
|
|
|
4
4
|
const PHASE_URI = "/lol-gameflow/v1/gameflow-phase";
|
|
5
5
|
const READY_CHECK_URI = "/lol-matchmaking/v1/ready-check";
|
|
6
6
|
const ACCEPT_URI = "/lol-matchmaking/v1/ready-check/accept";
|
|
7
|
-
const
|
|
8
|
-
const DELAY_KEY = "perfectionist:auto-accept:delay";
|
|
9
|
-
const MAX_DELAY = 15000;
|
|
7
|
+
const ACCEPT_KEY = "autoAccept";
|
|
10
8
|
const RETRY_MS = 700;
|
|
11
9
|
const MAX_ATTEMPTS = 4;
|
|
12
10
|
const GAME_SELECT_GUARD_MS = 1500;
|
|
13
11
|
const STYLE_ID = "perf-auto-accept-style";
|
|
14
12
|
const ROOT_ID = "perfAutoAccept";
|
|
15
13
|
const TOGGLE_ID = "perfAutoAcceptToggle";
|
|
16
|
-
const DELAY_INPUT_ID = "perfAutoAcceptDelay";
|
|
17
14
|
|
|
18
15
|
const CSS = `#perfAutoAccept {
|
|
19
16
|
display: flex !important; flex-direction: row !important; flex-wrap: nowrap !important;
|
|
@@ -25,24 +22,7 @@ const CSS = `#perfAutoAccept {
|
|
|
25
22
|
font-family: var(--font-body, "LoL Body", Arial, sans-serif) !important;
|
|
26
23
|
font-size: 12px !important; letter-spacing: 0.3px !important; color: #a09b8c !important;
|
|
27
24
|
}
|
|
28
|
-
#perfAutoAccept .auto-accept-button[selected] .auto-accept-button-text { color: #f0e6d2 !important; }
|
|
29
|
-
#perfAutoAccept .auto-accept-delay {
|
|
30
|
-
display: flex !important; align-items: center !important; box-sizing: border-box !important;
|
|
31
|
-
width: 82px !important; height: 24px !important; margin-left: 0 !important;
|
|
32
|
-
background: #1e2328 !important; border: 1px solid #785a28 !important; border-radius: 0 !important;
|
|
33
|
-
transition: border-color 0.15s ease, background-color 0.15s ease !important;
|
|
34
|
-
}
|
|
35
|
-
#perfAutoAccept .auto-accept-delay:hover { border-color: #c89b3c !important; }
|
|
36
|
-
#perfAutoAccept .auto-accept-delay:focus-within { border-color: #c89b3c !important; background: #0a1428 !important; }
|
|
37
|
-
#perfAutoAccept .auto-accept-delay input {
|
|
38
|
-
width: 100% !important; height: 100% !important; box-sizing: border-box !important;
|
|
39
|
-
background: transparent !important; border: none !important; outline: none !important; box-shadow: none !important;
|
|
40
|
-
color: #f0e6d2 !important; font-family: var(--font-body, "LoL Body", Arial, sans-serif) !important;
|
|
41
|
-
font-size: 12px !important; letter-spacing: 0.3px !important; text-align: center !important; padding: 0 6px !important;
|
|
42
|
-
}
|
|
43
|
-
#perfAutoAccept .auto-accept-delay input::placeholder { color: #5b5a56 !important; }
|
|
44
|
-
#perfAutoAccept .auto-accept-delay input::-webkit-outer-spin-button,
|
|
45
|
-
#perfAutoAccept .auto-accept-delay input::-webkit-inner-spin-button { -webkit-appearance: none !important; margin: 0 !important; }`;
|
|
25
|
+
#perfAutoAccept .auto-accept-button[selected] .auto-accept-button-text { color: #f0e6d2 !important; }`;
|
|
46
26
|
|
|
47
27
|
let api = null;
|
|
48
28
|
let active = false;
|
|
@@ -54,28 +34,10 @@ let unsubscribes = [];
|
|
|
54
34
|
let removeStyle = null;
|
|
55
35
|
let domObserver = null;
|
|
56
36
|
let domTimer = null;
|
|
57
|
-
let delayValue = readDelay();
|
|
58
|
-
|
|
59
|
-
function readDelay() {
|
|
60
|
-
try {
|
|
61
|
-
const raw = Number(localStorage.getItem(DELAY_KEY));
|
|
62
|
-
if (!Number.isFinite(raw) || raw < 0) return 0;
|
|
63
|
-
return Math.min(Math.floor(raw), MAX_DELAY);
|
|
64
|
-
} catch {
|
|
65
|
-
return 0;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function writeDelay(value) {
|
|
70
|
-
delayValue = value;
|
|
71
|
-
try {
|
|
72
|
-
localStorage.setItem(DELAY_KEY, String(value));
|
|
73
|
-
} catch {}
|
|
74
|
-
}
|
|
75
37
|
|
|
76
38
|
function enabled() {
|
|
77
39
|
try {
|
|
78
|
-
return api?.getOption?.(PLUGIN_ID,
|
|
40
|
+
return api?.getOption?.(PLUGIN_ID, ACCEPT_KEY, true) === true;
|
|
79
41
|
} catch {
|
|
80
42
|
return false;
|
|
81
43
|
}
|
|
@@ -139,17 +101,11 @@ async function acceptNow() {
|
|
|
139
101
|
}
|
|
140
102
|
}
|
|
141
103
|
|
|
142
|
-
function queueAccept() {
|
|
143
|
-
if (!active || !enabled() || accepted || sending || timer) return;
|
|
144
|
-
if (delayValue > 0) timer = setTimeout(acceptNow, delayValue);
|
|
145
|
-
else acceptNow();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
104
|
function onPhase(raw) {
|
|
149
105
|
const phase = unwrap(raw);
|
|
150
106
|
if (typeof phase !== "string") return;
|
|
151
107
|
if (phase === "ReadyCheck") {
|
|
152
|
-
if (!accepted)
|
|
108
|
+
if (!accepted) acceptNow();
|
|
153
109
|
return;
|
|
154
110
|
}
|
|
155
111
|
resetReadyCheck();
|
|
@@ -167,13 +123,13 @@ function onReadyCheck(raw) {
|
|
|
167
123
|
resetReadyCheck();
|
|
168
124
|
return;
|
|
169
125
|
}
|
|
170
|
-
|
|
126
|
+
acceptNow();
|
|
171
127
|
}
|
|
172
128
|
|
|
173
129
|
async function refresh() {
|
|
174
130
|
const phase = unwrap(await api.lcu.get(PHASE_URI).catch(() => null));
|
|
175
131
|
if (!active) return;
|
|
176
|
-
if (phase === "ReadyCheck")
|
|
132
|
+
if (phase === "ReadyCheck") acceptNow();
|
|
177
133
|
else resetReadyCheck();
|
|
178
134
|
}
|
|
179
135
|
|
|
@@ -182,31 +138,18 @@ function syncButton() {
|
|
|
182
138
|
if (!option) return;
|
|
183
139
|
if (enabled()) option.setAttribute("selected", "true");
|
|
184
140
|
else option.removeAttribute("selected");
|
|
185
|
-
const field = document.getElementById(DELAY_INPUT_ID);
|
|
186
|
-
if (field && document.activeElement !== field) field.value = String(delayValue);
|
|
187
141
|
}
|
|
188
142
|
|
|
189
143
|
function toggle() {
|
|
190
144
|
const next = !enabled();
|
|
191
145
|
try {
|
|
192
|
-
api.setOption(PLUGIN_ID,
|
|
146
|
+
api.setOption(PLUGIN_ID, ACCEPT_KEY, next, false);
|
|
193
147
|
} catch {}
|
|
194
148
|
syncButton();
|
|
195
|
-
if (next)
|
|
149
|
+
if (next) acceptNow();
|
|
196
150
|
else resetReadyCheck();
|
|
197
151
|
}
|
|
198
152
|
|
|
199
|
-
function onDelayInput(event) {
|
|
200
|
-
const raw = Number(event.target.value);
|
|
201
|
-
const next = Math.min(Math.max(Number.isFinite(raw) ? Math.floor(raw) : 0, 0), MAX_DELAY);
|
|
202
|
-
writeDelay(next);
|
|
203
|
-
if (event.type === "change") event.target.value = String(next);
|
|
204
|
-
if (active && enabled() && timer) {
|
|
205
|
-
clearTimer();
|
|
206
|
-
queueAccept();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
153
|
function buildButton() {
|
|
211
154
|
const root = document.createElement("div");
|
|
212
155
|
root.id = ROOT_ID;
|
|
@@ -224,23 +167,7 @@ function buildButton() {
|
|
|
224
167
|
toggle();
|
|
225
168
|
});
|
|
226
169
|
|
|
227
|
-
|
|
228
|
-
input.className = "auto-accept-delay";
|
|
229
|
-
const field = document.createElement("input");
|
|
230
|
-
field.id = DELAY_INPUT_ID;
|
|
231
|
-
field.type = "number";
|
|
232
|
-
field.min = "0";
|
|
233
|
-
field.max = String(MAX_DELAY);
|
|
234
|
-
field.step = "100";
|
|
235
|
-
field.placeholder = "ms";
|
|
236
|
-
field.title = "Delay before accepting, in milliseconds";
|
|
237
|
-
field.value = String(delayValue);
|
|
238
|
-
field.addEventListener("input", onDelayInput);
|
|
239
|
-
field.addEventListener("change", onDelayInput);
|
|
240
|
-
field.addEventListener("click", (event) => event.stopPropagation());
|
|
241
|
-
input.append(field);
|
|
242
|
-
|
|
243
|
-
root.append(option, input);
|
|
170
|
+
root.append(option);
|
|
244
171
|
return root;
|
|
245
172
|
}
|
|
246
173
|
|
|
@@ -345,33 +272,16 @@ function onDisable() {
|
|
|
345
272
|
api = null;
|
|
346
273
|
}
|
|
347
274
|
|
|
348
|
-
function onOptionChange(key) {
|
|
349
|
-
if (key !== OPTION_KEY) return;
|
|
350
|
-
syncButton();
|
|
351
|
-
if (enabled()) queueAccept();
|
|
352
|
-
else resetReadyCheck();
|
|
353
|
-
}
|
|
354
|
-
|
|
355
275
|
export function init() {
|
|
356
276
|
const registerWith = (utils) => {
|
|
357
277
|
utils.registerPlugin({
|
|
358
278
|
id: PLUGIN_ID,
|
|
359
279
|
name: "Auto Accept",
|
|
360
280
|
description:
|
|
361
|
-
"Accepts the ready check automatically
|
|
281
|
+
"Accepts the ready check automatically. Use the Auto Accept switch in the lobby footer to turn it on or off.",
|
|
362
282
|
version,
|
|
363
|
-
options: [
|
|
364
|
-
{
|
|
365
|
-
key: OPTION_KEY,
|
|
366
|
-
label: "Auto accept matches",
|
|
367
|
-
description:
|
|
368
|
-
"Accepts the ready check for you. The Auto Accept switch in the lobby footer toggles this same setting.",
|
|
369
|
-
default: true,
|
|
370
|
-
},
|
|
371
|
-
],
|
|
372
283
|
onEnable,
|
|
373
284
|
onDisable,
|
|
374
|
-
onOptionChange,
|
|
375
285
|
});
|
|
376
286
|
};
|
|
377
287
|
|
package/ban-blocker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = "3.6.
|
|
1
|
+
export const version = "3.6.2";
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = "ban-blocker";
|
|
4
4
|
const STYLE_ID = "perfectionist-ban-blocker-style";
|
|
@@ -70,6 +70,7 @@ const fetchedNames = new Set();
|
|
|
70
70
|
const playerNames = new Map();
|
|
71
71
|
const cellToPlayer = new Map();
|
|
72
72
|
const buttons = new Map();
|
|
73
|
+
const swapSeen = new Set();
|
|
73
74
|
const failedUntil = new Map();
|
|
74
75
|
const failCount = new Map();
|
|
75
76
|
let rows = [];
|
|
@@ -159,10 +160,19 @@ function linkPlayer(p, rowName, cellId) {
|
|
|
159
160
|
return root;
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
function pickStarted(s) {
|
|
164
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
165
|
+
return actions.some((a) => a.type === "pick" && (a.isInProgress || a.completed));
|
|
166
|
+
}
|
|
167
|
+
|
|
162
168
|
function banPending(s) {
|
|
163
|
-
const
|
|
169
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
170
|
+
const bans = actions.filter((a) => a.type === "ban");
|
|
164
171
|
if (!bans.length) return true;
|
|
165
|
-
|
|
172
|
+
if (bans.some((a) => !a.completed)) return true;
|
|
173
|
+
const phase = s?.timer?.phase;
|
|
174
|
+
if (phase && phase !== "BAN_PICK") return false;
|
|
175
|
+
return !pickStarted(s);
|
|
166
176
|
}
|
|
167
177
|
|
|
168
178
|
function pump() {
|
|
@@ -254,6 +264,7 @@ function onSessionGone() {
|
|
|
254
264
|
lastSession = null;
|
|
255
265
|
goneAway = true;
|
|
256
266
|
uiVisible = false;
|
|
267
|
+
swapSeen.clear();
|
|
257
268
|
removeButtons();
|
|
258
269
|
if (!goneTimer) {
|
|
259
270
|
goneTimer = setTimeout(() => {
|
|
@@ -449,16 +460,31 @@ function isSelfRow(r) {
|
|
|
449
460
|
return lastSession?.localPlayerCellId != null && (r.cell ?? r.slotId) === lastSession.localPlayerCellId;
|
|
450
461
|
}
|
|
451
462
|
|
|
463
|
+
function rowKey(r) {
|
|
464
|
+
return String(r.slotId ?? r.cell ?? r.index);
|
|
465
|
+
}
|
|
466
|
+
|
|
452
467
|
function nativeSwapIn(circle) {
|
|
453
|
-
|
|
468
|
+
if (!circle) return false;
|
|
469
|
+
return [...circle.querySelectorAll(".swap-button-component")].some((el) => el.dataset.bb !== "1");
|
|
454
470
|
}
|
|
455
471
|
|
|
456
472
|
function ensureButtons() {
|
|
457
473
|
const list = getRows();
|
|
458
474
|
for (const r of list) {
|
|
475
|
+
if (!r.circle || !r.circle.isConnected) r.circle = r.el.querySelector(".champion-icon-container");
|
|
459
476
|
if (!r.circle || !r.circle.isConnected) continue;
|
|
477
|
+
const key = rowKey(r);
|
|
460
478
|
let btn = buttons.get(r.index);
|
|
461
|
-
if (isSelfRow(r)
|
|
479
|
+
if (isSelfRow(r)) {
|
|
480
|
+
if (btn) {
|
|
481
|
+
btn.remove();
|
|
482
|
+
buttons.delete(r.index);
|
|
483
|
+
}
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (nativeSwapIn(r.circle)) swapSeen.add(key);
|
|
487
|
+
if (!swapSeen.has(key)) {
|
|
462
488
|
if (btn) {
|
|
463
489
|
btn.remove();
|
|
464
490
|
buttons.delete(r.index);
|
|
@@ -531,6 +557,7 @@ function update() {
|
|
|
531
557
|
renderButtons();
|
|
532
558
|
} else if (uiVisible) {
|
|
533
559
|
uiVisible = false;
|
|
560
|
+
swapSeen.clear();
|
|
534
561
|
removeButtons();
|
|
535
562
|
}
|
|
536
563
|
}
|
|
@@ -605,6 +632,7 @@ function onDisable() {
|
|
|
605
632
|
observer = null;
|
|
606
633
|
|
|
607
634
|
uiVisible = false;
|
|
635
|
+
swapSeen.clear();
|
|
608
636
|
goneAway = true;
|
|
609
637
|
target = undefined;
|
|
610
638
|
sent = 0;
|