GOTA Extender

Game of Thrones Ascent Extender

当前为 2014-08-18 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        GOTA Extender
// @namespace   gota_extender
// @description Game of Thrones Ascent Extender
// @include     http://gota.disruptorbeam.com/*
// @include     http://gota-www.disruptorbeam.com/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @version     1.8
// @grant       unsafeWindow
// @grant       GM_getValue
// @grant       GM_setValue
// ==/UserScript==

this.$ = this.jQuery = jQuery.noConflict(true);

// Thanks to Nolana (https://greasyfork.org/scripts/1271-gota-improvements)
$(window).bind("load", function () {
    setTimeout(function () {		
        initialize();
    }, 2000);
});

// ------------------------------------------------------------------------------------------------------------------------------------> Configurable variables
var userAlert = GM_getValue('userAlert', true);
var debugAlert = GM_getValue('debugAlert', false);
var autoCollect = GM_getValue('autoCollect', true);
var queueDelay = GM_getValue('queueDelay', 4);							// seconds
var autoCollectInterval = GM_getValue('autoCollectInterval', 60);		// minutes
// <------------------------------------------------------------------------------------------------------------------------------------ End of configurable variables

function initialize() {
    try {
        // Replace buildTimerUpdate
        injectConst(customBuildTimerUpdate);

        // Toggle auto collect
        toggleAutoCollect();

        // Reload window on 22h
        setInterval(function () {
            claimDaily();
            window.location.reload(true);
        }, 22 * 60 * 60 * 1000);

        if (debugAlert) {
            alert('Initialized.');
        }
    } catch (err) {
        if (debugAlert) {
            alert(err);
        }
    }
}

function injectConst(constant) {
    var script = document.createElement('script');
    script.type = "text/javascript";
    script.innerHTML = constant;
    document.head.appendChild(script);
}

var autoCollectLoop;
function toggleAutoCollect() {
    if (autoCollect) {
        autoCollectLoop = setInterval(collectTax, autoCollectInterval * 60 * 1000);

    } else {
        autoCollectLoop = clearInterval(autoCollectLoop);
    }
}

// ------------------------------------------------------------------------------------------------------------------------------------> Constants (generated)
var customBuildTimerUpdate = '\
buildTimerUpdate = function(c, a, b) {\
    $("#timer-" + c).html(renderBuildTime(a));\
    $("#timer-panel-" + c).html(renderBuildTime(a));\
\
    percent = 100 - 100 * (a / b);\
    $("#progress-" + c).html(\'<span style="width:\' + percent + \'%;"></span>\');\
\
    var d = buildingById(c);\
    d.build_remaining = a;\
    markup = renderBuildPanelAction(d);\
\
    $("#speed_button_" + c).show();\
    $("#build_panel_action_" + c).html(markup);\
    $("#production_timer_" + c).html(renderBuildTime(d.build_remaining, true));\
    $("#production_timer_upper_" +\
        c).html(renderBuildTime(d.build_remaining));\
    $("#production_progress_" + c).css({ width: percent + "%" });\
    $("#duration_long_" + c).html(durationLong(buildTimerDescription(d), a, b));\
    a--;\
    userContext.doBuildId == c && (300 >= a ?\
        ($("#speed_up_skip_block").hide(),\
            $("#speed_up_skip_use").show()) :\
        ($("#speed_up_skip_use").hide(),\
            $("#speed_up_skip_block").show()),\
        $(".speed_building_" + c).html() != renderSpeedUpButton(c) && $(".speed_building_" + c).html(renderSpeedUpButton(c)));\
\
    d.cooldown = a;\
    d.original_cooldown_seconds = b;\
    displayBuildingCooldown(d);\
    0 < a || (closeSpeedUp(), finalizeBuildingConstruction(d), clearBuildingTimer(d.symbol));\
\
	if(a < 300){\
		doInstantSpeedUp(c);\
	    var building = buildingById(c);\
        doFinishProduction(building.item_id);\
        setTimeout(function(){\
            closeModalLarge(building.symbol);\
            console.log("EXTENDER :: Injected buildTimerUpdate tries to close modal dialog.");\
        }, 2000);\
    }\
};\
doLog = function(a, b, c){ };';

var extenderButton = '<a id="extender-menu" class="navlink" data-menu="manager">\
    <span class="navlinkbox">\
        <span class="navlinkicon"></span>\
        <span class="vertcenter">\
            <span>Extender</span>\
        </span>\
    </span>\
</a>';

