Skip to content

Instantly share code, notes, and snippets.

@stevenhao
Last active August 31, 2018 04:23
Show Gist options
  • Save stevenhao/c0ab8afe97aead12ccc28e635f7aa255 to your computer and use it in GitHub Desktop.
Save stevenhao/c0ab8afe97aead12ccc28e635f7aa255 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Generals.io
// @namespace http://tampermonkey.net/
// @version 0.1
// @description toolbox for generals.io
// @author Steven Hao
// @match http://generals.io/*
// @grant none
// ==/UserScript==
// ==================================
// Some language stuff / utils
function toArray(nodeList) {
return Array.prototype.slice.call(nodeList);
}
Array.prototype.flatMap = function(fn) {
return this.map(fn).reduce((sum, add) => sum.concat(add));
};
String.prototype.contains = function(needle) {
return this.indexOf(needle) != -1;
};
Array.prototype.contains = function(needle) {
return this.indexOf(needle) != -1;
};
// ==================================
// Interfacing with the DOM
function getCells() {
var map = document.getElementById('map');
var rows = map.childNodes[0].childNodes;
return toArray(rows).flatMap(row => toArray(row.childNodes));
}
// ==================================
// Plugin #1: Mountains Watcher
// This watches for changes in "obstacles", and highlights them.
// When a general is captured, it changes from "fog" to "obstacle fog" on the map.
// This allows us to figure out where the dead generals were, and more easily guess where the remaining generals are.
var MountainsWatcher = (function() {
function getCityCells() {
var cells = getCells();
var result = [];
cells.forEach((cell, idx) => {
if (cell.className.contains('city') ||
cell.className.contains('mountain') ||
cell.className.contains('obstacle')) {
result.push(idx);
}
});
return result;
}
function markCell(cell) {
cell.style.outline = '3px dashed white';
}
var watchIntvl = 0;
function draw() {
if (result.draw) result.draw();
}
function start() {
if (watchIntvl) {
stop();
}
try {
var initialMountains = getCityCells();
console.log('initial mountains: ', initialMountains);
console.log('watching mountains...');
} catch (ex) {
console.log('failed to start');
return;
}
watchIntvl = setInterval(function() {
try {
var currentMountains = getCityCells();
var newMountains = currentMountains.filter(idx => !initialMountains.contains(idx));
var cells = getCells();
// console.log('new mountains:', newMountains);
newMountains.map(idx => cells[idx]).forEach(markCell);
} catch(ex) {
console.log('no longer watching mountains.');
stop();
}
draw();
}, 500);
}
function stop() {
clearInterval(watchIntvl);
watchIntvl = 0;
}
var result = {
draw: null,
running: function() {
return watchIntvl !== 0;
},
start: start,
stop: stop,
};
return result;
}());
// ==================================
// Putting it all together in a dashboard
(function() {
var dashboard = document.createElement('div');
dashboard.style.zIndex = '11'; // place it above the map scroll
dashboard.style.position = 'absolute';
dashboard.style.right = '20px';
dashboard.style.bottom = '30px';
dashboard.style.width = '150px';
dashboard.style.height = '300px';
dashboard.style.outline = '5px solid #252525';
dashboard.style.textAlign = 'center';
var dashboardTitle = document.createElement('p');
dashboardTitle.innerHTML = '#swog';
dashboard.appendChild(dashboardTitle);
var watchMountainsButton = document.createElement('button');
watchMountainsButton.style.fontSize = '14px';
watchMountainsButton.style.padding = '2px 4px';
watchMountainsButton.innerHTML = 'Watch Mountains';
watchMountainsButton.onclick = MountainsWatcher.start;
MountainsWatcher.draw = function() {
watchMountainsButton.style.backgroundColor = MountainsWatcher.running() ? 'black' : 'white';
};
dashboard.appendChild(watchMountainsButton);
setTimeout(function() {
document.body.appendChild(dashboard);
}, 500);
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment