Overrides the default game speed and improves reliability of mid and long tick fire rates
// ==UserScript==
// @name Evolve-Scab-Worker
// @namespace solistus.xyz
// @description Overrides the default game speed and improves reliability of mid and long tick fire rates
// @match https://pmotschmann.github.io/Evolve*
// @version 0.2.1
// @inject-into page
// @license MIT
// @run-at document-start
// ==/UserScript==
// TO DO:
// (for 1.0) add UI to allow tick speed to be set without using console commands
// (for 1.0) clean up debug output and implement debugging flag to toggle on/off easily
// (for 1.1?) add option to use vanilla worker messages to set the baseDelay to match vanilla speeds more accurately
// (maybe?) add support for a message to alter Ticker ratios, and/or to allow a separate interval to be toggled for just one message type
// (maybe?) test other options for the scab script body e.g. a separate included file [mainly for maintainability as editing code stored in a string literal can be a hassle]
let baseDelay = 190,
scabScript =
`let debug = console.debug.bind(console); //replace with ()=>{} to turn off debug output, or e.g. an array's push method to redirect output elsewhere
debug('scab worker started')
function
/* Generator for messages to send from worker to page for game ticks
* default params for standard ratios of fast/mid/long. 1 long, (midratio) mids, (midratio*fastratio) fasts per cycle (1/5/20 default).
*/
* Ticker(fastratio=4, midratio=5) {
while(true) {
yield "long";
let a = midratio; while(a--){ let b = fastratio; yield "mid"; while(b--) yield "fast"; }
}}
function pause() {
clearInterval(self.messenger); self.messenger = null;
debug("worker paused ticks.")
}
function resume() {
clearInterval(self.messenger);
self.messenger = setInterval(()=>{self.postMessage(self.ticker.next().value)}, self.delay);
debug('worker is now sending ticks.');
}
function setDelay(del) {
self.delay = del;
if(self.messenger) self.resume();
debug('worker delay set to ' + self.delay + (self.messenger ? "ms." : "ms. (game is paused)"));
}
self.delay = ${baseDelay},
self.ticker = Ticker(),
self.messenger = 0; resume();
self.addEventListener('message', ((e)=>{
let loop = e.data.loop ?? e.data, period = Number.parseInt(e.data.period) ?? 0;
switch(loop){
case 'clear':
case 'pause':
pause();
break;
case 'short':
case 'resume':
case 'unpause':
case 'play':
resume();
break;
case 'delay':
if(period)
setDelay(period);
else
console.log("worker delay is " + self.delay + (self.messenger?"ms.":"ms (PAUSED)."));
break;
case 'mid':
case 'long':
break;
default:
if(typeof loop == 'number' || loop == Number.parseInt(loop))
setDelay(Number.parseInt(loop));
else {
try { debug("worker received unsupported message: ", JSON.stringify(e.data)); }
catch { debug("worker received unsupported message, string conversion failed: ", e.data)}
}
}
}));`,
scabURL = URL.createObjectURL(new Blob([scabScript], {type:'application/javascript'}));
window._Worker = window.Worker;
window.scab = {
delay: baseDelay,
help: function(){
console.info('Supported message contents for scab.worker.postMessage(contents): ');
console.info('Vanilla game messages: {loop: <string>, period: <number>}, except loop: mid and loop: long (all three loops are controlled together on loop: short; mid and long messages are ignored). Period is ignored for all vanilla messages; use delay messages (see below) or this.speed() to alter tickrate.');
console.info('String messages (can also send as {loop: <str>}): clear/pause to pause game, short/resume/play to resume, delay to check current delay.');
console.info('Delay setters: {loop: "delay", period: <new delay>}, or simply send the delay as a string/number e.g. scab.worker.postMessage(50). Or, use scab.speed()');
},
speed: function(spd, asmult = true) { if(asmult) spd = Math.ceil(this.delay/spd); window.scab?.worker?.postMessage(spd); }
};
window.Worker = class Worker extends window._Worker {
constructor(...args) {
let isScab = false;
if (args[0] == 'evolve/evolve.js') { args[0] = scabURL; isScab = true;}
super(...args);
if(isScab) window.scab.worker = this;
console.debug('Worker(): ', args, this);
}
};
console.info('Scab worker injected. Access worker at window.scab.worker, set speed with window.scab.speed(delay), or set to a multiple of default rate with *.speed(mult, true)');
console.debug('To see all supported messages for manual sending, call window.scab.help().');