var extenderButtonStyle = '<style>\
 #extender-menu .navlinkicon { \
	background-image: url("http://disruptorbeamcdn-01.insnw.net/images/icons/newnav-menu.png?t=386c1688da2a"); \
 }</style>';

var extenderQueueButton = '<span class="btnwrap btnmed equipbtn queue"><span class="btnedge"><a class="btngold">Queue</a></span></span>';

var saveOptionsButton = '<span id="saveOptions" class="btnwrap btnlg"><span class="btnedge"><a class="btngold">Save</a></span></span>';
var saveOptionsButtonStyle = '<style>\
#saveOptions {\
    bottom: 15px;\
    left: 34%;\
    margin-left: -40px;\
    padding: 0;\
    position: absolute;\
    width: 80px;\
}</style>';

var resetOptionsButton = '<span id="resetOptions" class="btnwrap btnlg"><span class="btnedge"><a class="btngold">Reset</a></span></span>';
var resetOptionsButtonStyle = '<style>\
#resetOptions {\
    bottom: 15px;\
    left: 66%;\
    margin-left: -40px;\
    padding: 0;\
    position: absolute;\
    width: 80px;\
}</style>';

// ------------------------------------------------------------------------------------------------------------------------------------> Mutation observers and associated logic
// Observes DOM object mutations
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

// Observers construction
var mainToolbarObserver = new MutationObserver(main_toolbar_buttons_changed);
var modalsObserver = new MutationObserver(modal_dialog_changed);
var productionObserver = new MutationObserver(production_statview_changed);

// define what element should be observed by the observer
// and what types of mutations trigger the callback
mainToolbarObserver.observe(document.getElementById("main_toolbar_buttons"), {
//	childList: true,
	attributes: true,
//	characterData: true,	
    subtree: true,
	attributeOldValue: true, // if attributes
//	characterDataOldValue: true, // if characterData
//	attributeFilter: ["id", "dir"], // if attributes
});

modalsObserver.observe(document.getElementById("modal_dialogs_top"), {
	childList: true,
});

// Event handlers; FIRED by observed mutations
function modal_dialog_changed(mutations, target){
	if(debugAlert){
		console.log('EXTENDER :: Modal dialogs tree changed.');
	}	
	
	productionObserver.observe(document.getElementById("production_statview"), {
			childList: true,
	});
}

function main_toolbar_buttons_changed(mutations, target) {
    if(debugAlert){
        console.log('EXTENDER :: Mutation on main toolbar buttons.');		
		console.log(mutations);
    }
    
    var extender = $("#extender-menu");
    if (extender.length == 0) {
        $("#navmenubox").append(extenderButton);
        $("#navmenubox").append(extenderButtonStyle);
        $("#extender-menu").on('click', extenderButton_clicked);
    }	
	
	// Attempt production here
	executeProductionElement();
	
}

function executeProductionElement(){
	if(!productionQueue || productionQueue.length == 0){
		return;
	}	    

	var busyBuildings = [];
	for(var i = 0; i <  productionQueue.length; i++){
		var element = productionQueue[i];
		
		// Building found in busy buildings array
		if(busyBuildings.indexOf(element.building.symbol) > -1){
			continue;
		}
		
		// If produce successful, add building to busy array
		if(produce(element)){
			busyBuildings.push(element.building.symbol);
		};
	}
}

function production_statview_changed(){
	if(debugAlert) {
		alert('Production view constructed!');
	}
	
	var btn = '<span class="btnwrap btnmed equipbtn queue" data-quantity="1"><span class="btnedge"><a class="btngold">Queue</a></span></span>';
	var btnx5 = '<span class="btnwrap btnmed equipbtn queue" data-quantity="5"><span class="btnedge"><a class="btngold">Queue x5</a></span></span>';
	
	$(".statviewbtm").prepend(btnx5);
	$(".statviewbtm").prepend(btn);
	
	// Attach event handler
	$("span.btnwrap.btnmed.equipbtn.queue").on('click', queue_clicked);
}

