// ==UserScript==
// @name Kittens tools
// @namespace http://bloodrizer.ru/games/kittens/
// @version 1.086
// @description Kittens tools (visual)
// @author Anton
// @match http://bloodrizer.ru/games/kittens/
// @require https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.22/cytoscape.min.js
// ==/UserScript==
(function() {
'use strict';
var $ = jQuery;
var _BotSettings = {
autoBuy: false,
autoPromoteKittens: true,
autoCollectFaith: true,
autoCreateSteel: true,
autoCreatePlates: true,
autoSendHunters: true,
autoCreateManuscript: true,
autoCreateWood: true,
autoCreateBeams: true,
autoCreateSlabs: true,
autoCreateCompendium: true,
init: function () {
_BotUI.initSettingsLink();
_BotUI.initSettingsPage();
_BotSettings.restoreAll();
},
toggleSetting: function (settingName) {
var name = 'auto' + settingName;
if (typeof _BotSettings[name] === 'boolean') {
_BotSettings[name] = !_BotSettings[name];
_BotUI.initSettingsPage();
_BotSettings.store(name, _BotSettings[name]);
}
return false;
},
store: function(name, value) {
if (typeof(Storage) !== "undefined") localStorage.setItem(name, value);
},
restore: function(name, asBool) {
if (typeof asBool === 'undefined') asBool = false;
if (typeof(Storage) !== "undefined") {
var aValue = localStorage.getItem(name);
if (asBool && aValue !== null) {
return (aValue === 'true' || aValue === true);
} else {
return aValue;
}
}
else return null;
},
restoreAll: function () {
for (var x in _BotSettings) {
if (_BotSettings.hasOwnProperty(x)) {
if (x.indexOf("auto") === 0) {
var oldValue = _BotSettings.restore(x, true);
if (oldValue !== null) {
_BotSettings[x] = oldValue;
}
}
}
}
}
};
var _Helpers = {
_log2: [],
isGameReady: function() {
return $("#game").css('display') === 'block';
},
log: function(message) {
var mes = 'BOT: ' + message;
if (game && game.msg && game.ui) {
game.msg(mes, 'msg');
game.ui.renderConsoleLog();
}
},
log2: function(messsage) {
if (_Helpers._log2.length >= 100) {
_Helpers._log2.shift();
}
_Helpers._log2.push(messsage);
if (_BotUI.currentPage === 'log2') {
_BotUI.initLog2Page();
}
},
isResourceUnlocked: function(res) {
return game.resPool.get(res).unlocked;
},
getBotVersion: function () {
return typeof GM_info == 'function' ? GM_info().script.version :
(typeof GM_info == 'object' ? GM_info.script.version : '?');
},
getMinCraft: function(res) {
// craft no more than 2% of possible craft
var allCount = game.workshop.getCraftAllCount(res);
var ratioCount = Math.floor(allCount*0.02);
return ratioCount < 1 ? 1 : ratioCount;
},
canBuyBuilding: function(bldName) {
var prices = game.bld.getPrices(bldName);
for (var x in prices) {
if (prices.hasOwnProperty(x)) {
if (prices[x].val > game.resPool.get(prices[x].name).value) {
return false;
}
}
}
return true;
},
getCountKittensForPromote: function() {
var x=0;
for (var i = 0; i < game.village.sim.kittens.length; i++) {
var done = false;
if(game.village.sim.kittens[i].engineerSpeciality !== null) {
var kitten = game.workshop.getCraft(game.village.sim.kittens[i].engineerSpeciality);
if (kitten) {
var tier = kitten.tier;
if (game.village.sim.kittens[i].rank < tier) {
x++;
done = true;
}
}
}
if (!done) {
x++;
}
}
return x;
},
getZebraTitanium: function () {
if (game.diplomacy.get('zebras').unlocked) {
var shipVal = game.resPool.get("ship").value;
var shipRate = shipVal * 0.35; //0.35% per ship to get titanium
var titaniumAmt = 1.5;
titaniumAmt += titaniumAmt * (shipVal / 100) * 2; //2% more titanium per ship
return {percent: shipRate + 15, value: titaniumAmt};
}
return {percent: 0, value: 0};
},
clone: function (obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = _Helpers.clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = _Helpers.clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
};
var _BotActions = {
craftAll: function(res) {
if (_Helpers.isResourceUnlocked(res)) {
_Helpers.log2("Crafting " + res);
game.craftAll(res);
}
},
collectAstronomy: function() {
if (game.calendar.observeRemainingTime > 0) {
if (typeof game.calendar.observeHandler === 'function') {
game.calendar.observeHandler();
}
}
},
catnipToWood: function() {
var catnip = game.resPool.get("catnip");
if (catnip.value >= catnip.maxValue) {
var minWood = _Helpers.getMinCraft('wood');
var wood = game.resPool.get("wood");
if (wood.value + minWood <= wood.maxValue) {
_Helpers.log2('Catnip to Wood x ' + minWood);
game.craft('wood', minWood);
}
}
},
collectFaith: function() {
var faith = game.resPool.get("faith");
if (faith.value >= faith.maxValue) {
_Helpers.log2('Praise');
game.religion.praise();
}
},
sendAllHunters: function() {
var manpower = game.resPool.get("manpower");
if (manpower.value >= manpower.maxValue) {
_Helpers.log2('Sending hunters');
game.village.huntAll();
_BotActions.craftAll('parchment');
}
},
ironToSteel: function() {
if (_Helpers.isResourceUnlocked('steel')) {
var iron = game.resPool.get("iron");
var coal = game.resPool.get("coal");
if (iron.value >= iron.maxValue || coal.value >= coal.maxValue) {
if (coal.value >= 100 && iron.value >= 100) {
_Helpers.log2('Iron to Steel x ALL');
game.craftAll('steel');
}
}
}
},
ironToPlates: function() {
var iron = game.resPool.get("iron");
var minPlate = _Helpers.getMinCraft('plate');
if (iron.value >= (125 * minPlate) && _Helpers.isResourceUnlocked('plate')) {
_Helpers.log2('Iron to Plate x ' + minPlate);
game.craft('plate', minPlate);
}
},
woodToBeams: function() {
var wood = game.resPool.get("wood");
if (wood.value >= wood.maxValue && _Helpers.isResourceUnlocked('beam')) {
var minVal = _Helpers.getMinCraft('beam');
_Helpers.log2('Wood to Beam x ' + minVal);
game.craft('beam', minVal);
}
},
mineralsToSlabs: function() {
var minerals = game.resPool.get("minerals");
if (minerals.value >= minerals.maxValue && _Helpers.isResourceUnlocked('slab')) {
var minVal = _Helpers.getMinCraft('slab');
_Helpers.log2('Minerals to Slab x ' + minVal);
game.craft('slab', minVal);
}
},
cultureToManuscript: function() {
var culture = game.resPool.get("culture");
var parchment = game.resPool.get("parchment");
var minVal = _Helpers.getMinCraft('manuscript');
if (culture.value >= culture.maxValue && _Helpers.isResourceUnlocked('manuscript') && culture.value >= (400 * minVal) && parchment.value >= (25 * minVal)) {
_Helpers.log2('Culture to Manuscript x ' + minVal);
game.craft('manuscript', minVal);
}
},
makeABuy: function(itemName) {
var btn = $('.bldGroupContainer').find('div.btnContent').find('span').filter(function(){
var t = $(this).text();
return t.indexOf(itemName + " (") === 0 || t === itemName;
});
if (btn&& btn.length === 1) {
_Helpers.log('Autobuy ' + itemName);
_Helpers.log2('Autobuy ' + itemName);
btn.click();
}
},
promoteKittens: function() {
var gold = game.resPool.get("gold");
if (!gold.unlocked) return;
if (gold.value >= 15 && gold.value >= gold.maxValue && _Helpers.getCountKittensForPromote() > 0) {
game.village.promoteKittens();
}
},
scienceToCompendium: function() {
var science = game.resPool.get("science");
var manuscript = game.resPool.get("manuscript");
var minVal = _Helpers.getMinCraft('compedium');
if (science.value >= science.maxValue && _Helpers.isResourceUnlocked('compedium') && manuscript.value >= (50 * minVal) && science.value >= (10000 * minVal)) {
_Helpers.log2('Science + Manuscript to Compendium x ' + minVal);
game.craft('compedium', minVal);
}
}
};
// noinspection JSUnusedGlobalSymbols
var _BotUI = {
currentPage: 'log',
cy: undefined,
fixFontSize: function() {
var $midColumn = $('#midColumn');
var $rightColumn = $('#rightColumn');
var fnt1 = $('#leftColumn').css('font-size');
var fnt2 = $midColumn.css('font-size');
var fnt3 = $rightColumn.css('font-size');
if (fnt2 !== fnt1 || fnt3 !== fnt1) {
_Helpers.log('Fixing font size');
$midColumn.css('font-size', fnt1);
$rightColumn.css('font-size', fnt1);
}
},
fixStyles: function() {
var style = '<style type="text/css">' +
'.modern .btnContent, .btn.bldEnabled.modern div.btnContent, .btn.bldlackResConvert.modern div.btnContent {padding: 5px 0 5px 10px;} '+
'.btn.modern a {padding: 5px 6px 5px 6px !important;margin:-5px 0;} '+
'#rightTabLog {max-height: 75vh; overflow-y: scroll; padding-right: 4px;} ' +
'#IRCChatInner {overflow-y: scroll; height: 75vh;} ' +
'.msg {opacity: 1 !important;} ' +
'.right-tab-header a {padding: 0} ' +
'#scienceTree {z-index:2;position:fixed;left:2vw;top:2vh;width:96vw;height:96vh;background:azure;border:1px solid;} ' +
'#closeScienceTree {z-index:3;position:fixed;right:2vw;top:2vh;color:black;font-size:20px;padding:4px;border:1px solid;text-decoration:none;} ' +
'#closeScienceTree:hover {color:blue} ' +
'</style>';
$('body').append($(style));
},
addBotButton: function () {
var $a = $('<a href="#" id="botbutton">Bot (' + (_BotLogic.isAutoLogicStarted ? 'on' : 'off') + ')</a>');
$a.on("click", function() {
_BotLogic.isAutoLogicStarted = !_BotLogic.isAutoLogicStarted;
_Helpers.log((_BotLogic.isAutoLogicStarted ? 'Started' : 'Stopped') + ' version ' + _Helpers.getBotVersion());
$('#botbutton').text(_BotLogic.isAutoLogicStarted ? 'Bot (on)' : 'Bot (off)');
});
$('#headerLinks .links-block').append(' | ').append($a);
},
initSettingsLink: function () {
$('a.chatLink').text('Bot settings').attr('onclick', 'KittenTools.UI.onSettingsButtonClick()');
},
initSettingsPage: function () {
var inner = '';
for (var x in _BotSettings) {
if (_BotSettings.hasOwnProperty(x)) {
if (x.indexOf("auto") === 0) {
var name = x.substr(4);
var isChecked = _BotSettings[x];
inner += '<a href="#" onclick="KittenTools.Settings.toggleSetting(\'' + name + '\')">'
+ name + '</a> ' + (isChecked ? 'ON' : 'OFF') + '<br/>';
}
}
}
$("#IRCChatInner").html(inner);
},
initInfoPage: function() {
var inner = '', br = "<br/>";
var zebraTitanium = _Helpers.getZebraTitanium();
inner += 'Zebras trade:' + br;
inner += '- Titan chance: ' + parseFloat(zebraTitanium.percent).toFixed(2) + '%' + br;
inner += '- Titan amount: ' + parseFloat(zebraTitanium.value).toFixed(2) + br;
$("#IRCChatInner").html(inner);
},
initInfoButton: function () {
$('.right-tab-header').append(' | <a href="#" onclick="KittenTools.UI.onInfoButtonClick()">Info</a>');
},
initLog2Button: function () {
$('.right-tab-header').append(' | <a href="#" onclick="KittenTools.UI.onLog2ButtonClick()">Log2</a>');
},
initLog2Page: function() {
var inner = '', br = "<br/>";
inner += '<a href="#" onclick="KittenTools.UI.onClearLog2Click()">Clear log</a><hr/>';
for (var i = (_Helpers._log2.length - 1); i >= 0; i--) {
if (_Helpers._log2.hasOwnProperty(i)) {
inner += _Helpers._log2[i] + br;
}
}
$("#IRCChatInner").html(inner);
},
initCy: function() {
var el = document.getElementById('scienceTree');
if (typeof _BotUI.cy === 'undefined' && typeof cytoscape !== 'undefined' && el !== null) {
var elems = [];
//var techs = _Helpers.clone(game.science.techs);
//var dx = 0;
//var dy = 0;
var _addNode = function (name, connectTo) {
var t = game.science.get(name);
if (!t) return;
var nodeData = {data:{id:t.name}};
if (typeof connectTo !== 'undefined') {
nodeData.data.parent = connectTo;
}
elems.push(nodeData);
/*if (typeof connectTo !== 'undefined') {
var linkName = t.name + '_' + connectTo;
elems.push({data:{id:linkName,source:connectTo,target:t.name}});
}*/
if (typeof t.unlocks !== 'undefined' && typeof t.unlocks.tech === 'object') {
for (var x in t.unlocks.tech) {
if (t.unlocks.tech.hasOwnProperty(x)) {
_addNode(t.unlocks.tech[x], name);
}
}
}
};
_addNode('calendar');
_BotUI.cy = cytoscape({
container: el, // container to render in
zoom: 1,
elements: elems,
style: [
{
selector: 'node',
style: {
'label': 'data(id)'
}
}
]
});
}
},
init: function () {
_BotUI.fixStyles();
_BotUI.addBotButton();
_BotUI.initInfoButton();
_BotUI.initLog2Button();
_BotUI.initScienceTree();
},
initScienceTree: function() {
var closeDivButton = '<a href="#" id="closeScienceTree" onclick="KittenTools.UI.onCloseScienceTreeClick()">X</a>';
var scienceDiv = '<div id="scienceTree" style="display:none">' + closeDivButton + '</div>';
$('#gamePageContainer').prepend(scienceDiv);
//_BotUI.initCy();
},
onCloseScienceTreeClick: function() {
$('#scienceTree').hide();
},
onInfoButtonClick: function () {
_BotUI.currentPage = 'info';
game.ui.loadChat();
_BotUI.initInfoPage();
},
onSettingsButtonClick: function () {
_BotUI.currentPage = 'settings';
game.ui.loadChat();
_BotUI.initSettingsPage();
},
onLog2ButtonClick: function () {
_BotUI.currentPage = 'log2';
game.ui.loadChat();
_BotUI.initLog2Page();
},
initLogLink: function () {
$('a.chatLink').attr('onclick', 'KittenTools.UI.onLogButtonClick()');
},
onLogButtonClick: function () {
_BotUI.currentPage = 'log';
game.ui.hideChat();
},
onClearLog2Click: function () {
_Helpers._log2 = [];
_BotUI.initLog2Page();
}
};
var _BotLogic = {
tAutoLogic: undefined,
isAutoLogicStarted: true,
autoBuyItem: function(bldName) {
var bld = game.bld.get(bldName);
if (bld.unlocked && _Helpers.canBuyBuilding(bldName)) {
var itemName = bld.stages && bld.stages.length > 0 ? bld.stages[bld.stage].label : bld.label;
_BotActions.makeABuy(itemName);
}
},
autoBuyAll: function() {
if (!_BotSettings.autoBuy) return;
_BotLogic.autoBuyItem('field');
_BotLogic.autoBuyItem('pasture');
_BotLogic.autoBuyItem('unicornPasture');
_BotLogic.autoBuyItem('hut');
_BotLogic.autoBuyItem('logHouse');
_BotLogic.autoBuyItem('workshop');
_BotLogic.autoBuyItem('aqueduct');
_BotLogic.autoBuyItem('library');
_BotLogic.autoBuyItem('academy');
_BotLogic.autoBuyItem('barn');
_BotLogic.autoBuyItem('mine');
_BotLogic.autoBuyItem('lumberMill');
_BotLogic.autoBuyItem('temple');
_BotLogic.autoBuyItem('tradepost');
_BotLogic.autoBuyItem('warehouse');
_BotLogic.autoBuyItem('chapel');
_BotLogic.autoBuyItem('amphitheatre');
_BotLogic.autoBuyItem('smelter');
},
autoClick: function() {
var field = game.bld.get('field');
if (field.on < 5) {
var btn = $('.bldGroupContainer').find('div.btnContent').find('span').filter(function(){
return $(this).text().indexOf("Gather catnip") === 0;
});
if (btn && btn.length) btn.click();
}
},
autoLogic: function() {
_BotUI.fixFontSize();
_BotActions.collectAstronomy();
if (!_BotLogic.isAutoLogicStarted) return;
_BotLogic.autoClick();
_BotLogic.autoBuyAll();
_BotLogic.promoteKittens();
_BotLogic.collectFaith();
_BotLogic.ironToSteelOrPlates();
_BotLogic.sendAllHunters();
_BotLogic.cultureToManuscript();
_BotLogic.catnipToWood();
_BotLogic.woodToBeams();
_BotLogic.mineralsToSlabs();
_BotLogic.scienceToCompendium();
},
promoteKittens: function () {
if (_BotSettings.autoPromoteKittens) _BotActions.promoteKittens();
},
collectFaith: function () {
if (_BotSettings.autoCollectFaith) _BotActions.collectFaith();
},
ironToSteelOrPlates: function() {
var iron = game.resPool.get("iron");
var coal = game.resPool.get("coal");
if (iron.value >= iron.maxValue || coal.value >= coal.maxValue) {
var minPlate = _Helpers.getMinCraft('plate');
if (coal.value >= 100 && iron.value >= 100 && _Helpers.isResourceUnlocked('steel')) {
_BotLogic.ironToSteel();
} else if (iron.value >= (125 * minPlate) && _Helpers.isResourceUnlocked('plate')) {
_BotLogic.ironToPlates();
}
}
},
ironToSteel: function () {
if (_BotSettings.autoCreateSteel) _BotActions.ironToSteel();
},
ironToPlates: function () {
if (_BotSettings.autoCreatePlates) _BotActions.ironToPlates();
},
sendAllHunters: function () {
if (_BotSettings.autoSendHunters) _BotActions.sendAllHunters();
},
cultureToManuscript: function () {
if (_BotSettings.autoCreateManuscript) _BotActions.cultureToManuscript();
},
catnipToWood: function () {
if (_BotSettings.autoCreateWood) _BotActions.catnipToWood();
},
woodToBeams: function () {
if (_BotSettings.autoCreateBeams) _BotActions.woodToBeams();
},
mineralsToSlabs: function () {
if (_BotSettings.autoCreateSlabs) _BotActions.mineralsToSlabs();
},
scienceToCompendium: function () {
if (_BotSettings.autoCreateCompendium) _BotActions.scienceToCompendium();
}
};
var KittenTools = {
Helpers: _Helpers,
Actions: _BotActions,
UI: _BotUI,
Settings: _BotSettings,
Logic: _BotLogic
};
var _starter = function() {
_BotLogic.tAutoLogic = setInterval(_BotLogic.autoLogic, 1000);
_BotUI.init();
_BotSettings.init();
_Helpers.log('Started version ' + _Helpers.getBotVersion());
if (typeof game.KittenTools === 'undefined') {
game.KittenTools = KittenTools;
}
if (typeof unsafeWindow !== 'undefined') {
unsafeWindow.KittenTools = KittenTools;
unsafeWindow.cytoscape = cytoscape;
}
};
var _waiter = function() {
if (_Helpers.isGameReady()) {
_starter();
} else {
setTimeout(_waiter, 1000);
}
};
_waiter();
})();