Extender for GoTA
目前為
// ==UserScript==
// @name Game of Thrones Ascent Extender
// @namespace got_manager
// @description Extender for GoTA
// @include http://gota.disruptorbeam.com/*
// @include http://gota-www.disruptorbeam.com/*
// @version 1.0
// @grant none
// ==/UserScript==
// Use this with own @require of jQuery
//this.$ = this.jQuery = jQuery.noConflict(true);
// Disable jQuery effects
//jQuery.fx.off;
// --> Variable declarations
var gManager;
var autoCollectLoop;
var userAlert = true;
var bruteProductionTimer;
var autoCollectInterval = 60; // used in minutes
//<-- End of variables declaration
// --> Constants declarations
const debugAlert = false;
const queueDelay = 22; // used in seconds
const bruteProductionTimeout = 4000; // used in miliseconds
// --- Following constants are only informative
//const gManBtnId = "navlink-auto";
//const mainToolbar = "main_toolbar_buttons";
//const navMenu = "navmenubox";
//const buildingMenu = "buildingmenu";
//<-- End of constants declaration
// Each line ends with '\' to escape end of line character (don't ask)
const panelHTML = '<div id="managermenu" style="display:none">\
\
<a class="navlink active" id="auto-back" href="#">\
<span class="navlinkbox">\
<span class="navlinkicon"></span>\
<span class="vertcenter"><span>Menu</span></span>\
</span>\
</a>\
\
<div id="buildingmenubox" style="height: 127px !important">\
\
<a class="buildingmenuarrow buildingarrowleft toolbarbuttonback" onclick="toolbarScrollDirection(\'building_items\', \'left\', true);"></a>\
<div class="buildingmenucrop scrollable" id="building_scrollable">\
<a id="auto-collect" class="navlink active" href="#">\
<span class="navlinkbox">\
<span class="navlinkicon"></span>\
<span class="vertcenter">\
<span>Collect</span>\
</span>\
</span>\
</a>\
<a id="auto-queue" class="navlink active">\
<span class="navlinkbox">\
<span class="navlinkicon"></span>\
<span class="vertcenter">\
<span>Queue</span>\
</span>\
</span>\
<span class="buildingmenuarrow buildingarrowright toolbarbuttonforward"></span>\
</a>\
\
</div>\
<a class="buildingmenuarrow buildingarrowright toolbarbuttonforward" onclick="toolbarScrollDirection(\'building_items\', \'right\', true);"></a>\
\
</div>\
\
<div class="contentbtm"></div>\
\
</div>';
// Each line ends with '\' to escape end of line character (don't ask)
const panelStyle = '<style>\
#managermenu {\
background: url("http://disruptorbeamcdn-01.insnw.net/images/city/buildingpanelbg.jpg?t=78c5ef26ae48") repeat-x scroll 0 0 #0e0e0e;\
bottom: 2px;\
height: 178px;\
left: 5px;\
position: absolute;\
right: 5px;\
width: auto;\
}\
\
#auto-back {\
left: 19px;\
position: absolute;\
top: 26px;\
}\
\
#auto-back .navlinkicon {\
background-image: url("http://disruptorbeamcdn-01.insnw.net/images/icons/newnav-menu.png?t=78c5ef26ae48");\
}\
\
#auto-queue.navlink.active {\
margin-right: 3%;\
}\
#auto-collect .navlinkicon {\
background-image: url("http://disruptorbeamcdn-01.insnw.net/images/icons/newnav-shop.png?t=77bdf10c9699");\
}\
</style>';
// Each line ends with '\' to escape end of line character (don't ask)
const queueBtn = '<span class="btnwrap btnmed equipbtn">\
<span class="btnedge">\
<a class="btngold">Queue</a>\
</span>\
</span>';
// 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,
// attributes: true,
// characterData: true,
// subtree: true,
// attributeOldValue: true, // if attributes
// characterDataOldValue: true, // if characterData
// attributeFilter: ["id", "dir"], // if attributes
});
// Event handlers; FIRED by observed mutations
function modal_dialog_changed(mutations, target){
if(debugAlert){
alert('Modal dialogs tree changed.');
}
productionObserver.observe(document.getElementById("production_statview"), {
childList: true,
// attributes: true,
// characterData: true,
// subtree: true,
// attributeOldValue: true, // if attributes
// characterDataOldValue: true, // if characterData
// attributeFilter: ["id", "dir"], // if attributes
});
}
function main_toolbar_buttons_changed(mutations, target) {
if(debugAlert){
alert('Mutation on main toolbar buttons.');
console.log(mutations);
}
var container = $("#navmenubox");
if(!container || container.length == 0) {
if(debugAlert){
alert("No such container for button found.");
}
return;
}
var gManBtn = $("#navlink-auto");
if (!gManBtn || gManBtn.length == 0){
addButton(container);
}
//finishAllBuildings();
// Attempt production here
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"><span class="btnedge"><a class="btngold">Queue</a></span></span>';
$(".statviewbtm").prepend(btn);
// Attach event handler
$("span.btnwrap.btnmed.equipbtn.queue").on('click', queue_clicked);
}
// Keeps queued elements
var productionQueue = [];
function queue_clicked(){
// 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 = userContext.productionItemsClick[userContext.currentProductionItem];
for(var i=0; i< userContext.recipeData.length; i++){
if(userContext.recipeData[i].output == sourceEl.outputSymbol){
recipeName = userContext.recipeData[i].symbol;
break;
}
}
for(var i=0; i < userContext.buildingsData.length; i++){
var currentBuilding = userContext.buildingsData[i];
if(currentBuilding.symbol == 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: userContext.recipeData,
};
// Insert the element into the queueArray
productionQueue.push(productionEl);
var autoQueueBtn = $("#auto-queue");
if(!autoQueueBtn || autoQueueBtn.length == 0){
constructPanel();
}
$(autoQueueBtn).after(productionEl.HTML);
$("#" + productionEl.id + " span.navlinkicon").attr('style', productionEl.css);
if(userAlert && !produce(productionEl)){
alert('Enqueued.');
}
}
function produce(element){
// Check if the building is producing
var productionBuilding = buildingBySymbol(element.building.symbol);
if(productionBuilding.build_remaining && productionBuilding.build_remaining > 0){
if(debugAlert){
alert('Building busy.');
}
return false;
}
if(debugAlert){
console.log('Productiion of '+ element.name +
' id: '+ element.id +
' building: '+ element.building.symbol +
' recipe: '+ element.recipeName);
}
// Load data needed for production
userContext.recipeData = element.recipeData;
userContext.activeBuildingPanel = element.building.symbol;
// Attempt production
try{
customDoFinishProduction(element);
}catch(err){
if(userAlert){
alert(err);
}
return false;
}
// 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;
}
// Remove object html
var htmlElement = $("#" + element.id);
if(htmlElement){
$(htmlElement).remove();
}else{
if(debugAlert){
alert('Element\'s HTML is missing!');
}
return false;
}
return true;
}
function constructPanel(pageElement) {
$(pageElement).after(panelStyle);
$(pageElement).after(panelHTML);
gManager = $("#managermenu");
// Style buttons according to function on/off
if(autoCollectLoop){
$("#auto-collect").find(".navlinkbox").addClass("btngreen");
} else {
$("#auto-collect").find(".navlinkbox").removeClass("btngreen");
}
for(var i=0; i< productionQueue.length; i++){
var productionEl = productionQueue[i];
$("#auto-queue").after(productionEl.HTML);
$("#" + productionEl.id + " span.navlinkicon").attr('style', productionEl.css);
}
attachEventHandlers();
}
function attachEventHandlers() {
$("#auto-back").on('click', function(e){
e.preventDefault();
$(gManager).hide();
$("#main_toolbar_buttons").show();
});
// Auto Collect logic here; it's so small 'n' simple, keep it here
$("#auto-collect").on('click', function(e){
e.preventDefault();
//console.log(autoCollectLoop == null);
if(autoCollectLoop){
autoCollectLoop = clearInterval(autoCollectLoop);
$("#auto-collect").find(".navlinkbox").removeClass("btngreen");
if(userAlert){
alert('Auto-collect stopped.');
}
} else {
autoCollectLoop = setInterval(collectTax, autoCollectInterval*60*1000);
$("#auto-collect").find(".navlinkbox").addClass("btngreen");
if(userAlert){
alert('Auto-collect started - interval ' + autoCollectInterval + ' min.');
}
}
});
//$("#auto-queue").on('click', produce);
}
/*function finishAllBuildings(){
for(var i=0; i < productionQueue.length; i++) {
var currentBuilding = buildingByItemId(productionQueue[i].building.item_id);
if(currentBuilding && currentBuilding.upgrade_pending > 0){
if(debugAlert){
console.log(currentBuilding);
}
doFinishProduction(currentBuilding.item_id);
}
}
}*/
function addButton(container) {
// Construct html for the button
var button = '<a id="navlink-auto" class="navlink" data-menu="manager"> <span class="navlinkbox"> <span class="navlinkicon"></span><span class="vertcenter"><span>Auto</span></span></span></a>';
//var buttonStyle = '<style> #gm-auto-tax .navlinkicon { background-image: url("http://disruptorbeamcdn-01.insnw.net/images/icons/newnav-shop.png?t=072fac808ce1"); }</style>';
// Prepend to the container
//$(container).prepend(buttonStyle);
$(container).prepend(button);
// Reference the object, attach a listener and return it
var btnObj = $("#navlink-auto");
$(btnObj).on('click', button_listener);
return btnObj;
}
function button_listener() {
if(debugAlert){
alert("Button clicked.");
}
var btnToolBar = $("#main_toolbar_buttons");
var bdMenu = $("#buildingmenu");
if(!btnToolBar || btnToolBar.length == 0 || !bdMenu || bdMenu.length == 0) {
if(debugAlert) {
alert("Components not found!");
}
return;
}
gManager = $("#managermenu");
if(!gManager || gManager.length == 0) {
constructPanel(bdMenu);
}
$(btnToolBar).hide();
$(gManager).show();
}
function collectTax(){
if(debugAlert){
alert('Collect attempt.');
}
// doCollect(276768733); -> building.item_id
clickBuildingUpgradePanel('counting_house');
$("#collectbtn").click();
// $("#animatedCoinsSparkle")
$("#animatedCoins").promise().done(function(){
//$("#modal_close").click();
closeModalLarge('modal_dialogs_top');
});
}
// DO NOT use that function;
// Clears all timers on the page
function killAllTimers() {
var maxId = setTimeout(function(){}, 0);
for(var i=0; i < maxId; i+=1) {
clearTimeout(i);
}
}
function customDoFinishProduction(element) {
var c = element.building.item_id
var a = buildingByItemId(c), b = itemFromId(a.producing_archetype_id);
userContext.lastFinish = a.symbol;
doLog("doFinishProduction: building_id=" + c + " symbol=" + a.symbol + " producing=" + b.symbol);
"Upgrade" !== b.slot && (analytics.track("Production Finish", { building_symbol: a.symbol, item_symbol: b.symbol, item_category: b.slot }), analytics.wizardtrack("Production Finish", { building_symbol: a.symbol, item_symbol: b.symbol, item_category: b.slot }));
var d = "finish-" + c;
userLock(d) && (playSound("build"),
isWeb() && $("#collect_" + a.symbol).html(""),
$.ajax({
url: "/play/finish_production/" + c,
dataType: "JSON",
success: function(a) {
doLog("doFinishProduction: succeess ");
freeLock(d);
var b = buildingByItemId(c, a.building);
userContext.playerData.character = a.character;
userContext.playerData.user.money = a.user.money;
userContext.playerData.stat.onboarding = a.stat.onboarding;
userContext.playerData.stat.num_items_produced = a.stat.num_items_produced;
userContext.playerData.stat.produced_stone = a.stat.produced_stone;
userContext.playerData.stat.building_upgrades_finished =
a.stat.building_upgrades_finished;
b.producing_archetype_id = void 0;
b.modifier = void 0;
b.recipe_symbol = void 0;
var f = extractItemBySymbol(playerInventory, b.symbol);
f.effective_upgrade_level = a.building.effective_upgrade_level;
f.producing_archetype_id = void 0;
f.modifier = void 0;
f.recipe_symbol = void 0;
if (a.produced_item)
if (userContext.intCurrentRecipeIndex = void 0, doLog("doFinishProduction: data.produced_item.id=" + a.produced_item.id + " quantity=" + a.produced_item.quantity), insertInventoryFromItem(playerInventory,
a.produced_item), theNewItem = extractItemById(playerInventory, a.produced_item.id), 1 == a.is_loot) 0 < a.enhanced_loot_roll ? dialogAlert({ style: "alert", text: "The result of your production (enhanced) is: " + a.produced_full_name, items: [theNewItem], heading: "You have produced...", button1: "Okay" }) : dialogAlert({ style: "alert", text: "The result of your production is: " + a.produced_full_name, items: [theNewItem], heading: "You have produced...", button1: "Okay" });
else if (0 < a.affix_chance) {
var m;
m = "" + ("You have a " + a.affix_chance_from_stats +
"% chance to produce a superior-quality item from your talents, equipment and buildings.");
a.bonus_item_name && (m += " Your " + a.bonus_item_name + " adds another +" + a.affix_chance_from_bonus + "% chance to produce a superior-quality item from your talents, equipment and buildings.");
m = a.affix_roll1 <= a.affix_chance && a.affix_roll2 <= a.affix_chance ? m + "<p/>Critical Success! You obtained a superb result!" : a.affix_roll1 > a.affix_chance && a.affix_roll2 > a.affix_chance ? m + "<p/>You obtained a normal result." : m + "<p/>Success! You obtained a good result.";
dialogAlert({ style: "alert", text: m, items: [theNewItem], heading: a.produced_full_name, button1: "Okay" });
}
userContext.newBldgOrUpgrade = !0;
var q;
"Upgrade" != theNewItem.slot ? (userContext.newProducedItem = theNewItem, isWeb() && $("#collect_" + f.symbol).html(renderUpgradeCollect(f)), isWeb() && $("#build_panel_action_" + f.id).html(renderBuildPanelAction(f)), isWeb() && $("#speed_button_" + f.id).hide()) : q = theNewItem.symbol;
isWeb() ? (renderBuildingInventory(userContext.playerData), renderBuildingsOnScreen(userContext.playerData)) :
(f = void 0, f = void 0 == q ? { symbol: b.symbol, status: "idle" } : { symbol: b.symbol, status: "idle", upgrade: q }, iosSignal("finish_production", "update", f), isAndroid() && mobileCooldownDataSignal([{ mode: "building", symbol: b.symbol }]), refreshActiveBuildingPanel(), $("#building_tab_prod, .buildingupgradetree").fadeTo("slow", "1"));
uiEvent("do_finish_production");
uiEvent("building_panel_" + userContext.activeBuildingPanel);
a.produced_item && "stacks_of_coins" == a.produced_item.symbol && retrievePlayerData(!0, function(a) {
userContext.playerData.quests =
a.quests;
reRenderQuestActionItems();
});
"Upgrade" == theNewItem.slot && buildingUpgradePanel(b.symbol);
updatePlayerInfo(userContext.playerData);
updateAllStatus();
bruteProductionTimer = setInterval(customDoProduction(element.source.outputSymbol, element.source.recipeCategory, null, null, element.recipeName), bruteProductionTimeout);
}
}));
}
function customDoProduction(c, a, b, d, g) {
userContext.lastFinish = void 0;
void 0 == b && (b = 1);
doLog("doProduction: symbol=" + c + " producer=" + a + " quantity=" + b);
var p = void 0, f = "", m = void 0, q = "", k = void 0, D = void 0;
uiEvent("start_production");
void 0 == userContext.playerData.stat.num_shop_items_started && (userContext.playerData.stat.num_shop_items_started = 0);
userContext.playerData.stat.num_shop_items_started += 1;
for (var w = 0; w < userContext.recipeData.length; w++)
if (console.log("DEBUG: n=" + userContext.recipeData[w].category + ", symbol: " +
userContext.recipeData[w].output), g == userContext.recipeData[w].symbol || void 0 == g && (userContext.recipeData[w].output == c || userContext.recipeData[w].output_loot == c) && userContext.recipeData[w].category == a) {
p = userContext.recipeData[w];
p.output == c ? (k = itemFromSymbol(c), q = k.full_name) : (p.output_loot == c && (m = c), q = p.name);
D = w;
components = userContext.recipeData[w].input.split(",");
quantity_components = userContext.recipeData[w].input_quantity.split(",");
var s = itemFromSymbol(userContext.recipeData[w].category);
if (!0 ==
userContext.recipeData[w].unlocked) {
if (1 < userContext.recipeData[w].input.length)
for (s = 0; s < components.length; s++) {
var y = itemFromSymbol(components[s]), u = !1;
0 == s && !0 == userContext.recipeData[w].evolution && (u = !0);
u = sumInventoryQuantity(y.symbol, u);
if (parseInt(quantity_components[s]) * b > u) {
"" == f && (f = "You need more of the following:<p/>");
f += "<div>";
if (4 <= userContext.playerData.character.level)
switch (components[s]) {
case "stone":
case "iron":
case "fur":
case "ore":
case "horse":
case "riverways_fish_consumable":
case "smallfolk":
case "wood":
case "cloth":
case "grains":
u =
parseInt(quantity_components[s]) * b - u;
if (cost_item = itemFromSymbol("pennyroyal"))var z = cost_item.price_perk_points * u;
f += '<div id="basic_resource_' + components[s] + '">';
f += itemMiniView(y, { extra_styles: "left:-70px", quantity_override: u });
f += '<span style="position: relative; left: 250px; top: -88px" class="btnwrap btnmed btnprice" onclick="getBasicResource(\'' + components[s] + "'," + u + ',true);"><span class="btnedge"><a class="btngold">Get Now</a><em>for</em><strong>' + z + "</strong></span></span>";
f += "</div>";
break;
default:
f += itemMiniView(y);
}
f += "</div>";
f += "<p>" + y.howto + "</p>";
}
}
} else f = "You need <em>" + s.full_name + "</em> to produce that.";
break;
}
if ("" != f)doAlert("Requirements: " + q, f), analytics.track("Production Blocked-Resources", { item_symbol: c }), analytics.wizardtrack("Production Blocked-Resources", { item_symbol: c });
else if (p && hasMoney(p.craft_cost * b, function() { doProduction(c, a, b, d, g) })) {
f = JSON.parse(JSON.stringify(userContext.playerData.inventory));
w = [];
p.output == c ? (k = itemFromSymbol(c), q = k.full_name) : (p.output_loot ==
c && (m = c), q = p.name);
components = p.input.split(",");
quantity_components = p.input_quantity.split(",");
s = itemFromSymbol(p.category);
if (!0 == p.unlocked && (userContext.intCurrentRecipeIndex = D, 1 < p.input.length))for (s = 0; s < components.length; s++)y = itemFromSymbol(components[s]), u = !1, 0 == s && !0 == p.evolution && (u = !0), depleteItems(y.symbol, parseInt(quantity_components[s]) * b, void 0, w, u);
q = "";
D = void 0;
for (s = 0; s < w.length; s++)
if (y = itemFromSymbol(w[s].symbol), w[s].full_name != y.full_name)
D = JSON.parse(JSON.stringify(w[s])),
q += "[" + w[s].full_name + "]";
else if (itemHasSeals(w[s]) && (!w[s].preserve_attributes || !1 == w[s].preserve_attributes))D = JSON.parse(JSON.stringify(w[s])), y = generateSealNameList(w[s]), q += "[" + w[s].full_name + " : " + y + "]";
if (!0 != d && void 0 != D)
return playerInventory = JSON.parse(JSON.stringify(f)), userContext.playerData.inventory = playerInventory, dialogAlert({
style: "confirm",
margin_top: 100,
items: [D],
button2: "Not Now",
button2_action: function() { closeAlert(); },
button1: "Confirm",
button1_action: function() {
closeAlert();
return doProduction(c, a, b, !0, g);
},
heading: "Confirm Superior Materials",
text: "Producing this item now will consume superior versions of your materials: " + q + "<p/>Are you sure you want to contribute superior versions of materials to produce this item?"
}), !1;
var I = buildingBySymbol(userContext.activeBuildingPanel);
I.build_remaining = p.craft_duration * b;
I.original_build_seconds = p.craft_duration * b;
I.build_progress = 0;
"" != p.output && (I.producing_archetype_id = itemFromSymbol(p.output).id);
I.recipe_symbol = p.symbol;
I.action_sub_id = b;
f = renderBuildingConstruction(I);
isWeb() && $("#bc_" + I.id).html(f);
displayBuildingCooldown(I);
"Upgrade" == itemFromId(I.producing_archetype_id).slot ? buildingUpgradePanel(userContext.activeBuildingPanel, !0, !1) : (buildingUpgradePanel(userContext.activeBuildingPanel, !0, !1, !0), buildingTabProd(), isWeb() && $("#collect_" + I.symbol).html(renderUpgradeCollect(I)));
p = "/play/set_production";
p = (m ? p + ("?loot_symbol=" + m + "&producer_symbol=" + a) : k ? p + ("/" + c + "?producer_symbol=" + a) : p + ("?producer_symbol=" + a)) +
("&quantity=" + b);
g && (p += "&recipe_symbol=" + g);
$.ajax({
url: p,
dataType: "JSON",
success: function(a) {
userContext.prodProgressShow = void 0;
userContext.playerData.stat.num_shop_items_started = a.num_shop_items_started;
updateAllStatus();
uiEvent("do_production");
isWeb() || iosSignal("building", "cooldown", mobileCooldownData({ mode: "building", symbol: I.symbol, flag: "production_started" }));
bruteProductionTimer = clearInterval(bruteProductionTimer);
}
});
}
}