// Keeps queued elements
var productionQueue = [];
function queue_clicked(){

    try {
        // Extract and construct eye-candy stuff
        var divUrl = $("div.statviewimg img").attr('src');
        var statViewName = $(".statviewname h3").text();
        var queueId = 'productionQueueElement_' + productionQueue.length;
        var elementStyle = 'background-image: url("' + divUrl + '"); background-position: 0 center !important; background-size: 100% auto !important;';
        var elementHtml = '<a class="navlink active" id="' + queueId + '">\
				<span class="navlinkbox">\
					<span class="navlinkicon"></span>\
                    <span class="vertcenter">\
						<span>' + statViewName + '</span>\
					</span>\
				</span>\
			   </a>';

        // Extract variables needed
        var building;
        var recipeName;

        var sourceEl = unsafeWindow.userContext.productionItemsClick[unsafeWindow.userContext.currentProductionItem];
        for (var i = 0; i < unsafeWindow.userContext.recipeData.length; i++) {
            if (unsafeWindow.userContext.recipeData[i].output == sourceEl.outputSymbol) {
                recipeName = unsafeWindow.userContext.recipeData[i].symbol;
                break;
            }
        }

        for (var i = 0; i < unsafeWindow.userContext.buildingsData.length; i++) {
            var currentBuilding = unsafeWindow.userContext.buildingsData[i];
            if (currentBuilding.symbol == unsafeWindow.userContext.activeBuildingPanel) {
                building = currentBuilding;
                break;
            }
        }

        // Construct production element
        var productionEl = {
            id: queueId,
            name: statViewName,
            HTML: elementHtml,
            css: elementStyle,
            source: sourceEl,
            building: building,
            recipeName: recipeName,
            recipeData: unsafeWindow.userContext.recipeData,
        };

        var quantity = $(this).attr("data-quantity");
        if (debugAlert) {
            console.log("EXTENDER :: Queued " + quantity + " " + productionEl.name);
        }

        do {
            // Insert the element into the queueArray
            productionQueue.push(productionEl);
            quantity--;
        } while (quantity > 0)

//	var autoQueueBtn = $("#auto-queue");
//	if(!autoQueueBtn || autoQueueBtn.length == 0){
//		constructPanel();
//	}
//
//	$(autoQueueBtn).after(productionEl.HTML);
//	$("#" + productionEl.id + " span.navlinkicon").attr('style', productionEl.css);

        var productionBuilding = unsafeWindow.buildingBySymbol(productionEl.building.symbol);
        if (productionBuilding.build_remaining && productionBuilding.build_remaining > 0) {
            if (userAlert) {
                alert('Enqueued.');
            }
        } else {
            unsafeWindow.doProduction(productionEl.source.outputSymbol, productionEl.source.recipeCategory, null, null, productionEl.recipeName);
        }
        
    } catch (err) {
        if (debugAlert) {
            alert(err);
        }
    }
}

function produce(element){

	// Check if the building is producing
    var productionBuilding = unsafeWindow.buildingBySymbol(element.building.symbol);
	if(productionBuilding.build_remaining && productionBuilding.build_remaining > 0){
		if(debugAlert){
			console.log('EXTENDER :: Attempted production for building ' + element.building.symbol + ', but building was busy.');
		}

		return false;
	}	
	
	if(debugAlert){
		console.log('EXTENDER :: Productiion of '+ element.name +
					' id: '+ element.id +
					' building: '+ element.building.symbol +
					' recipe: '+ element.recipeName);
	}	
	
	// Load data needed for production
	unsafeWindow.userContext.recipeData = element.recipeData;
    unsafeWindow.userContext.activeBuildingPanel = element.building.symbol;

    // Attempt production
	setTimeout(function () {
	    try {
	        if (debugAlert) {
	            console.log("EXTENDER :: Do production, do production!!!!! Now: " + element.name);
	        }
	        unsafeWindow.doProduction(element.source.outputSymbol, element.source.recipeCategory, null, null, element.recipeName);
	    } catch (err) {
            if (debugAlert) {
                alert(err);
            }
	    }
	}, queueDelay * 1000);

	// Remove element from the production array
	var elementPosition = productionQueue.indexOf(element);
	if(elementPosition > -1){
		productionQueue.splice(elementPosition, 1);
	}else{
		if(debugAlert){
			alert('Element missing from production queue!');
		}
		return false;
	}

    if (debugAlert) {
        console.log("EXTENDER :: Production finished. Element popped. Exiting...");
    }

    return true;
}

function collectTax(){
    
    if(debugAlert){
       alert('Collect attempt.');
    }
	
    // Can't use doCollect because of some stupid offset
    // in the animation. needs to have the activePanel set
    unsafeWindow.clickBuildingUpgradePanel('counting_house');
    unsafeWindow.$("#collectbtn").click();
	setTimeout(function() {
	    unsafeWindow.closeModalLarge('modal_dialogs_top');
	    if (debugAlert) {
	        console.log("EXTENDER :: Attempt to close the modal dialog.");
	    }

	}, 2000);
	
}

function setGMValues() {
    GM_setValue("userAlert", userAlert);
    GM_setValue("debugAlert", debugAlert);
    GM_setValue("autoCollect", autoCollect);
    GM_setValue("autoCollectInterval", autoCollectInterval);
}

