Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Emscripten's WebAssembly games non-intrusive auto-clicker by hijacking "JSEvents" object event handlers via browser debugger.
{ // For copy/paste purpose...
/* Usually, in most emscripten games "JSEvents" interface is private, therefore we expose it to global scope by using debugger (i.e Developer Tools)... */
if (false) {
/* Note: unityWebView.game.Module could be named differently (based on a game), for example like "gameInstance.Module" etc.. */
// Copy this to the debugger and execute to stop at the breakpoint, where we will expose "JSEvents" to global scope.
debug(unityWebView.game.Module.SetFullscreen);
unityWebView.game.Module.SetFullscreen();
undebug(unityWebView.game.Module.SetFullscreen);
//window.JSEvents = JSEvents; // expose this...
}
}
// after successful JSEvents exposure, simply execute the code below which will take advantage of JSEvents to emulate mouse clicks on pre-programmed positions at custom period of time.
var findHandler = (function() {
let handlerMap = {};
for(let handlerId in JSEvents.eventHandlers) {
let handler = JSEvents.eventHandlers[handlerId];
handlerMap[handler.eventTypeString] = handlerId;
}
return function(handlerType) {
return { handlerId: handlerMap[handlerType], handler: JSEvents.eventHandlers[handlerMap[handlerType]] };
};
})();
var removeHandler = function(handlerType) {
let eventHandler = findHandler(handlerType);
if (eventHandler.handler)
JSEvents._removeHandler(eventHandler.handlerId);
};
var autoClick = (function() {
let mouseMoveHandler = findHandler("mousemove").handler;
let mouseDownHandler = findHandler("mousedown").handler;
let mouseUpHandler = findHandler("mouseup").handler;
let target = unityWebView.game.Module.ctx.canvas;
let mouseEvent = {
"screenX": 0,
"screenY": 0,
"clientX": 0,
"clientY": 0,
"ctrlKey": false,
"shiftKey": false,
"altKey": false,
"metaKey": false,
"button": 0,
"buttons": 0,
"movementX": 0,
"movementY": 0,
};
return function(x, y) {
mouseEvent.screenX = mouseEvent.clientX = x;
mouseEvent.screenY = mouseEvent.clientY = y;
JSEvents.fillMouseEventData(JSEvents.mouseEvent, mouseEvent, target);
unityWebView.game.Module["dynCall_iiii"](mouseMoveHandler.callbackfunc, 8, JSEvents.mouseEvent, 0);
unityWebView.game.Module["dynCall_iiii"](mouseDownHandler.callbackfunc, 5, JSEvents.mouseEvent, 0);
unityWebView.game.Module["dynCall_iiii"](mouseUpHandler.callbackfunc, 6, JSEvents.mouseEvent, 0);
};
})();
var bounds = { width: unityWebView.game.Module.canvas.width, height: unityWebView.game.Module.canvas.height };
var autoClicker = {
interval: 85,
timerId: autoClicker && autoClicker.timerId,
timeoutClick: function(id, x, y, interval) {
autoClicker[id] = autoClicker[id] || setTimeout(function() {
autoClick(x, y);
autoClicker[id] = null;
}, interval);
},
init: function() {
removeHandler("blur");
clearInterval(autoClicker.timerId);
autoClicker.timerId = setInterval(function() {
/* Auto-Clicking positions goes here... */
autoClick(bounds.width - 135, bounds.height - 278);
autoClicker.timeoutClick("autoProgress_start", bounds.width + 105, bounds.height - 351, autoClicker.interval / 5);
autoClicker.timeoutClick("autoProgress_next/finish", bounds.width + 116, bounds.height - 351, autoClicker.interval / 4);
autoClicker.timeoutClick("level_up_Mizuki", bounds.width - 470, bounds.height - 527, autoClicker.interval / 3);
autoClicker.timeoutClick("level_up_Bunny", bounds.width - 470, bounds.height - 418, autoClicker.interval / 2);
autoClicker.timeoutClick("level_up_Estelle", bounds.width - 470, bounds.height - 312, autoClicker.interval / 1);
// autoClicker.timeoutClick("level_up_Megane", bounds.width - 470, bounds.height - 205, autoClicker.interval / 3);
// autoClicker.timeoutClick("level_up_Angela", bounds.width - 470, bounds.height - 96, autoClicker.interval / 2);
// autoClicker.timeoutClick("level_up_Lyrsa", bounds.width - 470, bounds.height + 12, autoClicker.interval / 1);
autoClicker.timeoutClick("autoSkill_NeptunesTouch", bounds.width - 97, bounds.height - 15, 58 * 1000);
autoClicker.timeoutClick("autoSkill_ExitingFlirt", bounds.width - 28, bounds.height - 15, 59 * 1000);
autoClicker.timeoutClick("autoSkill_ManlySweat", bounds.width + 34, bounds.height - 15, 61 * 1000);
autoClicker.timeoutClick("autoBonusClaimer", bounds.width + 210, bounds.height - 165, 30 * 1000);
}, autoClicker.interval);
}
};
/* Toggle ON/OFF Switch via 'Spacebar' and custom active zone */
var toggleState = true;
if (typeof printMousePos !== "undefined")
document.removeEventListener("click", printMousePos);
if (typeof activeZone !== "undefined")
document.removeEventListener("mousemove", activeZone);
if (typeof toggleButton !== "undefined")
document.removeEventListener("keyup", toggleButton);
var printMousePos = function(mouseEvt) {
console.log(`${mouseEvt.clientX}, ${mouseEvt.clientY}`);
console.log(`autoClick(bounds.width - ${bounds.width - mouseEvt.clientX}, bounds.height - ${bounds.height - mouseEvt.clientY});`);
};
var activeZone = function(evt) {
if (!toggleState)
return false;
if (evt.clientX < bounds.width / 1.5) {
if (autoClicker.timerId) {
clearInterval(autoClicker.timerId);
autoClicker.timerId = null;
console.log("[ActionZone] AutoClicker OFF!");
}
} else if (autoClicker.timerId == null) {
autoClicker.init();
console.log("[ActionZone] AutoClicker ON!");
}
};
var toggleButton = function(evt) {
if (evt.keyCode == 32) {
toggleState = !toggleState;
if (toggleState && autoClicker.timerId == null) {
autoClicker.init();
console.log("[KeyPress] AutoClicker ON!");
} else {
clearInterval(autoClicker.timerId);
autoClicker.timerId = null;
console.log("[KeyPress] AutoClicker OFF!");
}
}
};
document.addEventListener("click", printMousePos);
document.addEventListener("mousemove", activeZone);
document.addEventListener("keyup", toggleButton);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment