// ==UserScript==
// @name hwmTransporter
// @namespace Tamozhnya1
// @version 8.9
// @description Перемещения по карте, поиск работы и засады с любой страницы
// @author Tamozhnya1
// @encoding utf-8
// @include *heroeswm.ru/*
// @include *lordswm.com/*
// @grant GM_log
// @grant GM_listValues
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM.xmlHttpRequest
// @grant GM.notification
// @license MIT
// ==/UserScript==
if(typeof GM_getValue != 'function') {
this.GM_getValue = function (key,def) { return localStorage[key] || def; };
this.GM_setValue = function (key,value) { return localStorage[key] = value; };
this.GM_deleteValue = function (key) { return delete localStorage[key]; };
}
const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
if(playerIdMatch) {
var PlayerId = playerIdMatch[1];
}
if(!PlayerId) {
GM_deleteValue("TransporterUserName");
return;
}
const isEn = document.documentElement.lang == "en";
var AmbushState = { Setted: 1, Battle: 2 };
var finalResultDiv;
const isHeartOnPage = document.querySelector("canvas#heart") || document.querySelector("div#heart_js_mobile");
// Граф всех возможных путей перемещения по карте
const routes = [null,
[null,null,["1-2",1],["1-3",1],["1-4",1.4],["1-5",1],["1-3-6",2],["1-7",1.4],["1-8",1],["1-3-9",2.4],["1-5-10",2],["1-11",1.4],["1-12",1.4],["1-8-13",2.4],["1-2-14",2],["1-2-15",2.4],["1-4-16",2.8],["1-2-14-17",3],["1-2-14-18",3.4],["1-5-19",2.4],["1-5-10-20",3.4],["1-5-19-21",3.8],["1-5-10-20-22",4.8],["1-12-23",2.8],["1-3-24",2.4],null,["1-5-26",2.4],["1-8-27",2]],
[null,["2-1",1],null,["2-3",1.4],["2-4",1],["2-5",1.4],["2-3-6",2.4],["2-1-7",2.4],["2-1-8",2],["2-3-9",2.8],["2-5-10",2.4],["2-11",1],["2-1-12",2.4],["2-1-8-13",3.4],["2-14",1],["2-15",1.4],["2-4-16",2.4],["2-14-17",2],["2-14-18",2.4],["2-11-19",2],["2-11-19-20",3],["2-11-19-21",3.4],["2-11-19-20-22",4.4],["2-3-9-23",3.8],["2-4-24",2],null,["2-5-26",2.8],["2-1-8-27",3]],
[null,["3-1",1],["3-2",1.4],null,["3-4",1],["3-1-5",2],["3-6",1],["3-1-7",2.4],["3-8",1.4],["3-9",1.4],["3-1-5-10",3],["3-1-11",2.4],["3-12",1],["3-12-13",2],["3-2-14",2.4],["3-4-15",2],["3-4-16",2.4],["3-2-14-17",3.4],["3-4-15-18",3],["3-1-5-19",3.4],["3-1-5-10-20",4.4],["3-1-5-19-21",4.8],["3-1-5-19-21-22",5.8],["3-9-23",2.4],["3-24",1.4],null,["3-1-5-26",3.4],["3-8-27",2.4]],
[null,["4-1",1.4],["4-2",1],["4-3",1],null,["4-1-5",2.4],["4-6",1.4],["4-1-7",2.8],["4-1-8",2.4],["4-3-9",2.4],["4-1-5-10",3.4],["4-2-11",2],["4-3-12",2],["4-3-12-13",3],["4-14",1.4],["4-15",1],["4-16",1.4],["4-14-17",2.4],["4-15-18",2],["4-2-11-19",3],["4-2-11-19-20",4],["4-2-11-19-21",4.4],["4-2-11-19-20-22",5.4],["4-3-9-23",3.4],["4-24",1],null,["4-1-5-26",3.8],["4-1-8-27",3.4]],
[null,["5-1",1],["5-2",1.4],["5-1-3",2],["5-1-4",2.4],null,["5-1-3-6",3],["5-7",1],["5-8",1.4],["5-1-3-9",3.4],["5-10",1],["5-11",1],["5-1-12",2.4],["5-8-13",2.8],["5-2-14",2.4],["5-2-15",2.8],["5-1-4-16",3.8],["5-2-14-17",3.4],["5-2-14-18",3.8],["5-19",1.4],["5-10-20",2.4],["5-19-21",2.8],["5-10-20-22",3.8],["5-1-12-23",3.8],["5-1-3-24",3.4],null,["5-26",1.4],["5-7-27",2.4]],
[null,["6-3-1",2],["6-3-2",2.4],["6-3",1],["6-4",1.4],["6-3-1-5",3],null,["6-3-1-7",3.4],["6-3-8",2.4],["6-9",1],["6-3-1-5-10",4],["6-3-1-11",3.4],["6-12",1.4],["6-9-13",2.4],["6-4-14",2.8],["6-4-15",2.4],["6-4-16",2.8],["6-4-14-17",3.8],["6-4-15-18",3.4],["6-3-1-5-19",4.4],["6-3-1-5-10-20",5.4],["6-3-1-5-19-21",5.8],["6-3-1-5-10-20-22",6.8],["6-9-23",2],["6-24",1],null,["6-3-1-5-26",4.4],["6-12-27",2.8]],
[null,["7-1",1.4],["7-1-2",2.4],["7-1-3",2.4],["7-1-4",2.8],["7-5",1],["7-1-3-6",3.4],null,["7-8",1],["7-8-12-9",3],["7-10",1.4],["7-5-11",2],["7-8-12",2],["7-8-13",2.4],["7-1-2-14",3.4],["7-1-2-15",3.8],["7-1-4-16",4.2],["7-1-2-14-17",4.4],["7-1-2-14-18",4.8],["7-5-19",2.4],["7-10-20",2.8],["7-5-19-21",3.8],["7-10-20-22",4.2],["7-8-12-23",3.4],["7-1-3-24",3.8],null,["7-26",1],["7-27",1.4]],
[null,["8-1",1],["8-1-2",2],["8-3",1.4],["8-1-4",2.4],["8-5",1.4],["8-3-6",2.4],["8-7",1],null,["8-12-9",2],["8-5-10",2.4],["8-1-11",2.4],["8-12",1],["8-13",1.4],["8-1-2-14",3],["8-1-2-15",3.4],["8-1-4-16",3.8],["8-1-2-14-17",4],["8-1-2-14-18",4.4],["8-5-19",2.8],["8-5-10-20",3.8],["8-5-19-21",4.2],["8-5-10-20-22",5.2],["8-12-23",2.4],["8-3-24",2.8],null,["8-7-26",2],["8-27",1]],
[null,["9-3-1",2.4],["9-3-2",2.8],["9-3",1.4],["9-3-4",2.4],["9-3-1-5",3.4],["9-6",1],["9-12-8-7",3],["9-12-8",2],null,["9-3-1-5-10",4.4],["9-3-1-11",3.8],["9-12",1],["9-13",1.4],["9-3-2-14",3.8],["9-3-4-15",3.4],["9-3-4-16",3.8],["9-3-2-14-17",4.8],["9-3-4-15-18",4.4],["9-3-1-5-19",4.8],["9-3-1-5-10-20",5.8],["9-3-1-5-19-21",6.2],["9-3-1-5-10-20-22",7.2],["9-23",1],["9-6-24",2],null,["9-12-8-7-26",4],["9-12-27",2.4]],
[null,["10-5-1",2],["10-5-2",2.4],["10-5-1-3",3],["10-5-1-4",3.4],["10-5",1],["10-5-1-3-6",4],["10-7",1.4],["10-5-8",2.4],["10-5-1-3-9",4.4],null,["10-11",1.4],["10-5-1-12",3.4],["10-5-8-13",3.8],["10-11-14",2.8],["10-5-2-15",3.8],["10-5-1-4-16",4.8],["10-11-14-17",3.8],["10-11-14-18",4.2],["10-19",1],["10-20",1.4],["10-19-21",2.4],["10-20-22",2.8],["10-5-1-12-23",4.8],["10-5-1-3-24",4.4],null,["10-26",1],["10-7-27",2.8]],
[null,["11-1",1.4],["11-2",1],["11-1-3",2.4],["11-2-4",2],["11-5",1],["11-1-3-6",3.4],["11-5-7",2],["11-1-8",2.4],["11-1-3-9",3.8],["11-10",1.4],null,["11-1-12",2.8],["11-1-8-13",3.8],["11-14",1.4],["11-2-15",2.4],["11-2-4-16",3.4],["11-14-17",2.4],["11-14-18",2.8],["11-19",1],["11-19-20",2],["11-19-21",2.4],["11-19-20-22",3.4],["11-1-12-23",4.2],["11-2-4-24",3],null,["11-5-26",2.4],["11-5-7-27",3.4]],
[null,["12-1",1.4],["12-1-2",2.4],["12-3",1],["12-3-4",2],["12-1-5",2.4],["12-6",1.4],["12-8-7",2],["12-8",1],["12-9",1],["12-1-5-10",3.4],["12-1-11",2.8],null,["12-13",1],["12-1-2-14",3.4],["12-3-4-15",3],["12-3-4-16",3.4],["12-1-2-14-17",4.4],["12-3-4-15-18",4],["12-1-5-19",3.8],["12-1-5-10-20",4.8],["12-1-5-19-21",5.2],["12-1-5-10-20-22",6.2],["12-23",1.4],["12-3-24",2.4],null,["12-8-7-26",3],["12-27",1.4]],
[null,["13-8-1",2.4],["13-8-1-2",3.4],["13-12-3",2],["13-12-3-4",3],["13-8-5",2.8],["13-9-6",2.4],["13-8-7",2.4],["13-8",1.4],["13-9",1.4],["13-8-5-10",3.8],["13-8-1-11",3.8],["13-12",1],null,["13-8-1-2-14",4.4],["13-12-3-4-15",4],["13-12-3-4-16",4.4],["13-8-1-2-14-17",5.4],["13-12-3-4-15-18",5],["13-8-5-19",4.2],["13-8-5-10-20",5.2],["13-8-5-19-21",5.6],["13-8-5-10-20-22",6.6],["13-23",1],["13-9-6-24",3.4],null,["13-8-7-26",3.4],["13-27",1]],
[null,["14-2-1",2],["14-2",1],["14-2-3",2.4],["14-4",1.4],["14-2-5",2.4],["14-4-6",2.8],["14-2-1-7",3.4],["14-2-1-8",3],["14-2-3-9",3.8],["14-11-10",2.8],["14-11",1.4],["14-2-1-12",3.4],["14-2-1-8-13",4.4],null,["14-15",1],["14-15-16",2],["14-17",1],["14-18",1.4],["14-11-19",2.4],["14-11-19-20",3.4],["14-11-19-21",3.8],["14-11-19-20-22",4.8],["14-2-3-9-23",4.8],["14-4-24",2.4],null,["14-2-5-26",3.8],["14-2-1-8-27",4]],
[null,["15-2-1",2.4],["15-2",1.4],["15-4-3",2],["15-4",1],["15-2-5",2.8],["15-4-6",2.4],["15-2-1-7",3.8],["15-2-1-8",3.4],["15-4-3-9",3.4],["15-2-5-10",3.8],["15-2-11",2.4],["15-4-3-12",3],["15-4-3-12-13",4],["15-14",1],null,["15-16",1],["15-17",1.4],["15-18",1],["15-2-11-19",3.4],["15-2-11-19-20",4.4],["15-2-11-19-21",4.8],["15-2-11-19-21-22",5.8],["15-4-3-9-23",4.4],["15-24",1.4],null,["15-2-5-26",4.2],["15-2-1-8-27",4.4]],
[null,["16-4-1",2.8],["16-4-2",2.4],["16-4-3",2.4],["16-4",1.4],["16-4-1-5",3.8],["16-4-6",2.8],["16-4-1-7",4.2],["16-4-1-8",3.8],["16-4-3-9",3.8],["16-4-1-5-10",4.8],["16-4-2-11",3.4],["16-4-3-12",3.4],["16-4-3-12-13",4.4],["16-15-14",2],["16-15",1],null,["16-15-17",2.4],["16-18",1.4],["16-4-2-11-19",4.4],["16-4-2-11-19-20",5.4],["16-4-2-11-19-21",5.8],["16-4-2-11-19-20-22",6.8],["16-4-3-9-23",4.8],["16-4-24",2.4],null,["16-4-1-5-26",5.2],["16-4-1-8-27",4.8]],
[null,["17-14-2-1",3],["17-14-2",2],["17-14-2-3",3.4],["17-14-4",2.4],["17-14-2-5",3.4],["17-14-4-6",3.8],["17-14-2-1-7",4.4],["17-14-2-1-8",4],["17-14-2-3-9",4.8],["17-14-11-10",3.8],["17-14-11",2.4],["17-14-2-1-12",4.4],["17-14-2-1-8-13",5.4],["17-14",1],["17-15",1.4],["17-15-16",2.4],null,["17-18",1],["17-14-11-19",3.4],["17-14-11-19-20",4.4],["17-14-11-19-21",4.8],["17-14-11-19-21-22",5.8],["17-14-2-3-9-23",5.8],["17-15-24",2.8],null,["17-14-2-5-26",4.8],["17-14-2-1-8-27",5]],
[null,["18-14-2-1",3.4],["18-14-2",2.4],["18-15-4-3",3],["18-15-4",2],["18-14-2-5",3.8],["18-15-4-6",3.4],["18-14-2-1-7",4.8],["18-14-2-1-8",4.4],["18-15-4-3-9",4.4],["18-14-11-10",4.2],["18-14-11",2.8],["18-15-4-3-12",4],["18-15-4-3-12-13",5],["18-14",1.4],["18-15",1],["18-16",1.4],["18-17",1],null,["18-14-11-19",3.8],["18-14-11-19-20",4.8],["18-14-11-19-21",5.2],["18-14-11-19-20-22",6.2],["18-15-4-3-9-23",5.4],["18-15-24",2.4],null,["18-14-2-5-26",5.2],["18-14-2-1-8-27",5.4]],
[null,["19-5-1",2.4],["19-11-2",2],["19-5-1-3",3.4],["19-11-2-4",3],["19-5",1.4],["19-5-1-3-6",4.4],["19-5-7",2.4],["19-5-8",2.8],["19-5-1-3-9",4.8],["19-10",1],["19-11",1],["19-5-1-12",3.8],["19-5-8-13",4.2],["19-11-14",2.4],["19-11-2-15",3.4],["19-11-2-4-16",4.4],["19-11-14-17",3.4],["19-11-14-18",3.8],null,["19-20",1],["19-21",1.4],["19-20-22",2.4],["19-5-1-12-23",5.2],["19-11-2-4-24",4],null,["19-10-26",2],["19-5-7-27",3.8]],
[null,["20-10-5-1",3.4],["20-19-11-2",3],["20-10-5-1-3",4.4],["20-19-11-2-4",4],["20-10-5",2.4],["20-10-5-1-3-6",5.4],["20-10-7",2.8],["20-10-5-8",3.8],["20-10-5-1-12-9",5.8],["20-10",1.4],["20-19-11",2],["20-10-5-1-12",4.8],["20-10-5-8-13",5.2],["20-19-11-14",3.4],["20-19-11-2-15",4.4],["20-19-11-2-4-16",5.4],["20-19-11-14-17",4.4],["20-19-11-14-18",4.8],["20-19",1],null,["20-21",1],["20-22",1.4],["20-10-5-1-12-23",6.2],["20-19-11-2-4-24",5],null,["20-10-26",2.4],["20-10-7-27",4.2]],
[null,["21-19-5-1",3.8],["21-19-11-2",3.4],["21-19-5-1-3",4.8],["21-19-11-2-4",4.4],["21-19-5",2.8],["21-19-5-1-3-6",5.8],["21-19-5-7",3.8],["21-19-5-8",4.2],["21-19-5-1-3-9",6.2],["21-19-10",2.4],["21-19-11",2.4],["21-19-5-1-12",5.2],["21-19-5-8-13",5.6],["21-19-11-14",3.8],["21-19-11-2-15",4.8],["21-19-11-2-4-16",5.8],["21-19-11-14-17",4.8],["21-19-11-14-18",5.2],["21-19",1.4],["21-20",1],null,["21-22",1],["21-19-5-1-12-23",6.6],["21-19-11-2-4-24",5.4],null,["21-19-10-26",3.4],["21-19-5-7-27",5.2]],
[null,["22-20-10-5-1",4.8],["22-20-19-11-2",4.4],["22-20-10-5-1-3",5.8],["22-20-19-11-2-4",5.4],["22-20-10-5",3.8],["22-20-10-5-1-3-6",6.8],["22-20-10-7",4.2],["22-20-10-5-8",5.2],["22-20-10-5-1-12-9",7.2],["22-20-10",2.8],["22-20-19-11",3.4],["22-20-10-5-1-12",6.2],["22-20-10-5-8-13",6.6],["22-20-19-11-14",4.8],["22-20-19-11-2-15",5.8],["22-20-19-11-2-4-16",6.8],["22-20-19-11-14-17",5.8],["22-20-19-11-14-18",6.2],["22-20-19",2.4],["22-20",1.4],["22-21",1],null,["22-20-10-5-1-12-23",7.6],["22-20-19-11-2-4-24",6.4],null,["22-20-10-26",3.8],["22-20-10-7-27",5.6]],
[null,["23-12-1",2.8],["23-9-3-2",3.8],["23-9-3",2.4],["23-9-3-4",3.4],["23-12-1-5",3.8],["23-9-6",2],["23-12-8-7",3.4],["23-12-8",2.4],["23-9",1],["23-12-1-5-10",4.8],["23-12-1-11",4.2],["23-12",1.4],["23-13",1],["23-9-3-2-14",4.8],["23-9-3-4-15",4.4],["23-9-3-4-16",4.8],["23-9-3-2-14-17",5.8],["23-9-3-4-15-18",5.4],["23-12-1-5-19",5.2],["23-12-1-5-10-20",6.2],["23-12-1-5-19-21",6.6],["23-12-1-5-10-20-22",7.6],null,["23-9-6-24",3],null,["23-12-8-7-26",4.4],["23-13-27",2]],
[null,["24-3-1",2.4],["24-4-2",2],["24-3",1.4],["24-4",1],["24-3-1-5",3.4],["24-6",1],["24-3-1-7",3.8],["24-3-8",2.8],["24-6-9",2],["24-3-1-5-10",4.4],["24-4-2-11",3],["24-3-12",2.4],["24-6-9-13",3.4],["24-4-14",2.4],["24-15",1.4],["24-4-16",2.4],["24-15-17",2.8],["24-15-18",2.4],["24-4-2-11-19",4],["24-4-2-11-19-20",5],["24-4-2-11-19-21",5.4],["24-4-2-11-19-20-22",6.4],["24-6-9-23",3],null,null,["24-3-1-5-26",4.8],["24-3-8-27",3.8]],
[],
[null,["26-5-1",2.4],["26-5-2",2.8],["26-5-1-3",3.4],["26-5-1-4",3.8],["26-5",1.4],["26-5-1-3-6",4.4],["26-7",1],["26-7-8",2],["26-7-8-12-9",4],["26-10",1],["26-5-11",2.4],["26-7-8-12",3],["26-7-8-13",3.4],["26-5-2-14",3.8],["26-5-2-15",4.2],["26-5-1-4-16",5.2],["26-5-2-14-17",4.8],["26-5-2-14-18",5.2],["26-10-19",2],["26-10-20",2.4],["26-10-19-21",3.4],["26-10-20-22",3.8],["26-7-8-12-23",4.4],["26-5-1-3-24",4.8],null,null,["26-7-27",2.4]],
[null,["27-8-1",2],["27-8-1-2",3],["27-8-3",2.4],["27-8-1-4",3.4],["27-7-5",2.4],["27-12-6",2.8],["27-7",1.4],["27-8",1],["27-12-9",2.4],["27-7-10",2.8],["27-7-5-11",3.4],["27-12",1.4],["27-13",1],["27-8-1-2-14",4],["27-8-1-2-15",4.4],["27-8-1-4-16",4.8],["27-8-1-2-14-17",5],["27-8-1-2-14-18",5.4],["27-7-5-19",3.8],["27-7-10-20",4.2],["27-7-5-19-21",5.2],["27-7-10-20-22",5.6],["27-13-23",2],["27-8-3-24",3.8],null,["27-7-26",2.4]]];
// Номера, названия и координаты секторов
const locations = {
1: [50,50,"Empire Capital","EmC","Столица Империи"],
2: [51,50,"East River","EsR","Восточная Река"],
3: [50,49,"Tiger Lake","TgL","Тигриное Озеро"],
4: [51,49,"Rogues' Wood","RgW","Лес Разбойников"],
5: [50,51,"Wolf Dale","WoD","Долина Волков"],
6: [50,48,"Peaceful Camp","PcC","Мирный Лагерь"],
7: [49,51,"Lizard Lowland","LzL","Равнина Ящеров"],
8: [49,50,"Green Wood","GrW","Зеленый Лес"],
9: [49,48,"Eagle Nest","EgN","Орлиное Гнездо"],
10: [50,52,"Portal Ruins","PoR","Руины Портала"],
11: [51,51,"Dragons' Caves","DrC","Пещеры Драконов"],
12: [49,49,"Shining Spring","ShS","Сияющий Родник"],
13: [48,49,"Sunny City","SnC","Солнечный Город"],
14: [52,50,"Magma Mines","MgM","Магма Шахты"],
15: [52,49,"Bear Mountain","BrM","Медвежья Гора"],
16: [52,48,"Fairy Trees","FrT","Магический Лес"],
17: [53,50,"Harbour City","HrC","Портовый Город"],
18: [53,49,"Mythril Coast","MfC","Мифриловый Берег"],
19: [51,52,"Great Wall","GtW","Великая Стена"],
20: [51,53,"Titans' Valley","TiV","Равнина Титанов"],
21: [52,53,"Fishing Village","FsV","Рыбачье село"],
22: [52,54,"Kingdom Castle","KiC","Замок Королевства"],
23: [48,48,"Ungovernable Steppe","UnS","Непокорная Степь"],
24: [51,48,"Crystal Garden","CrG","Кристальный Сад"],
25: [53,52,"East Island","EsI","Восточный Остров"],
26: [49,52,"The Wilderness","ThW","Дикие земли"],
27: [48,50,"Sublime Arbor","SbA","Великое Древо"],
101: [48, 53, "Watchers' guild", "", "Гильдия стражей", { Url: "/task_guild.php", Color: "DarkGoldenRod" }],
102: [48, 54, "Leaders' Guild", "", "Гильдия лидеров", { Url: "/leader_guild.php", Color: "DarkGoldenRod" }],
103: [49, 54, "Adventurers' guild", "", "Гильдия искателей", { Url: "/campaign_list.php", Color: "DarkGoldenRod" }],
104: [50, 54, "Thieves' guild", "", "Гильдия воров", { Url: "/thief_guild.php", Color: "DarkGoldenRod" }],
105: [51, 54, "Smith", "", "Кузница", { Url: "/mod_workbench.php?type=repair", Color: "DarkGoldenRod" }]
};
const objectLocations = { 0 : 0
, 5: 1, 9: 1, 6: 1, 7: 1, 4: 1, 3: 1, 8: 1, 165: 1, 10: 1, 11: 1, 12: 1, 32: 1, 34: 1, 38: 1
, 238: 2, 300: 2, 75: 2, 26: 2, 258: 2, 279: 2, 25: 2, 23: 2, 33: 2, 342: 2, 24: 2, 36: 2, 87: 2, 89: 2, 321: 2, 28: 2
, 239: 3, 16: 3, 15: 3, 13: 3, 259: 3, 343: 3, 280: 3, 84: 3, 301: 3, 224: 3, 27: 3, 39: 3, 14: 3, 31: 3, 35: 3, 322: 3
, 344: 4, 281: 4, 302: 4, 260: 4, 19: 4, 21: 4, 22: 4, 323: 4, 18: 4, 20: 4, 30: 4, 37: 4, 78: 4, 90: 4, 225: 4, 240: 4
, 282: 5, 74: 5, 226: 5, 43: 5, 44: 5, 303: 5, 85: 5, 45: 5, 46: 5, 47: 5, 48: 5, 86: 5, 241: 5, 261: 5, 324: 5, 345: 5
, 50: 6, 283: 6, 262: 6, 304: 6, 73: 6, 49: 6, 141: 6, 51: 6, 79: 6, 53: 6, 54: 6, 55: 6, 52: 6, 82: 6, 325: 6, 346: 6
, 56: 7, 326: 7, 59: 7, 64: 7, 284: 7, 58: 7, 60: 7, 61: 7, 63: 7, 80: 7, 83: 7, 242: 7, 263: 7, 57: 7, 305: 7, 347: 7
, 285: 8, 243: 8, 68: 8, 88: 8, 69: 8, 67: 8, 71: 8, 72: 8, 76: 8, 77: 8, 81: 8, 70: 8, 264: 8, 306: 8, 327: 8, 348: 8
, 244: 9, 328: 9, 227: 9, 265: 9, 286: 9, 94: 9, 349: 9, 139: 9, 307: 9, 101: 9, 98: 9, 95: 9, 119: 9, 120: 9, 140: 9, 97: 9
, 163: 10, 329: 10, 350: 10, 99: 10, 100: 10, 102: 10, 118: 10, 211: 10, 217: 10, 287: 10, 308: 10, 93: 10, 228: 10, 266: 10, 245: 10, 92: 10
, 167: 11, 169: 11, 168: 11, 210: 11, 172: 11, 170: 11, 209: 11, 171: 11, 218: 11, 229: 11, 246: 11, 267: 11, 288: 11, 309: 11, 330: 11, 351: 11
, 247: 12, 331: 12, 289: 12, 219: 12, 117: 12, 108: 12, 111: 12, 110: 12, 109: 12, 112: 12, 113: 12, 114: 12, 230: 12, 268: 12, 310: 12, 352: 12
, 104: 13, 311: 13, 269: 13, 220: 13, 116: 13, 248: 13, 332: 13, 106: 13, 107: 13, 115: 13, 213: 13, 231: 13, 103: 13, 290: 13, 105: 13, 353: 13
, 270: 14, 122: 14, 312: 14, 249: 14, 216: 14, 333: 14, 164: 14, 291: 14, 121: 14, 135: 14, 142: 14, 143: 14, 144: 14, 145: 14, 232: 14, 354: 14
, 313: 15, 334: 15, 124: 15, 125: 15, 214: 15, 136: 15, 123: 15, 146: 15, 147: 15, 148: 15, 149: 15, 215: 15, 250: 15, 271: 15, 292: 15, 355: 15
, 335: 16, 233: 16, 272: 16, 251: 16, 126: 16, 134: 16, 153: 16, 151: 16, 127: 16, 152: 16, 150: 16, 212: 16, 221: 16, 293: 16, 314: 16, 356: 16
, 131: 17, 252: 17, 273: 17, 315: 17, 294: 17, 336: 17, 162: 17, 161: 17, 160: 17, 132: 17, 133: 17, 222: 17, 234: 17, 158: 17, 159: 17, 357: 17
, 358: 18, 235: 18, 253: 18, 130: 18, 129: 18, 137: 18, 138: 18, 154: 18, 128: 18, 155: 18, 156: 18, 157: 18, 274: 18, 295: 18, 316: 18, 337: 18
, 192: 19, 202: 19, 179: 19, 173: 19, 193: 19, 194: 19, 195: 19, 201: 19, 178: 19, 203: 19, 254: 19, 275: 19, 296: 19, 317: 19, 338: 19, 359: 19
, 191: 20, 176: 20, 177: 20, 187: 20, 188: 20, 189: 20, 190: 20, 206: 20, 207: 20, 208: 20, 255: 20, 276: 20, 297: 20, 318: 20, 339: 20, 360: 20
, 174: 21, 199: 21, 197: 21, 166: 21, 361: 21, 198: 21, 196: 21, 200: 21, 223: 21, 236: 21, 256: 21, 277: 21, 298: 21, 319: 21, 340: 21, 175: 21
, 186: 22, 184: 22, 320: 22, 185: 22, 183: 22, 362: 22, 182: 22, 180: 22, 204: 22, 205: 22, 237: 22, 257: 22, 278: 22, 299: 22, 341: 22, 181: 22
, 365: 23, 364: 23, 370: 23, 363: 23, 369: 23, 366: 23, 371: 23, 372: 23, 373: 23, 374: 23, 375: 23, 376: 23, 377: 23, 378: 23, 379: 23, 380: 23
, 367: 24, 392: 24, 390: 24, 388: 24, 383: 24, 384: 24, 385: 24, 386: 24, 387: 24, 368: 24, 389: 24, 381: 24, 391: 24, 382: 24, 393: 24, 394: 24
, 395: 26, 409: 26, 399: 26, 397: 26, 398: 26, 400: 26, 401: 26, 402: 26, 403: 26, 404: 26, 405: 26, 406: 26, 407: 26, 408: 26, 396: 26, 410: 26
, 411: 27, 419: 27, 413: 27, 414: 27, 415: 27, 416: 27, 417: 27, 418: 27, 412: 27, 420: 27, 421: 27, 422: 27, 423: 27, 424: 27, 425: 27, 426: 27
};
const minX = 48;
const maxX = 53;
const minY = 48;
const maxY = 54;
const DefaultTravelingTime = 40;
let AmbushMinutesInterval = 60;
const ClientServerTimeDifferenceRequestInterval = 60 * 60 * 1000;
const isMobileInterface = document.querySelector("div#btnMenuGlobal") ? true : false;
const GoTo = isEn ? "Go to" : "Перейти в";
const Second = isEn ? "sec." : "с.";
const YourPremiumMountUntil = isEn ? "Your premium mount until" : "Ваш премиум транспорт";
const YourMountUntil = isEn ? "Your mount until" : "Ваш транспорт до";
const Until = isEn ? " until " : " до ";
const UndressBeforeMove = isEn ? "Undress before move" : "Раздеться перед перемещением";
const NotUseComplexRoute = isEn ? "Not use complex route" : "Не использовать сложный маршрут";
const HideMapName = isEn ? "Hide map" : "Скрыть карту";
const HideHuntName = isEn ? "Hide hunt" : "Скрыть охоты";
const HideRightBlockName = isEn ? "Hide right block" : "Скрыть правый блок";
const ComplexRouteName = isEn ? "Complex route" : "Сложный маршрут";
const MountUntilName = isEn ? "Mount until" : "Транспорт до";
const BreakTravelingName = isEn ? "Break traveling" : "Прервать путешествие";
const TravelingNotEnabled = isEn ? "Traveling not enabled" : "Путешествие не доступно";
const YouAreInAChallenge = isEn ? "You are in a challenge. Your actions are limited!" : "Вы находитесь в заявке на бой. Ваши действия ограничены!";
const How = isEn ? "How?" : "Как?";
const YouAreHere = isEn ? "You're already here" : "Ты уже здесь";
const AmbushMaySettedOnAdjacentSector = isEn ? "Ambush may setted on adjacent sector" : "Засада ставится на соседний сектор";
const ItIsTooEarly = isEn ? "It is too early" : "Ещё рано";
const Legend = isEn ? "Click: moving, ctrl(mdl)+click: ambush, alt+click: sector info" : "Click: движение, ctrl(mdl)+click: засада, alt+click: просмотр";
const MoveHere = isEn ? "Move here" : "Перейти сюда";
const YouAreInADifferentLocation = isEn ? "You are in a different location." : "Вы находитесь в другом районе.";
const TravelingTimeName = isEn ? "Traveling time" : "Время пути";
const Antithief = isEn ? "Antithief" : "Антивор";
const AmbushingName = isEn ? "You are in ambush" : "Вы в засаде";
const CheckMountName = isEn ? "Check mount" : "Проверить транспорт";
const LoadName = isEn ? "Load" : "Грузить";
const PremiunAccountName = isEn ? "Abu" : "Абу";
const locationNamesLocalizedColumn = isEn ? 2 : 4;
const AmbushResult = { NotFound: 0, Win: 1, Fail: 2 };
const factoryTypes = ["mn", "fc", "sh"];
const Mining = isEn ? "Mining" : "Добыча";
const Machining = isEn ? "Machining" : "Обработка";
const Production = isEn ? "Production" : "Производство";
const PopupAlwaysName = isEn ? "Popup always" : "Всегда всплывающая";
const HideBattlesDayWithName = isEn ? "Hide battles day with..." : "Скрыть день боёв с...";
const FindNearestMiningName = isEn ? "Find nearest mining" : "Найти ближайшую добычу";
const FindNearestManufactureName = isEn ? "Find nearest manufacture" : "Найти ближайшую обработку";
const FindNearestProductionName = isEn ? "Find nearest production" : "Найти ближайшее производство";
const MoveToWorkAfterFindName = isEn ? "Move to work after find" : "Сразу идти на предприятие";
const ShowLocationNumbersName = isEn ? "Show location numbers" : "Номера локаций";
const JobFinding = isEn ? "Job finding" : "Поиск работы";
const windowObject = window.wrappedJSObject || unsafeWindow;
let persGvStopped = false;
let playerLocationNumber = getPlayerLocationNumber();
if(!playerLocationNumber) {
return; // При первом запуске скрипта, если мы не на карте, неизвестна текущая локация игрока
}
let MountInfo;
var AmbushMoratoriumPanel;
main();
async function main(forceGetMountInfo) {
initUserName();
MountInfo = await getMountInfo(forceGetMountInfo);
AmbushMinutesInterval *= 1 - (MountInfo.IsPremiunAccount ? 0.3 : 0);
tryGetAmbushState();
if(!isHeartOnPage) {
return;
}
healthTimer();
requestServerTime();
checkActivity();
setActivity();
if(/map.php/.test(location.href)) {
const mapRightBlock = document.getElementById("map_right_block");
if(!mapRightBlock) {
drawStopButton();
return; // Нет правого блока с предприятиями, значит мы в пути. Скрипт не выполняем
}
GM_setValue("LastObservingLocationNumber", location.search != '' ? getLocationNumberFromMapUrlByXy(location.href) : playerLocationNumber);
loadFactories();
}
drawMap();
processMoving();
checkAmbushResult();
if(location.pathname == '/object-info.php') {
const center = document.querySelector("body center");
const objectLocationReference = center.querySelector("a[href*='map.php?cx='][href*='&cy=']");
//console.log(`center: ${center}, objectLocationReference: ${objectLocationReference}`);
const moveHereReference = getMoveToObjectReference(location.pathname + location.search, objectLocationReference); // Добавление кнопки перемещения на предприятие
}
if(location.pathname == '/ecostat_details.php' || location.pathname == '/home.php') {
const objs = document.querySelectorAll("a[href*='object-info.php?id=']");
const doubledHash = [];
for(let obj of objs) {
if(!doubledHash.includes(obj.href)) {
const moveHereReference = getMoveToObjectReference(obj.href, obj);
doubledHash.push(obj.href);
}
}
}
if(location.pathname == '/group_wars.php') {
addMoveToMapObjectReferences();
}
if(location.pathname == '/mercenary_guild.php') {
const colorElement = document.querySelector("font[color='#E65054']");
if(colorElement.querySelector("b").innerText == YouAreInADifferentLocation) {
const lastObservingLocationNumber = parseInt(GM_getValue("LastObservingLocationNumber", 0));
if([2, 6, 16, 21].includes(lastObservingLocationNumber)) {
const ref = getMoveToMapObjectReference(location.href, colorElement, lastObservingLocationNumber);
} else {
const nearestLocations = getLocationsSortedByDistance();
//console.log(`nearestLocations: ${nearestLocations}`);
for(const nearestLocation of nearestLocations) {
if([2, 6, 16, 21].includes(parseInt(nearestLocation))) {
const ref = getMoveToMapObjectReference(location.href, colorElement, nearestLocation);
break;
}
}
}
}
}
if(location.pathname == '/pirate_event.php') {
const tableDiv = document.getElementById("tableDiv");
addMoveToMapObjectReferences(tableDiv);
}
processHouseInfo();
}
function checkActivity() {
checkTurnedOn();
setTimeout(checkActivity, 1000);
}
function setActivity() {
checkTurnedOn();
GM_setValue("LastActivityDate", Date.now());
setTimeout(setActivity, 60 * 1000);
}
function checkTurnedOn() {
const now = Date.now();
const computerTurnedOn = parseInt(GM_getValue("LastActivityDate", 0)) + 5 * 60 * 1000 < now;
//console.log(`now: ${now}, LastActivityDate: ${GM_getValue("LastActivityDate")}, computerTurnedOn: ${computerTurnedOn}`);
if(computerTurnedOn) {
//console.log(`now: ${now}, LastActivityDate: ${GM_getValue("LastActivityDate")}, computerTurnedOn: ${computerTurnedOn}`);
checkAmbushResult(true);
}
}
function addMoveToMapObjectReferences(element) {
element = element || document;
const locationRefs = element.querySelectorAll("a[href^='map.php?cx=']");
for(let locationRef of locationRefs) {
const locationNumber = getLocationNumberByCoordinate(getUrlParamValue(locationRef.href, "cx"), getUrlParamValue(locationRef.href, "cy"));
const ref = getMoveToMapObjectReference(location.href, locationRef, locationNumber);
}
}
function getObjectLocations() {
const objs = document.querySelectorAll("a[href*='object-info.php?id=']");
let absentList = "";
for(let obj of objs) {
const objectId = getUrlParamValue(obj.href, "id");
if(!objectLocations[objectId]) {
objectLocations[objectId] = playerLocationNumber;
absentList += `, ${objectId}: ${playerLocationNumber}`;
}
}
if(absentList != "") {
ShowBigData(absentList);
}
//console.log(absentList);
}
function drawStopButton() {
const mapRightBlock = document.getElementById("map_right_block");
//console.log([MountInfo.ComplexRoute, GM_getValue("IgnoreComplexRoute"), GM_getValue("IgnoreComplexRoute") == "true", (!MountInfo.ComplexRoute) || (GM_getValue("IgnoreComplexRoute") == "true")]);
if(!mapRightBlock && GM_getValue("TargetLocationNumber") && (!MountInfo.ComplexRoute || gmGetBool("IgnoreComplexRoute"))) {
let targetLocationNumber = parseInt(GM_getValue("TargetLocationNumber"));
let route = routes[playerLocationNumber][targetLocationNumber][0];
let nextLocationNumber = route.split('-')[1];
if(nextLocationNumber != targetLocationNumber) {
const insideMap = document.querySelector("#inside_map");
const mapMoving = addElement("div", insideMap, { id: "mapMoving" });
const stopMovingButton = addElement("div", mapMoving, { id: "stopMovingButton", class: "home_button2 btn_hover2 map_btn_width", style: "width: 300px;", innerHTML: BreakTravelingName });
stopMovingButton.addEventListener("click", stopMoving, false);
}
}
}
async function toggleAntithief(toggleAntithiefCheckbox) {
const toggleKey = GM_getValue("ToggleAntithiefKey");
if(toggleKey && MountInfo.AntithiefControlled) {
const toggleVar = toggleAntithiefCheckbox.checked ? "t_on" : "t_off";
//console.log(`toggleKey: ${toggleKey}, url: /shop.php?${toggleVar}=${toggleKey}&cat=transport`);
await getRequest(`/shop.php?${toggleVar}=${toggleKey}&cat=transport`);
}
}
function toggleHuntBlock() {
const map_hunt_block_div = document.getElementById("map_hunt_block_div");
if(map_hunt_block_div) {
const mapRightBlock = document.getElementById("map_right_block");
let mapRightBlockHeight = mapRightBlock.offsetHeight;
if(gmGetBool("HideHuntBlock")) {
mapRightBlockHeight -= map_hunt_block_div.offsetHeight;
}
map_hunt_block_div.style.display = gmGetBool("HideHuntBlock") ? "none" : "block";
if(!gmGetBool("HideHuntBlock")) {
mapRightBlockHeight += map_hunt_block_div.offsetHeight;
}
mapRightBlock.style.height = `${mapRightBlockHeight}px`;
}
}
function toggleBattlesDayWith() {
const mapRightBlock = document.querySelector("#map_right_block");
if(mapRightBlock) {
const battlesDayTable = mapRightBlock.querySelector("table.wbwhite");
if(battlesDayTable && !battlesDayTable.classList.contains("rounded_table")) {
battlesDayTable.style.display = gmGetBool("HideBattlesDayWithBlock") ? "none" : "";
}
}
}
function toggleRightBlock() {
const mapRightBlock = document.getElementById("map_right_block");
if(mapRightBlock) {
mapRightBlock.style.display = gmGetBool("HideRightBlock") ? "none" : "block";
}
}
function tryGetAmbushState() {
if(location.pathname == '/map.php') {
const ambushDiv = Array.from(document.querySelectorAll("div#map_right_block .wbwhite.rounded_table")).find(x => x.innerHTML.includes(AmbushingName));
if(ambushDiv) {
GM_setValue("AmbushState", AmbushState.Setted);
GM_deleteValue("AmbushSuspendExpireDate");
} else {
if(GM_getValue("AmbushState") == AmbushState.Setted) {
GM_deleteValue("AmbushState");
}
}
}
if(location.pathname == '/war.php') {
const warId = getUrlParamValue(location.href, "warid");
const lt = getUrlParamValue(location.href, "lt");
finalResultDiv = document.getElementById("finalresult_text");
if(lt != "-1" && finalResultDiv.innerHTML.length <= 10 && GM_getValue("AmbushState") == AmbushState.Setted) {
GM_setValue("AmbushState", AmbushState.Battle);
observe(finalResultDiv, parseBattleResultPanel);
}
}
console.log(`tryGetAmbushState AmbushState: ${GM_getValue("AmbushState")}`);
}
function parseBattleResultPanel() {
if(GM_getValue("AmbushState") == AmbushState.Battle && finalResultDiv.innerHTML.length > 10) {
GM_deleteValue("AmbushState");
const bolds = finalResultDiv.querySelectorAll("font b");
let result = "fail";
for(const bold of bolds) {
if(bold.innerHTML == (isEn ? "Victorious:" : "Победившая сторона:")) {
console.log(bold.parentNode.nextSibling.nextSibling.firstChild.innerText);
if(bold.parentNode.nextSibling.nextSibling.firstChild.innerText == GM_getValue("TransporterUserName")) {
result = "win";
}
break;
}
}
if(result == "fail") {
GM_setValue("AmbushSuspendExpireDate", Date.now() + AmbushMinutesInterval * 60 * 1000);
}
console.log(`result: ${result}, AmbushSuspendExpireDate: ${GM_getValue("AmbushSuspendExpireDate")}`);
}
}
async function checkAmbushResult(force = false) {
console.log(`checkAmbushResult force: ${force}, AmbushState: ${GM_getValue("AmbushState")}, AmbushSuspendExpireDate: ${GM_getValue("AmbushSuspendExpireDate")}`);
const afterAmbushUnknownResult = GM_getValue("AmbushState") == AmbushState.Battle; // После засады был бой
if(afterAmbushUnknownResult && !isFullHealth() && !force) {
GM_setValue("AmbushSuspendExpireDate", Date.now() + AmbushMinutesInterval * 60 * 1000);
} else {
let doc;
if(location.pathname == '/pl_warlog.php') {
const page = getUrlParamValue(location.href, "page");
const id = getUrlParamValue(location.href, "id");
if(id == PlayerId && (!page || page == 0)) {
doc = document;
}
}
if(doc || afterAmbushUnknownResult || force) {
doc = doc || await getRequest(`/pl_warlog.php?id=${PlayerId}`);
processWarlog(doc);
}
}
if(afterAmbushUnknownResult) {
GM_deleteValue("AmbushState");
}
refreshAmbushMoratoriumPanel();
}
function getHealth() {
const health_amount = document.getElementById("health_amount");
let health;
if(health_amount) {
health = parseInt(health_amount.innerText);
} else {
health = windowObject.heart;
}
return health;
}
function isFullHealth() {
const healthRestoreTime = parseInt(GM_getValue("HealthRestoreTime", 0));
return healthRestoreTime < Date.now();
}
function healthTimer() {
if(isHeartOnPage) {
const health_amount = document.getElementById("health_amount");
let heart; // 78
let maxHeart; // 100
let timeHeart; // 405
if(health_amount) {
const res = /top_line_draw_canvas_heart\((\d+), (\d+), (\d+)\);/.exec(document.body.innerHTML); // top_line_draw_canvas_heart(0, 100, 405);
if(res) {
heart = parseInt(res[1]);
maxHeart = parseInt(res[2]);
timeHeart = parseInt(res[3]);
}
} else {
heart = windowObject.heart;
maxHeart = windowObject.max_heart;
timeHeart = windowObject.time_heart;
}
console.log(`healthTimer heart: ${heart}, maxHeart: ${maxHeart}, timeHeart: ${timeHeart}`);
let restSeconds = timeHeart * (maxHeart - heart) / maxHeart;
if(restSeconds > 0) {
GM_setValue("HealthRestoreTime", Date.now() + restSeconds * 1000);
} else {
GM_deleteValue("HealthRestoreTime");
}
}
expireHealthRestoreTime();
}
function expireHealthRestoreTime() {
const healthRestoreTime = parseInt(GM_getValue("HealthRestoreTime", 0));
//console.log(`expireHealthRestoreTime healthRestoreTime: ${healthRestoreTime}}`);
if(healthRestoreTime > 0) {
if(Date.now() > healthRestoreTime) {
GM_deleteValue("HealthRestoreTime");
drawAmbushMarks();
} else {
setTimeout(expireHealthRestoreTime, 1000);
}
}
}
function processWarlog(doc) {
const lastAmbushRef = Array.from(doc.querySelectorAll("a[href*='warlog.php?warid=']")).find(x => x.nextSibling.textContent == ": • ");
let lastAmbushResult = AmbushResult.NotFound;
if(lastAmbushRef) {
lastAmbushResult = lastAmbushRef.nextElementSibling.tagName.toLowerCase() == "b" ? AmbushResult.Win : AmbushResult.Fail;
var lastAmbushDate = toClientTime(parseDate(lastAmbushRef.innerText));
}
if(lastAmbushDate) {
if(lastAmbushResult == AmbushResult.Fail) {
const newAmbushSuspendExpireDate = lastAmbushDate.getTime() + (AmbushMinutesInterval + 1) * 60 * 1000;
// Если нет старого значения AmbushSuspendExpireDate или расхождение с новым из лога больше минуты, то установим новое, если оно ещё актуально
if(!GM_getValue("AmbushSuspendExpireDate") || Math.abs(parseInt(GM_getValue("AmbushSuspendExpireDate")) - newAmbushSuspendExpireDate) > 60 * 1000) {
if(newAmbushSuspendExpireDate > Date.now()) {
GM_setValue("AmbushSuspendExpireDate", newAmbushSuspendExpireDate);
} else {
GM_deleteValue("AmbushSuspendExpireDate");
}
}
}
} else {
GM_deleteValue("AmbushSuspendExpireDate");
}
console.log(`processWarlog lastAmbushResult: ${lastAmbushResult}, lastAmbushDate: ${lastAmbushDate.toLocaleString()}, ambushSuspendExpireDate: ${fromTimeSpanToString(GM_getValue("AmbushSuspendExpireDate"))}`);
}
function fromTimeSpanToString(timeSpan) {
if(timeSpan) {
return (new Date(parseInt(timeSpan))).toLocaleString();
}
}
function toClientTime(serverDateTime) {
//console.log(`LastRequestedClientServerTimeDifferenceMilliseconds: ${GM_getValue("LastRequestedClientServerTimeDifferenceMilliseconds", 0)}, serverDateTime.getTime(): ${serverDateTime.getTime()}, ${serverDateTime.getTime() + GM_getValue("LastRequestedClientServerTimeDifferenceMilliseconds", 0)}`);
return new Date(serverDateTime.getTime() + parseInt(GM_getValue("LastRequestedClientServerTimeDifferenceMilliseconds", 0)));
}
function getServerTime() { return Date.now() + parseInt(GM_getValue("LastRequestedClientServerTimeDifferenceMilliseconds", 0)); }
function requestServerTime() {
if(parseInt(GM_getValue("LastClientServerTimeDifferenceRequestDate", 0)) + ClientServerTimeDifferenceRequestInterval < (new Date().getTime())) {
GM_setValue("LastClientServerTimeDifferenceRequestDate", new Date().getTime());
const objXMLHttpReqTime = new XMLHttpRequest();
objXMLHttpReqTime.open('GET', '/time.php?rand=' + (Math.random() * 1000000), true);
objXMLHttpReqTime.onreadystatechange = function() {
if(objXMLHttpReqTime.readyState == 4 && objXMLHttpReqTime.status == 200) {
let responseParcing = /now (\d+)/.exec(objXMLHttpReqTime.responseText); //objXMLHttpReqTime.responseText: now 1681711364 17-04-23 09:02
if(responseParcing) {
GM_setValue("LastRequestedClientServerTimeDifferenceMilliseconds", new Date().getTime() - parseInt(responseParcing[1]) * 1000);
}
}
}
objXMLHttpReqTime.send(null);
} else {
setTimeout(function() { requestServerTime(); }, ClientServerTimeDifferenceRequestInterval);
}
}
function truncDateTimeToMinutes(dateTime) {
const coeff = 1000 * 60;
return new Date(Math.floor(dateTime.getTime() / coeff) * coeff);
}
function refreshAmbushMoratoriumPanel() {
if(GM_getValue("AmbushSuspendExpireDate")) {
const ambushMoratoriumEndDate = parseInt(GM_getValue("AmbushSuspendExpireDate"));
const now = Date.now();
//console.log(`ambushMoratoriumEndDate > now: ${ambushMoratoriumEndDate > now}`);
if(ambushMoratoriumEndDate > now) {
const formatedTime = formatInterval(ambushMoratoriumEndDate - now);
setAmbushMoratoriumPanelValue(formatedTime);
const pers_gv = refreshAmbushMoratoriumPanel.pers_gv || (refreshAmbushMoratoriumPanel.pers_gv = document.querySelector("#pers_gv"));
persGvStopped = persGvStopped || pers_gv && pers_gv.innerText == "00:00" && formatedTime != "00:00";
if(persGvStopped) {
pers_gv.innerText = formatedTime;
}
setTimeout(refreshAmbushMoratoriumPanel, 1000);
} else {
setAmbushMoratoriumPanelValue();
GM_deleteValue("AmbushSuspendExpireDate");
if(gmGetBool("ThievesGuildNotifications")) {
GM.notification("Вы можете устроить засаду", "ГВД", "https://dcdn.heroeswm.ru/i/portraits/thiefwarrioranip33.png", function() { window.focus(); getURL("/map.php"); });
}
persGvStopped = false;
drawAmbushMarks();
}
} else {
setAmbushMoratoriumPanelValue();
drawAmbushMarks();
}
}
function setAmbushMoratoriumPanelValue(value) {
if(AmbushMoratoriumPanel) {
AmbushMoratoriumPanel.innerText = value || "";
}
}
function formatInterval(interval) {
let diff = interval;
const hours = Math.floor(diff / 1000 / 60 / 60);
diff -= hours * 1000 * 60 * 60;
const mimutes = Math.floor(diff / 1000 / 60);
diff -= mimutes * 1000 * 60;
const seconds = Math.floor(diff / 1000);
const formatedTime = (hours > 0 ? hours + ":" : "") + ( (mimutes < 10) ? '0' : '' ) + mimutes + ':' + (seconds < 10 ? '0' : '') + seconds;
return formatedTime;
}
function drawMap() {
const insideMap = document.querySelector("#inside_map");
const jsmap = document.querySelector("#jsmap");
const isHideMap = gmGetBool("HideMap");
const mapRightBlock = document.getElementById("map_right_block");
if(jsmap) {
jsmap.style.display = isHideMap ? "none" : "block";
}
toggleRightBlock();
toggleBattlesDayWith();
toggleHuntBlock();
if(insideMap && (!gmGetBool("PopupAlways") || isMobileInterface)) {
mapRightBlock.style.removeProperty('height');
let mapMovingContainer = insideMap;
let mapMovingStyle = "";
if(isMobileInterface) {
insideMap.style.flexWrap = "wrap";
//insideMap.style.justifyContent = "normal";
addElement("div", insideMap, { style: "flex-basis: 100%; height: 0;"});
mapMovingStyle = "order: 4;";
} else {
mapMovingContainer = addElement("div", insideMap, { style: "order: 1;" });
mapMovingContainer.appendChild(jsmap);
insideMap.style.gap = "10px";
}
drawMapCore(mapMovingContainer, mapMovingStyle);
} else {
let mapHeight = 350;
let mapWidth = 500;
const mapActivatorDiv = addElement("div", document.body, { style: `position: fixed; width: 5px; height: ${ClientHeight() - 50}px; top: 50px; left: 0; background-color: #FFCCCB; opacity: 80%;` });
const mapContainerDiv = addElement("div", document.body, { style: `position: fixed; width: ${mapWidth}px; height: ${mapHeight}px; top: ${(ClientHeight() - mapHeight)/ 2}px; left: -${mapWidth}px; transition-duration: 0.3s; z-index: 10;` }, true);
const mapMoving = drawMapCore(mapContainerDiv, "box-shadow: 1px 1px 5px #333;"); //, `height: ${innerMapHeight}px`
let timer;
mapActivatorDiv.addEventListener("mouseover", function(event) { timer = setTimeout(function() { mapContainerDiv.style.top = `${ClientHeight() / 2 - 175}px`; mapContainerDiv.style.left = "0"; }, 100); }, false);
mapActivatorDiv.addEventListener("mouseout", function(event) { timer = setTimeout(function() { mapContainerDiv.style.left = `-${mapWidth + 10}px`; }, 300); }, false);
mapContainerDiv.addEventListener("mouseover", function(event) { clearTimeout(timer); }, false);
mapContainerDiv.addEventListener("mouseout", function(event) { timer = setTimeout(function() { mapContainerDiv.style.left = `-${mapWidth + 10}px`; }, 100); }, false);
}
}
function drawMapCore(parentNode, mainStyle) {
let mapMoving = document.getElementById("mapMoving");
if(mapMoving) {
mapMoving.parentNode.removeChild(mapMoving);
}
const workImageSize = 25;
mapMoving = addElement("div", parentNode, { id: "mapMoving", style: (mainStyle || "") + "border: 2mm ridge rgba(211, 220, 50, .6); background: linear-gradient(0.15turn, #3f87a6, #ebf8e1, #f69d3c 80%);" });
mapMoving.innerHTML = `
<div style="position: relative; text-align: center; font-size: 9px;">
<span style="font-size: 9px;">${ (MountInfo.EndDate ? `${MountInfo.ComplexRoute ? ComplexRouteName + ", " : ""}${MountInfo.IsPremiunAccount ? PremiunAccountName + ", " : ""}${MountUntilName}: ${(new Date(MountInfo.EndDate)).toLocaleString()}, ` : "") + `${TravelingTimeName}: ${MountInfo.TravelingTime} ${Second}` }</span>
${ MountInfo.AntithiefControlled ? `, <input id='toggleAntithiefCheckbox' type='checkbox' ${MountInfo.Antithief ? "checked" : ""}>${Antithief}` : "" }
<div id="checkMountButton" title="${CheckMountName}" style="display: inline-block;">
<img src="https://dcdn2.heroeswm.ru/i/pl_info/btn_reset.png" style="height: 12px; wigth: 12px;">
</div>
<br />
<input id='removeArtsBeforeMovingCheckbox' type='checkbox' ${gmGetBool("removeArtsBeforeMoving") ? "checked" : ""}>${UndressBeforeMove}
<input id='IgnoreComplexRouteCheckbox' type='checkbox' ${gmGetBool("IgnoreComplexRoute") ? "checked" : ""}>${NotUseComplexRoute}
<input id='HideMapCheckbox' type='checkbox' ${gmGetBool("HideMap") ? "checked" : ""}>${HideMapName}
<br />
<input id='HideHuntBlockCheckbox' type='checkbox' ${gmGetBool("HideHuntBlock") ? "checked" : ""}>${HideHuntName}
<input id='HideRightBlockCheckbox' type='checkbox' ${gmGetBool("HideRightBlock") ? "checked" : ""}>${HideRightBlockName}
<input id='popupAlwaysCheckbox' type='checkbox' ${gmGetBool("PopupAlways") ? "checked" : ""}>${PopupAlwaysName}
<input id='showLocationNumbersCheckbox' type='checkbox' ${gmGetBool("ShowLocationNumbers") ? "checked" : ""}>${ShowLocationNumbersName}
</div>
<div>
<table id="hwmMapMoveTable" style="">
</table>
</div>
<div style="position: relative; text-align: left; font-size: 9px;">
<div id="findNearestProductionBigButton" title="${FindNearestProductionName}" style="float: right;">
<img src="https://dcdn.heroeswm.ru/i/btns/job_fl_btn_production.png" style="scale: 1.5;">
</div>
${LoadName}<input id='loadMiningCheckbox' type='checkbox' ${gmGetBool("Load" + factoryTypes[0]) ? "checked" : ""}>${Mining}
<input id='loadMachiningCheckbox' type='checkbox' ${gmGetBool("Load" + factoryTypes[1]) ? "checked" : ""}>${Machining}
<input id='loadProductionCheckbox' type='checkbox' ${gmGetBool("Load" + factoryTypes[2]) ? "checked" : ""}>${Production}
<input id='HideBattlesDayWithBlockCheckbox' type='checkbox' ${gmGetBool("HideBattlesDayWithBlock") ? "checked" : ""}>${HideBattlesDayWithName}
<br/>
<span style="font-size: 9px;">${Legend}, PlayerSector: ${playerLocationNumber}${playerLocationNumber != GM_getValue("LastObservingLocationNumber") ? ", View: " + GM_getValue("LastObservingLocationNumber") : ""}</span>
<!--<span id="ClickMe">ClickMe</span>-->
<br/>
${isEn ? "Min salary: " : "Минимальная зарплата: "}<input id='minSalaryNumber' type='number' value='${GM_getValue("MinSalary", "")}' size="4" onfocus="this.select();">
<input id='thievesGuildNotificationsCheckbox' type='checkbox' ${gmGetBool("ThievesGuildNotifications") ? "checked" : ""}>${isEn ? "Thieves guild notifications" : "Оповещение о засаде"}
<br/>
<b>${JobFinding}:</b>
<div id="findNearestMiningButton" title="${FindNearestMiningName}" style="display: inline-block;">
<img src="https://dcdn.heroeswm.ru/i/btns/job_fl_btn_mining.png" style="width: ${workImageSize}px; height: ${workImageSize}px;">
</div>
<div id="findNearestManufactureButton" title="${FindNearestManufactureName}" style="display: inline-block;">
<img src="https://dcdn.heroeswm.ru/i/btns/job_fl_btn_manufacture.png" style="width: ${workImageSize}px; height: ${workImageSize}px;">
</div>
<div id="findNearestProductionButton" title="${FindNearestProductionName}" style="display: inline-block;">
<img src="https://dcdn.heroeswm.ru/i/btns/job_fl_btn_production.png" style="width: ${workImageSize}px; height: ${workImageSize}px;">
</div>
<input id='moveToWorkAfterFindCheckbox' type='checkbox' ${gmGetBool("MoveToWorkAfterFind") ? "checked" : ""}>${MoveToWorkAfterFindName}
<span id="workFindingMessageSpan"/>
</div>`;
mapMoving.querySelector("#removeArtsBeforeMovingCheckbox").addEventListener("click", function() { GM_setValue("removeArtsBeforeMoving", this.checked); }, false);
mapMoving.querySelector("#IgnoreComplexRouteCheckbox").addEventListener("click", function() { GM_setValue("IgnoreComplexRoute", this.checked); }, false);
mapMoving.querySelector("#HideMapCheckbox").addEventListener("click", function() { GM_setValue("HideMap", this.checked); window.location.reload(); }, false);
if(MountInfo.AntithiefControlled) {
mapMoving.querySelector("#toggleAntithiefCheckbox").addEventListener("click", function() { toggleAntithief(this); }, false);
}
mapMoving.querySelector("#HideHuntBlockCheckbox").addEventListener("click", function() { GM_setValue("HideHuntBlock", this.checked); toggleHuntBlock(); }, false);
mapMoving.querySelector("#HideRightBlockCheckbox").addEventListener("click", function() { GM_setValue("HideRightBlock", this.checked); toggleRightBlock(); }, false);
mapMoving.querySelector("#checkMountButton").addEventListener("click", function() { main(true); }, false);
mapMoving.querySelector("#loadMiningCheckbox").addEventListener("click", function() { GM_setValue("Load" + factoryTypes[0], this.checked); }, false);
mapMoving.querySelector("#loadMachiningCheckbox").addEventListener("click", function() { GM_setValue("Load" + factoryTypes[1], this.checked); }, false);
mapMoving.querySelector("#loadProductionCheckbox").addEventListener("click", function() { GM_setValue("Load" + factoryTypes[2], this.checked); }, false);
mapMoving.querySelector("#popupAlwaysCheckbox").addEventListener("click", function() { GM_setValue("PopupAlways", this.checked); window.location.reload(); }, false);
mapMoving.querySelector("#showLocationNumbersCheckbox").addEventListener("click", function() { GM_setValue("ShowLocationNumbers", this.checked); window.location.reload(); }, false);
mapMoving.querySelector("#HideBattlesDayWithBlockCheckbox").addEventListener("click", function() { GM_setValue("HideBattlesDayWithBlock", this.checked); toggleBattlesDayWith(); }, false);
//mapMoving.querySelector("#ClickMe").addEventListener("click", function() { getObjectLocations(); }, false);
mapMoving.querySelector("#moveToWorkAfterFindCheckbox").addEventListener("click", function() { GM_setValue("MoveToWorkAfterFind", this.checked); }, false);
mapMoving.querySelector("#minSalaryNumber").addEventListener("change", function() { GM_setValue("MinSalary", parseInt(this.value)); }, false);
mapMoving.querySelector("#findNearestMiningButton").addEventListener("click", function() { findNearestWork("mn"); }, false);
mapMoving.querySelector("#findNearestManufactureButton").addEventListener("click", function() { findNearestWork("fc"); }, false);
mapMoving.querySelector("#findNearestProductionButton").addEventListener("click", function() { findNearestWork("sh"); }, false);
mapMoving.querySelector("#findNearestProductionBigButton").addEventListener("click", function() { findNearestWork("sh"); }, false);
mapMoving.querySelector("#thievesGuildNotificationsCheckbox").addEventListener("click", function() { GM_setValue("ThievesGuildNotifications", this.checked); }, false);
const table = mapMoving.querySelector("#hwmMapMoveTable");
const now = new Date();
for(let y = minY; y <= maxY; y++) {
const tableRow = addElement("tr", table);
for(let x = minX; x <= maxX; x++) {
let cellStyle = "";
let locationNumber = getLocationNumberByCoordinate(x, y);
const tableCell = addElement("td", tableRow, { id: `transporterLocation${locationNumber}` });
if(locationNumber) {
const loc = locations[locationNumber];
tableCell.innerHTML = `${loc[locationNamesLocalizedColumn].replace(" ", "<br>")} ${ gmGetBool("ShowLocationNumbers") ? `(${locationNumber})` : "" }`;
tableCell.style = `cursor: pointer; font-size: 10px; font-weight: bold; text-align: center; border: 1px solid #000; padding: 3px; color: ${locationNumber == playerLocationNumber ? "red" : "black"};`;
if(locationNumber < 100) {
let routeTime = "";
const routeSettings = routes[playerLocationNumber][locationNumber];
if(routeSettings) {
const routeLength = routeSettings[1];
routeTime = `\n${TravelingTimeName} ${routeLength * MountInfo.TravelingTime} ${Second}`;
}
tableCell.title = `${GoTo} ${loc[locationNamesLocalizedColumn]}${routeTime}`;
tableCell.addEventListener("mouseenter", function() { this.style.border = "1px solid #fff"; }, false);
tableCell.addEventListener("mouseleave", function() { this.style.border = "1px solid #000"; }, false);
tableCell.addEventListener("click", function(e) { if(e.altKey) { getURL(`/map.php?cx=${x}&cy=${y}`); } else if(e.ctrlKey) { setThiefAmbush(locationNumber); } else { tryMoving(locationNumber); } }, false);
tableCell.addEventListener("auxclick", function(e) { e.stopPropagation();/*if(e.which === 2) { e.preventDefault(); }*/ if(e.button == 1) { setThiefAmbush(locationNumber); } }, false); // console.log(`e.which: ${e.which}, e.button: ${e.button}`);
const sectorViewReference = addElement("a", tableCell, { href: `/map.php?cx=${x}&cy=${y}`, style: "display: block; float: left;", title: `${isEn ? "View" : "Просмотр"}` });
addElement("img", sectorViewReference, { style: "border: 0;", src: "data:image/gif,GIF89a%10%00%10%00%D5%00%00B%40B%15%15%18((-PPUzz%7FHHJ%5D%5D_--.zz%7BWWX23%3BEHS%80%88%A2rx%8C%DA%DD%E7bj%80sx%87%88%8C%97%7D%85%98HO_%7D%85%97%88%8C%95psz%DC%DD%DF%D4%D5%D7x%7F%8C%2B-0%C2%DF%FF%DF%F4%FFMOPmop%EF%F1%F2%E7%F9%FF%EA%FD%FF%E7%FF%FF%13%15%15%E9%FF%FF%18%1A%1A%FA%FF%FFmoo%FC%FF%FF%FD%FF%FFZ%5B%5B%5D%5D%5B%40%3F%3F%FF%FF%FF%16%16%16%10%10%10%05%05%05%00%00%00%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%002%00%2C%00%00%00%00%10%00%10%00%00%06%5C%40%99pH%2C%12%13%01%8D%80e%24%02ZP%A8%A2)k%C8%A2%D1As%01Ma'%CDF%D4%14%7D4!-%94%A8%95%BAJ%9A%07P%8B%E4mm%2C%D4H(%CA%A9%AC%A82%05%19%0C%14%041*%17%80E0%1D%18%8AD%2F%06%89%8FB%25'%1F%94B.%08-%992%23%1E%9ECA%00%3B" });
sectorViewReference.addEventListener("click", function(e) { e.stopPropagation(); })
if([2, 6, 16, 21].includes(parseInt(locationNumber))) {
getMoveToMapObjectReference('/mercenary_guild.php', tableCell, locationNumber, "https://dcdn.heroeswm.ru/i/btns/job_fl_btn_mercenary.png", "display: block; float: right; width: 16px; height: 16px;");
}
const guestInfo = getGuestInfo(locationNumber);
const guestInfoKeys = Object.keys(guestInfo);
if(guestInfoKeys.length > 0) {
const guestInfoTitles = guestInfoKeys.map(x => `${guestInfo[x].HostInfo} до ${(new Date(guestInfo[x].ExpireDate)).toLocaleString()}`);
const guestReference = addElement("a", tableCell, { href: `/house_info.php?id=${guestInfoKeys[0]}`, style: "display: block; float: left;", title: guestInfoTitles.join("\n") });
guestReference.addEventListener("click", function(e) { e.stopPropagation(); })
addElement("img", guestReference, { style: "border: 0;", src: "https://dcdn.heroeswm.ru/i/btns/job_fl_btn_houses.png", style: "width: 16px; height: 16px;" });
}
} else {
tableCell.style.color = loc[5].Color;
tableCell.addEventListener("click", function() { getURL(loc[5].Url); }, false);
if(x == 50 && y == 54) {
addElement("br", tableCell);
AmbushMoratoriumPanel = addElement("span", tableCell, { id: "AmbushMoratoriumPanel" });
}
if(x == 51 && y == 54) {
addElement("br", tableCell);
addElement("span", tableCell, { id: "SmithMoratoriumPanel" });
}
}
}
}
}
processMercenaryTaskLocation();
return mapMoving;
}
function drawAmbushMarks() {
for(const locationNumber of Object.keys(locations).filter(x => parseInt(x) < 100)) {
const routeSettings = routes[playerLocationNumber][locationNumber];
const tableCell = document.getElementById(`transporterLocation${locationNumber}`);
const thiefwarrioranip33 = tableCell.querySelector("img[src*='thiefwarrioranip33']");
if(routeSettings && routeSettings[1] < 2 && !GM_getValue("AmbushSuspendExpireDate") && !GM_getValue("AmbushState") && isFullHealth()) {
if(!thiefwarrioranip33) {
const ambushImage = addElement("img", tableCell, { src: "https://dcdn.heroeswm.ru/i/portraits/thiefwarrioranip33.png", style: "width: 16px; height: 16px;", title: `${isEn ? "Ambush" : "Засада"}` });
ambushImage.addEventListener("click", function(e) { e.stopPropagation(); setThiefAmbush(locationNumber); });
}
} else {
if(thiefwarrioranip33) {
thiefwarrioranip33.remove();
}
}
}
}
async function processMercenaryTaskLocation() {
const mercenaryTaskLocation = await getMercenaryTaskLocation();
if(mercenaryTaskLocation) {
addElement("img", document.getElementById(`transporterLocation${mercenaryTaskLocation}`), { src: "https://dcdn2.heroeswm.ru/i/cssmap/map_sectors_naim.png", style: "width: 16px; height: 16px;", title: `${isEn ? "Mercenary guild task" : "Задание гильдии наемников"}` });
}
}
function getMercenaryTaskLocation() {
return new Promise((resolve, reject) => {
if(location.pathname == '/map.php') {
setTimeout(function() {
if(windowObject.naim_type == 'fight') {
GM_setValue("MercenaryTaskLocation", windowObject.naim_sector);
} else {
GM_deleteValue("MercenaryTaskLocation");
}
resolve(GM_getValue("MercenaryTaskLocation"));
}, 300);
} else {
resolve(GM_getValue("MercenaryTaskLocation"));
}
});
}
async function findNearestWork(factoryType) {
const movingEnabled = await varifyMovingEnabled();
let notEmptyLocationsSortedByDistance = [playerLocationNumber];
if(movingEnabled) {
notEmptyLocationsSortedByDistance = getLocationsSortedByDistance();
}
notEmptyLocationsSortedByDistance = notEmptyLocationsSortedByDistance.filter(x => !GM_getValue(`LastDetectedEmptyFactoriesDate_${factoryType}${x}`));
const workFindingMessageSpan = document.querySelector("span#workFindingMessageSpan");
for(const locationNumber of notEmptyLocationsSortedByDistance) {
workFindingMessageSpan.innerText = `Viewing ${locationNumber}...`;
var findedWorkObject = await findWorkInLocation(factoryType, locationNumber);
if(findedWorkObject) {
if(gmGetBool("MoveToWorkAfterFind")) {
tryMoving(locationNumber, findedWorkObject.href);
} else {
getURL(findedWorkObject.href);
}
workFindingMessageSpan.innerText = "";
break;
}
}
if(!findedWorkObject) {
workFindingMessageSpan.innerText = "Vacancy not found";
}
}
async function findWorkInLocation(factoryType, locationNumber) {
const x = locations[locationNumber][0];
const y = locations[locationNumber][1];
const doc = await getRequest(`map.php?cx=${x}&cy=${y}&st=${factoryType}`);
const objectRefs = doc.querySelectorAll("a[href^='object-info.php?id=']");
//console.log(`objectRefs: ${objectRefs.length}`);
for(const objectRef of objectRefs) {
//console.log(`objectRef.innerText: ${objectRef.innerText}, ${objectRef.innerText.includes("\u00bb\u00bb\u00bb")}`);
if(objectRef.innerText.includes("\u00bb\u00bb\u00bb") && !objectRef.querySelector("font")) {
const salary = parseInt(objectRef.parentNode.previousElementSibling.querySelector("b").innerHTML);
const minSalary = parseInt(GM_getValue("MinSalary", 0));
//console.log(`minSalary: ${minSalary}, salary: ${salary}, objectRef: ${objectRef}`);
if(minSalary == 0 || salary >= minSalary) {
return objectRef;
}
}
}
}
function getRequest(url) {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: "text/html; charset=windows-1251",
onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); },
onerror: function(error) { reject(error); }
});
});
}
function postRequest(url, data) {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({ method: "POST", url: url, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: data,
onload: function(response) { resolve(response); },
onerror: function(error) { reject(error); }
});
});
}
function getLocationsSortedByDistance() {
if(playerLocationNumber in routes && routes[playerLocationNumber]) {
const playerLocationRoutes = routes[playerLocationNumber];
const availableLocationsDistance = { };
availableLocationsDistance[playerLocationNumber] = 0;
for(let i = 0; i < playerLocationRoutes.length; i++) {
if(playerLocationRoutes[i]) {
availableLocationsDistance[i] = playerLocationRoutes[i][1];
}
}
const locationsSortedByDistance = Object.keys(availableLocationsDistance).sort(function(a,b) { return availableLocationsDistance[a] - availableLocationsDistance[b]; });
//console.log(locationsSortedByDistance);
return locationsSortedByDistance;
}
}
function getLocationNumberByCoordinate(x, y) {
for(let locationNumber in locations) {
if(locations[locationNumber][0] == x && locations[locationNumber][1] == y) {
return locationNumber;
}
}
}
function processMoving() {
let targetLocationNumber = parseInt(GM_getValue("TargetLocationNumber"));
//console.log(`playerLocationNumber: ${playerLocationNumber}, TargetLocationNumber: ${GM_getValue("TargetLocationNumber")}, LastMoveTryFrom: ${GM_getValue("LastMoveTryFrom")}`);
if(GM_getValue("LastMoveTryFrom") == playerLocationNumber && targetLocationNumber != playerLocationNumber) {
stopMoving(); // Мы не смогли уйти из локации, поэтому останавливаем движение; и мы не движемся на объект в этой же локации
return;
}
let arrived = false;
if(targetLocationNumber) {
if(targetLocationNumber == playerLocationNumber) {
GM_deleteValue("TargetLocationNumber");
GM_deleteValue("LastMoveTryFrom");
GM_deleteValue("LastMoveTryTo");
arrived = true;
} else {
goToNextRoutePoint();
}
}
//console.log([playerLocationNumber, targetLocationNumber, arrived, GM_getValue("EnterObjectOnArrived")]);
// Перемещение к объекту после прибытия
if(arrived) {
let enterObjectOnArrived = GM_getValue("EnterObjectOnArrived");
if(enterObjectOnArrived) {
GM_deleteValue("EnterObjectOnArrived");
getURL(enterObjectOnArrived);
//setTimeout(function() { window.location = enterObjectOnArrived; }, 300);
}
}
}
function tryMoving(targetLocationNumber, enterObjectOnArrived) {
if(!MountInfo.ComplexRoute) {
alert(isEn ? "Script working only if mount with complex route enabled" : "Скрипт работает, если есть транспорт со сложным маршрутом");
return;
}
if(targetLocationNumber == playerLocationNumber && !enterObjectOnArrived) {
alert(YouAreHere);
return;
}
if(targetLocationNumber == 25) {
alert(How);
return;
}
checkMovingEnabledAndGo(targetLocationNumber, enterObjectOnArrived);
}
async function varifyMovingEnabled() {
let movingEnabled = true;
if(/map.php/.test(location.href)) {
const mapNavigator = document.querySelector("#map_navigator");
movingEnabled = (Array.from(mapNavigator.querySelectorAll("div[id*='dbut']")).find(x => x.style.display == "block")) ? true : false;
} else {
const doc = await getRequest("/inventory.php");
const invNote = doc.querySelector("div.inv_note_inside");
movingEnabled = !(invNote && invNote.innerHTML.includes(YouAreInAChallenge));
}
return movingEnabled;
}
async function checkMovingEnabledAndGo(targetLocationNumber, enterObjectOnArrived) {
let movingEnabled = true;
if(targetLocationNumber != playerLocationNumber) {
movingEnabled = await varifyMovingEnabled();
}
if(movingEnabled) {
undressAndGo(targetLocationNumber, enterObjectOnArrived);
} else {
alert(YouAreInAChallenge);
}
}
async function undressAndGo(targetLocationNumber, enterObjectOnArrived) {
if(gmGetBool("removeArtsBeforeMoving") && targetLocationNumber != playerLocationNumber) {
await getRequest("/inventory.php?all_off=100");
}
startMoving(targetLocationNumber, enterObjectOnArrived);
}
function startMoving(targetLocationNumber, enterObjectOnArrived) {
GM_setValue("TargetLocationNumber", targetLocationNumber);
if(enterObjectOnArrived) {
GM_setValue("EnterObjectOnArrived", enterObjectOnArrived);
}
goToNextRoutePoint();
}
function goToNextRoutePoint() {
const targetLocationNumber = parseInt(GM_getValue("TargetLocationNumber"));
let nextRoutePoint;
if(MountInfo.ComplexRoute && !gmGetBool("IgnoreComplexRoute")) {
nextRoutePoint = targetLocationNumber;
} else if(playerLocationNumber in routes && targetLocationNumber in routes[playerLocationNumber] && routes[playerLocationNumber][targetLocationNumber]) {
const route = routes[playerLocationNumber][targetLocationNumber][0];
nextRoutePoint = route.split('-')[1];
}
if(nextRoutePoint) {
GM_setValue("LastMoveTryFrom", playerLocationNumber);
GM_setValue("LastMoveTryTo", nextRoutePoint);
//getURL(`/move_sector.php?id=${nextRoutePoint}&rand=${Math.random()}`);
if(playerLocationNumber != nextRoutePoint) {
getURL(`/move_sector.php?id=${nextRoutePoint}&rand=${Math.random()}`);
} else if(GM_getValue("EnterObjectOnArrived")) {
processMoving();
}
}
}
function stopMoving() {
GM_deleteValue("TargetLocationNumber");
GM_deleteValue("EnterObjectOnArrived");
GM_deleteValue("LastMoveTryFrom");
GM_deleteValue("LastMoveTryTo");
}
function getPlayerLocationNumber() {
if(location.pathname == '/map.php' && location.search == '') {
// Если мы на карте без параметров, т.е. на локации, где сами находимся. Если мы не в пути, тогда видим предприятия. Мы можем обновить текущее положение игрока.
const minesRef = document.querySelector("a[href*='map.php?cx='][href*='&cy='][href*='&st=mn']"); // Берем из ссылки на заголовке шахт данной локации
if(minesRef) {
const locationNumber = getLocationNumberFromMapUrlByXy(minesRef.href);
if(locationNumber) {
GM_setValue("PlayerLocationNumber", locationNumber);
return locationNumber;
}
}
}
return parseInt(GM_getValue("PlayerLocationNumber")); // Иначе, возьмем из кеша. Там будет пусто только при первом запуске скрипта, когда мы не просматриваем карту.
}
function getLocationNumberFromMapUrlByXy(href) {
const x = getUrlParamValue(href, "cx");
const y = getUrlParamValue(href, "cy");
for(let locationNumber in locations) {
if(x == locations[locationNumber][0] && y == locations[locationNumber][1]) {
return locationNumber;
}
}
}
function getMoveToObjectReference(objectUrl, parentNode) {
const objectId = getUrlParamValue(objectUrl, "id");
const objectLocationNumber = objectLocations[objectId];
//console.log(`objectId: ${objectId}, objectLocationNumber: ${objectLocationNumber}, parentNode: ${parentNode}`);
return getMoveToMapObjectReference(objectUrl, parentNode, objectLocationNumber);
}
function getMoveToMapObjectReference(objectUrl, parentNode, objectLocationNumber, image, imageStyle) {
//console.log(`objectLocationNumber: ${objectLocationNumber}, playerLocationNumber: ${playerLocationNumber}, image: ${image}`);
if(objectLocationNumber != playerLocationNumber || image) {
let routeTime = "";
const routeSettings = routes[playerLocationNumber][objectLocationNumber];
if(routeSettings) {
const routeLength = routeSettings[1];
routeTime = `\n${TravelingTimeName} ${routeLength * MountInfo.TravelingTime} ${Second}`;
}
const moveHereReference = createElement('span', { style: "cursor: pointer;", innerHTML: `<img src="${image || getHorseImageData()}" alt="${MoveHere}" title="${MoveHere + routeTime}" align="absmiddle" height="15" width="15" style="max-height: 12px; max-width: 12px;${imageStyle || ""}"> ` });
moveHereReference.onclick = function(e) { tryMoving(objectLocationNumber, objectUrl); e.stopPropagation(); };
//console.log(`objectUrl: ${objectUrl}, moveHereReference: ${moveHereReference}, routeTime: ${routeTime}, parentNode: ${parentNode}, parentNode.nextSibling: ${parentNode.nextSibling}, parentNode.nextElementSibling: ${parentNode.nextElementSibling}, parentNode.parentNode: ${parentNode.parentNode}, parentNode.previousSibling: ${parentNode.previousSibling}`);
if(image) {
parentNode.appendChild(moveHereReference);
} else {
const insertResult = parentNode.parentNode.insertBefore(moveHereReference, parentNode.nextSibling);
//console.log(`insertResult: ${insertResult}, parentNode: ${parentNode}`);
}
return moveHereReference;
}
}
async function setThiefAmbush(locationNumber) {
if(checkSectorForAmbush(locationNumber)) {
if(GM_getValue("AmbushSuspendExpireDate")) {
alert(`${ItIsTooEarly}`);
} else {
await postRequest("/thief_ambush.php", `id=${locationNumber}&with_who=0`);
getURL("/map.php");
}
} else {
alert(AmbushMaySettedOnAdjacentSector);
}
}
function checkSectorForAmbush(locationNumber) {
if(playerLocationNumber in routes && locationNumber in routes[playerLocationNumber] && routes[playerLocationNumber][locationNumber]) {
const route = routes[playerLocationNumber][locationNumber][0];
const nextRoutePoint = route.split('-')[1];
return nextRoutePoint == locationNumber;
}
return false;
}
function resetMountInfo() {
GM_deleteValue("TravelingTime");
GM_deleteValue("ComplexRoute");
GM_deleteValue("EndDate");
GM_deleteValue("Antithief");
GM_deleteValue("AntithiefControlled");
GM_deleteValue("ToggleAntithiefKey");
GM_deleteValue("IsPremiunAccount");
}
async function getMountInfo(force) {
let endDate = GM_getValue("EndDate") ? parseInt(GM_getValue("EndDate")) : undefined;
if(!endDate || endDate <= Date.now() || force) {
if(endDate <= Date.now()) {
resetMountInfo();
}
const doc = await getRequest("/shop.php?cat=transport");
const mounts = doc.querySelectorAll('div.s_art_r');
//console.log(["mounts", mounts.length]);
const mountsInfoGeted = mounts.length > 0; // Если 0, то мы в пути и на страницу магазина нас не пускают. Поэтому используем старые данные о транспорте
if(mountsInfoGeted) {
let isPremiunAccount = false;
for(const mount of mounts) {
if(mount.innerHTML.includes(YourPremiumMountUntil) || mount.innerHTML.includes(YourMountUntil)) {
var mountRow = mount;
isPremiunAccount = mount.innerHTML.includes(YourPremiumMountUntil);
break;
}
}
if(mountRow) {
resetMountInfo();
GM_setValue("IsPremiunAccount", isPremiunAccount);
const mountExpireTimeDiv = mountRow.querySelector('div.s_art_note_transport') || mountRow.querySelector('div.s_art_name.s_transport_name');
const dateString = (mountExpireTimeDiv.querySelector('span') || mountExpireTimeDiv).innerText.split(Until)[1];
GM_setValue("EndDate", parseDate(dateString).getTime());
const transportOptions = mountRow.querySelectorAll("div.s_art_prop_transport");
for(let transportOption of transportOptions) {
if(transportOption.innerHTML.includes(TravelingTimeName)) {
const timeValue = /(\d{1,2})/.exec(transportOption.innerHTML);
GM_setValue("TravelingTime", timeValue[1]);
}
if(transportOption.innerHTML.includes(ComplexRouteName)) {
GM_setValue("ComplexRoute", transportOption.querySelector("img.s_art_prop_transport_amount_image[src*='check_yes']") ? true : false);
}
if(transportOption.innerHTML.includes(Antithief)) {
let antithiefControlImage = transportOption.querySelector("img.s_art_prop_transport_amount_image[src*='check_on']");
antithiefControlImage = antithiefControlImage || transportOption.querySelector("img.s_art_prop_transport_amount_image[src*='check_off']");
GM_setValue("Antithief", antithiefControlImage ? true : false);
GM_setValue("AntithiefControlled", antithiefControlImage ? true : false);
if(antithiefControlImage) {
GM_setValue("ToggleAntithiefKey", getUrlParamValue(antithiefControlImage.parentNode.href, "t_on") || getUrlParamValue(antithiefControlImage.parentNode.href, "t_off"));
}
}
}
}
}
}
const mountInfo = {
TravelingTime: parseInt(GM_getValue("TravelingTime", DefaultTravelingTime)),
ComplexRoute: gmGetBool("ComplexRoute"),
EndDate: GM_getValue("EndDate") ? parseInt(GM_getValue("EndDate")) : undefined,
Antithief: gmGetBool("Antithief"),
AntithiefControlled: gmGetBool("AntithiefControlled"),
IsPremiunAccount: gmGetBool("IsPremiunAccount")
};
//console.log(mountInfo);
return mountInfo;
}
function processHouseInfo() {
if(location.pathname == '/house_info.php') {
const houseId = getUrlParamValue(location.href, "id");
const hostDiv = document.querySelector("div#tt");
const container = getParent(hostDiv, "table");
const loc = container.querySelector("a[href^='map.php?cx=']");
const locationNumber = getLocationNumberFromMapUrlByXy(loc.href);
const ownerName = container.querySelector("a[href^='pl_info.php?id=']").querySelector("b").innerText;
const hostName = hostDiv.querySelector("b").innerText;
let maxExpireDate;
const guestRoomDivs = container.querySelectorAll("div[id^='gr']");
for(const guestRoomDiv of guestRoomDivs) {
const playerReference = guestRoomDiv.querySelector(`a[href='pl_info.php?id=${PlayerId}']`)
if(playerReference && playerReference.nextSibling) {
const re = /(\d{2}:\d{2} \d{2}-\d{2})/.exec(playerReference.nextSibling.nodeValue);
if(re) {
const expireDate = parseDate(re[1], true);
if(!maxExpireDate || maxExpireDate < expireDate) {
maxExpireDate = expireDate;
}
}
}
}
const guestInfo = getGuestInfo(locationNumber);
if(maxExpireDate) {
guestInfo[houseId] = { HostInfo: `${ownerName} (${hostName})`, ExpireDate: maxExpireDate.toJSON() };
}
GM_setValue(`GuestInfo${locationNumber}`, JSON.stringify(guestInfo));
//console.log(guestInfo);
}
}
function getGuestInfo(locationNumber) {
if(GM_getValue(`GuestInfo${locationNumber}`)) {
const now = new Date();
const guestInfo = JSON.parse(GM_getValue(`GuestInfo${locationNumber}`));
for(const guestInfoKey of Object.keys(guestInfo)) {
if(new Date(guestInfo[guestInfoKey].ExpireDate) < now) {
var repackNeeded = true;
delete guestInfo[guestInfoKey];
}
}
const newKeys = Object.keys(guestInfo);
if(repackNeeded) {
if(newKeys.length == 0) {
GM_deleteValue(`GuestInfo${locationNumber}`);
} else {
GM_setValue(`GuestInfo${locationNumber}`, JSON.stringify(guestInfo));
}
}
if(newKeys.length > 0) {
return guestInfo;
}
}
return {};
}
function parseDate(dateString, isFuture = false) {
//console.log(dateString)
if(!dateString) {
return;
}
const dateStrings = dateString.split(" ");
let hours = 0;
let minutes = 0;
let seconds = 0;
const timePart = dateStrings.find(x => x.includes(":"));
if(timePart) {
const time = timePart.split(":");
hours = parseInt(time[0]);
minutes = parseInt(time[1]);
if(time.length > 2) {
seconds = parseInt(time[2]);
}
}
const now = new Date();
let year = now.getFullYear();
let month = now.getMonth();
let day = now.getDate();
const datePart = dateStrings.find(x => x.includes("-"));
if(datePart) {
const date = datePart.split("-");
month = parseInt(date[isEn ? (date.length == 3 ? 1 : 0) : 1]) - 1;
day = parseInt(date[isEn ? (date.length == 3 ? 2 : 1) : 0]);
if(date.length == 3) {
year = isEn ? parseInt(date[0]) : parseInt(date[2]);
if(year < 1000) {
year += Math.floor((new Date()).getFullYear() / 1000) * 1000;
}
} else {
if(isFuture && month == 0 && now.getMonth() == 11) {
year += 1;
}
}
}
//console.log(`year: ${year}, month: ${month}, day: ${day}, time[0]: ${time[0]}, time[1]: ${time[1]}, ${new Date(year, month, day, parseInt(time[0]), parseInt(time[1]))}`);
return new Date(year, month, day, hours, minutes, seconds);
}
function addElement(type, parent, data, insertFirst = false) {
let el = createElement(type, data);
if(parent) {
if(insertFirst) {
parent.insertBefore(el, parent.firstChild);
} else {
parent.appendChild(el);
}
}
return el;
}
function createElement(type, data) {
let el = document.createElement(type);
if(data) {
for(let key in data) {
if(key == "innerText" || key == "innerHTML") {
el[key] = data[key];
} else {
el.setAttribute(key, data[key]);
}
}
}
return el;
}
function getHorseImageData() { return "data:image/png;base64,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"; }
function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
function getURL(url) { window.location.href = url; }
function gmGetBool(valueName) {
const value = GM_getValue(valueName);
if(value) {
if(typeof(value) == "string") {
return value == "true";
}
if(typeof(value) == "boolean") {
return value;
}
}
return false;
}
async function loadFactories() {
let selectedJobDiv = document.querySelector("div.job_fl_btn.show_hint.job_fl_btn_selected");
if(!selectedJobDiv) {
return; // Мы в пути
}
let currentFactoryType = getUrlParamValue(selectedJobDiv.parentNode.href, "st");
const viewingLocationNumber = getLocationNumberFromMapUrlByXy(selectedJobDiv.parentNode.href);
let indexOfCurrentFactoryType = factoryTypes.indexOf(currentFactoryType);
if(indexOfCurrentFactoryType == -1) {
return;
}
const mapRightBlock = document.getElementById("map_right_block");
//const mapRightBlockInside = document.getElementById("map_right_block_inside");
//console.log(`${mapRightBlock.id}, offsetHeight: ${mapRightBlock.offsetHeight}, height: ${mapRightBlock.style.height}`);
//console.log(`${mapRightBlockInside.id}, offsetHeight: ${mapRightBlockInside.offsetHeight}, height: ${mapRightBlockInside.style.height}`);
let mapRightBlockHeight = mapRightBlock.offsetHeight;
let mainFactoriesTable = mapRightBlock.querySelector("table.wb");
if(!mainFactoriesTable) {
return;
}
let mapRef = document.querySelector("a[href^='map.php?cx=']");
let x = getUrlParamValue(mapRef.href, "cx");
let y = getUrlParamValue(mapRef.href, "cy");
let factoriesTableContainer = mainFactoriesTable.parentNode;
const factoryTables = { };
factoryTables[currentFactoryType] = mainFactoriesTable;
for(const factoryType of factoryTypes) {
if(factoryType != currentFactoryType && gmGetBool("Load" + factoryType) && GM_getValue(`LastDetectedEmptyFactoriesDate_${factoryType}${viewingLocationNumber}`, 0) + 1000 * 60 * 60 * 24 * 30 < Date.now()) {
const doc = await getRequest(`map.php?cx=${x}&cy=${y}&st=${factoryType}`);
const docMapRightBlock = doc.getElementById("map_right_block");
factoryTables[factoryType] = docMapRightBlock.querySelector("table.wb");
}
}
for(let i = 0; i < factoryTypes.length; i++) {
let tableElement = factoryTables[factoryTypes[i]];
if(!tableElement) {
continue;
}
const isTableEmpty = tableElement.rows.length <= 2 && (tableElement.rows.length < 2 || tableElement.rows[1].cells.length == 0);
if(isTableEmpty) {
GM_setValue(`LastDetectedEmptyFactoriesDate_${factoryTypes[i]}${viewingLocationNumber}`, Date.now());
} else if(GM_getValue(`LastDetectedEmptyFactoriesDate_${factoryTypes[i]}${viewingLocationNumber}`)) {
GM_deleteValue(`LastDetectedEmptyFactoriesDate_${factoryTypes[i]}${viewingLocationNumber}`);
}
if(!isTableEmpty) {
if(indexOfCurrentFactoryType < i) {
factoriesTableContainer.appendChild(tableElement)
mapRightBlockHeight += tableElement.offsetHeight;
}
if(indexOfCurrentFactoryType > i) {
factoriesTableContainer.insertBefore(tableElement, mainFactoriesTable);
mapRightBlockHeight += tableElement.offsetHeight;
}
} else if(indexOfCurrentFactoryType == i) {
mapRightBlockHeight -= mainFactoriesTable.offsetHeight;
factoriesTableContainer.removeChild(mainFactoriesTable); // Если текущий список предприятий - пустой, то уберем его
}
}
mapRightBlock.style.height = `${mapRightBlockHeight}px`;
}
function ClientHeight() { return document.compatMode == 'CSS1Compat' && document.documentElement ? document.documentElement.clientHeight : document.body.clientHeight; }
function ShowBigData(data) { addElement("TEXTAREA", document.body, { innerHTML: data }); }
function getParent(element, parentType, number = 1) {
let result = element;
let foundNumber = 0;
while(result = result.parentNode) {
if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
foundNumber++;
if(foundNumber == number) {
return result;
}
}
}
}
function observe(target, handler, config = { childList: true, subtree: true }) {
const ob = new MutationObserver(async function(mut, observer) {
//console.log(`Mutation start`);
observer.disconnect();
if(handler.constructor.name === 'AsyncFunction') {
await handler();
} else {
handler();
}
observer.observe(target, config);
});
ob.observe(target, config);
}
async function initUserName() {
if(!GM_getValue("TransporterUserName")) {
const doc = await getRequest(`/pl_info.php?id=${PlayerId}`);
GM_setValue("TransporterUserName", doc.querySelector("h1").innerText);
}
}