Makes the ball in the Plinko mini-game always go the best way possible
Size
8.6 KB
Version
1.1.3
Created
Nov 27, 2025
Updated
16 days ago
1// ==UserScript==
2// @name YouNow Plinko Auto-Win
3// @description Makes the ball in the Plinko mini-game always go the best way possible
4// @version 1.1.3
5// @match https://*.younow.com/*
6// @icon https://www.younow.com/favicon.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('YouNow Plinko Auto-Win extension loaded');
12
13 // Randomly choose left or right edge as target (both are optimal)
14 const targetSide = Math.random() < 0.5 ? 'left' : 'right';
15 console.log(`Target side selected: ${targetSide}`);
16
17 let hooksInstalled = false;
18 let canvasHooked = false;
19
20 // Install hooks immediately to catch early game initialization
21 function installHooks() {
22 if (hooksInstalled) return;
23 hooksInstalled = true;
24
25 console.log('Installing canvas and physics hooks...');
26
27 // Hook into HTMLCanvasElement.prototype.getContext BEFORE the game loads
28 const originalGetContext = HTMLCanvasElement.prototype.getContext;
29
30 HTMLCanvasElement.prototype.getContext = function(type, ...args) {
31 const context = originalGetContext.call(this, type, ...args);
32
33 // Only hook into the Plinko game canvas
34 if (type === '2d' && (this.id === 'defaultCanvas0' || this.className.includes('p5Canvas'))) {
35 if (!canvasHooked) {
36 console.log('Plinko canvas context intercepted!');
37 hookCanvasContext(context, this);
38 canvasHooked = true;
39 }
40 }
41
42 return context;
43 };
44
45 // Hook into Matter.js if it exists or will exist
46 hookMatterJS();
47
48 // Keep checking for Matter.js in case it loads later
49 const checkInterval = setInterval(() => {
50 if (typeof window.Matter !== 'undefined') {
51 console.log('Matter.js detected, installing physics hooks');
52 hookMatterJS();
53 clearInterval(checkInterval);
54 }
55 }, 500);
56
57 setTimeout(() => clearInterval(checkInterval), 15000);
58 }
59
60 function hookCanvasContext(context, canvas) {
61 const originalArc = context.arc;
62 const originalFill = context.fill;
63 const originalStroke = context.stroke;
64 let lastBallY = 0;
65 let ballDetected = false;
66
67 // Hook arc (used to draw circles)
68 context.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) {
69 // Detect ball (circle with radius between 5-20 pixels)
70 if (radius > 5 && radius < 20 && y > lastBallY) {
71 ballDetected = true;
72 // Calculate target position based on selected side
73 const edgeOffset = 25;
74 const targetX = targetSide === 'left' ? edgeOffset : canvas.width - edgeOffset;
75
76 // Apply strong drift towards target
77 const drift = (targetX - x) * 0.2;
78 x = x + drift;
79
80 console.log(`Ball guided to ${targetSide}: x=${x.toFixed(1)}, y=${y.toFixed(1)}`);
81 lastBallY = y;
82 }
83
84 return originalArc.call(this, x, y, radius, startAngle, endAngle, anticlockwise);
85 };
86
87 // Also hook fill and stroke to detect drawing operations
88 context.fill = function(...args) {
89 if (ballDetected) {
90 console.log('Ball fill detected');
91 ballDetected = false;
92 }
93 return originalFill.call(this, ...args);
94 };
95
96 context.stroke = function(...args) {
97 if (ballDetected) {
98 console.log('Ball stroke detected');
99 ballDetected = false;
100 }
101 return originalStroke.call(this, ...args);
102 };
103 }
104
105 function hookMatterJS() {
106 if (typeof window.Matter === 'undefined' || !window.Matter.Body) return;
107
108 const Matter = window.Matter;
109 console.log('Hooking Matter.js physics engine');
110
111 // Hook setVelocity
112 const originalSetVelocity = Matter.Body.setVelocity;
113 Matter.Body.setVelocity = function(body, velocity) {
114 if (body.label === 'ball' || body.circleRadius || body.isCircle) {
115 const canvas = document.getElementById('defaultCanvas0');
116 if (canvas && body.position) {
117 const edgeOffset = 25;
118 const targetX = targetSide === 'left' ? edgeOffset : canvas.width - edgeOffset;
119 const currentX = body.position.x;
120 const distance = Math.abs(currentX - targetX);
121
122 if (distance > 5) {
123 const direction = currentX < targetX ? 1 : -1;
124 velocity.x = velocity.x + (direction * 1.2);
125 console.log(`Matter.js velocity adjusted: ${velocity.x.toFixed(2)} towards ${targetSide}`);
126 }
127 }
128 }
129
130 return originalSetVelocity.call(this, body, velocity);
131 };
132
133 // Hook applyForce
134 const originalApplyForce = Matter.Body.applyForce;
135 Matter.Body.applyForce = function(body, position, force) {
136 if (body.label === 'ball' || body.circleRadius || body.isCircle) {
137 const canvas = document.getElementById('defaultCanvas0');
138 if (canvas && body.position) {
139 const edgeOffset = 25;
140 const targetX = targetSide === 'left' ? edgeOffset : canvas.width - edgeOffset;
141 const currentX = body.position.x;
142 const distance = Math.abs(currentX - targetX);
143
144 if (distance > 5) {
145 const direction = currentX < targetX ? 1 : -1;
146 force.x = force.x + (direction * 0.0005);
147 }
148 }
149 }
150
151 return originalApplyForce.call(this, body, position, force);
152 };
153
154 // Hook setPosition to force ball to edge
155 const originalSetPosition = Matter.Body.setPosition;
156 Matter.Body.setPosition = function(body, position) {
157 if (body.label === 'ball' || body.circleRadius || body.isCircle) {
158 const canvas = document.getElementById('defaultCanvas0');
159 if (canvas) {
160 const edgeOffset = 25;
161 const targetX = targetSide === 'left' ? edgeOffset : canvas.width - edgeOffset;
162 const distance = Math.abs(position.x - targetX);
163
164 if (distance > 5) {
165 const drift = (targetX - position.x) * 0.1;
166 position.x = position.x + drift;
167 console.log(`Matter.js position adjusted: ${position.x.toFixed(2)} towards ${targetSide}`);
168 }
169 }
170 }
171
172 return originalSetPosition.call(this, body, position);
173 };
174 }
175
176 // Try to hook existing canvas if it already exists
177 function hookExistingCanvas() {
178 const canvas = document.getElementById('defaultCanvas0');
179 if (canvas && !canvasHooked) {
180 console.log('Found existing canvas, attempting to hook...');
181 // Force a new context retrieval to trigger our hook
182 try {
183 const ctx = canvas.getContext('2d');
184 if (ctx && !canvasHooked) {
185 hookCanvasContext(ctx, canvas);
186 canvasHooked = true;
187 console.log('Successfully hooked existing canvas context');
188 }
189 } catch (e) {
190 console.error('Failed to hook existing canvas:', e);
191 }
192 }
193 }
194
195 // Install hooks immediately
196 installHooks();
197
198 // Also watch for game container to appear
199 const observer = new MutationObserver(() => {
200 const gameContainer = document.getElementById('plinko-game-container');
201 const canvas = document.getElementById('defaultCanvas0');
202
203 if (gameContainer || canvas) {
204 console.log('Plinko game detected in DOM!');
205 installHooks();
206 hookExistingCanvas();
207 }
208 });
209
210 if (document.body) {
211 observer.observe(document.body, {
212 childList: true,
213 subtree: true
214 });
215 }
216
217 // Try to hook existing canvas immediately
218 setTimeout(() => hookExistingCanvas(), 100);
219 setTimeout(() => hookExistingCanvas(), 500);
220 setTimeout(() => hookExistingCanvas(), 1000);
221
222 console.log('YouNow Plinko Auto-Win extension initialized and ready');
223})();