function showSettings() {
    // Fill in data...
    var extenderHtml = 
		'<h1 style="font-family:GoudyTrajan-Bold,Trajan,\'Trajan Pro\',Trajanbold;">Extender options</h1><hr />'+
		'<a style="color:white;padding-right:4px;padding-left:32px!important;" href="#" id="toggleUserAlerts" class="extender-option checkbox ' + (userAlert ? 'checked' : '') + '">Show user alerts</a>'+
		'<a style="color:white;padding-right:4px;padding-left:32px!important;" href="#" id="toggleDebugAlerts" class="extender-option checkbox ' + (debugAlert ? 'checked' : '') + '">Show debug alerts</a>'+
	    '<a style="color:white;padding-right:4px;padding-left:32px!important;" href="#" id="toggleAutoCollect" class="extender-option checkbox ' + (autoCollect ? 'checked' : '') + '">Enable auto-collecting</a>' +
		    '<br />' +
        '<label for="autoCollectInteval">Auto collect in (minutes):&nbsp;</label>' +
	    '<input type="number" maxlength="3" style="width:38px" id="autoCollectInterval" value="' + autoCollectInterval + '">' +
        '<div class="tablewrap">' +
        '<table id="queueTable" class="powertable">' +
        '<tbody>' +
        '<tr id="headerRow">' +
        '<th id="col1"><span class="colsort">Building</span></th>' +
        '<th id="col2"><span class="colsort">Name</span></th>' +
        '<th id="col3"><span class="colsort">Icon</span></th>' +
        '<th id="col4"><span class="colsort">QueueID</span></th>' +
        '</tr>' +
        '</tbody>' +
        '</table>' +
        '</div>'
    ;

    $("#credits_page").html(extenderHtml);
    renderProductionItems();

    if ($("#saveOptions").length == 0) {
        $("#creditsclose").before(saveOptionsButton);
        $("#creditsclose").before(saveOptionsButtonStyle);

        $("#saveOptions").on('click', saveOptions_click);
    }

    $("#creditsclose").attr('onclick', '(function(){ $("#credits_roll").hide(); })()');

    if ($("#resetOptions").length == 0) {
        $("#creditsclose").after(resetOptionsButton);
        $("#creditsclose").after(resetOptionsButtonStyle);
        $("#resetOptions").on('click', resetOptions_click);
    }

    $("#credits_roll").show();
    //$("#modalbg_dark").show();
}

function extenderButton_clicked(e) {
    e.preventDefault();

    if (debugAlert) {
        alert('Extender menu access.');
    }

    showSettings();
}

function saveOptions_click(e) {
    e.preventDefault();

    userAlert = $("#toggleUserAlerts").hasClass("checked");
    debugAlert = $("#toggleDebugAlerts").hasClass("checked");
    autoCollect = $("#toggleAutoCollect").hasClass("checked");
    
    var newInterval = parseInt($("#autoCollectInterval").val());
    if (autoCollectInterval != newInterval) {
        autoCollectInterval = newInterval;
        autoCollectLoop = null;
        toggleAutoCollect();
    }

    setGMValues();
    $("#credits_roll").hide();

    if (userAlert) {
        alert('Settings saved.');
    }
}

function resetOptions_click(e) {
    e.preventDefault();

    userAlert = true;
    debugAlert = false;
    autoCollect = true;

    autoCollectInterval = 60;
    autoCollectLoop = null;
    toggleAutoCollect();

    setGMValues();
    $("#credits_roll").hide();

    if (userAlert) {
        alert('Options reset.');
    }
}

$("#credits_roll").on('click', '.extender-option.checkbox', function (e) {
    e.preventDefault();

    if (debugAlert) {
        alert('Option changed.');
    }

    $(this).toggleClass('checked');
});

function renderProductionItems() {

    for (var i = 0; i < productionQueue.length; i++) {
        var pEl = productionQueue[i];
        var tableRow =  '<tr class="" style="cursor: pointer" onclick="alert(\'Implement me!\');">'+
                        '<td><span class="name colsort">' + pEl.building.symbol + '</span></td>' +
                        '<td><span class="name colsort">' + pEl.name + '</span></td>' +
                        '<td><span class="avatarimg" id="'+ pEl.id +'"></span></td>' +
                        '<td><span class="ranklist colsort">' + i + '</span></td>' +
                        '</tr>';

        $("#headerRow").after(tableRow);
        $("#" + pEl.id).attr("style", pEl.css);
    }
}