// ==UserScript==
// @name hwmTimers
// @namespace Tamozhnya1
// @author Tamozhnya1
// @description Таймеры гильдии рабочих, воров, наёмников, рейнджеров, охотников, кузнецов, восстановления здоровья и маны
// @version 7.3
// @include https://www.heroeswm.ru/*
// @include *.lordswm.com/*
// @exclude */rightcol.php*
// @exclude */ch_box.php*
// @exclude */chat*
// @exclude */ticker.html*
// @exclude */frames*
// @exclude */brd.php*
// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_setValue
// @grant GM.xmlHttpRequest
// @grant GM.notification
// @license MIT
// ==/UserScript==
if(!this.GM_getValue || (this.GM_getValue.toString && this.GM_getValue.toString().indexOf("not supported") > -1)) {
this.GM_getValue = function(key, def) { return localStorage[key] || def; };
this.GM_setValue = function(key, value) { localStorage[key] = value; };
this.GM_deleteValue = function(key) { return delete localStorage[key]; };
}
const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
if(!playerIdMatch) {
return;
}
const PlayerId = playerIdMatch[1];
const isEn = document.documentElement.lang == "en";
const isHeartOnPage = document.querySelector("canvas#heart") || document.querySelector("div#heart_js_mobile") ? true : false;
const isNewInterface = document.querySelector("div#hwm_header") ? true : false;
const mooving = location.pathname == '/map.php' && !document.getElementById("map_right_block");
const windowObject = window.wrappedJSObject || unsafeWindow;
const timerNames = ["health", "work", "smith", "merc", "hunt", "thief", "mana"];
const disable_alarm_delay = 30; //секунд задержки после предыдущего сигнала
let healthAudio;
let workAudio;
let smithAudio;
let warlikeAudio;
let defaultAudio;
let texts;
main();
function main() {
initUserName();
verifyOptionKeys();
texts = setTexts();
if(location.pathname == '/war.php') {
inBattle(); // в бою
return;
}
if(!isHeartOnPage) {
return;
}
const [army_percent] = healthTimer();
// Обработка результатов битвы, если только что из неё вышли
const bselect_link = document.querySelector("a[href='bselect.php']") || document.querySelector("a[href='plstats.php']");
if(bselect_link && bselect_link.parentNode.innerHTML.indexOf("#ff0000") === -1) { // Сидим на форуме, меню - красное
checkBattleResults(army_percent < 100 ? "fail" : "win");
}
initAudios();
requestServerTime();
checkWork();
checkPremiumAccount();
checkHuntLicense();
checkWorkaholic();
checkMercenary();
if(location.pathname == "/leader_guild.php") {
Array.from(document.querySelectorAll("form[name^='f'] input[type='submit']")).forEach(x => x.addEventListener("click", function () { updateOption("battleType", "leader"); }));
}
checkRangerGuild();
checkModWorkebench();
if(location.pathname == '/map.php') {
checkThiefAmbush();
checkRangerAmbush();
checkMapHunter();
}
createTimersPanel();
timersPanelDataBind();
tick();
}
function verifyOptionKeys() {
const defaultOptions = {
"healthNotification": "no",
"workNotification": "yes",
"enrollNumber": "0",
"smithNotification": "yes",
"mercNotification": "yes",
"huntNotification": "yes",
"thiefNotification": "yes",
"customTimeRate": "1",
"abuBlessRate": "1",
"abuBlessExpirationTime": "0",
"abuBlessInfo": "",
"huntLicenseRate": "1",
"huntLicenseExpirationTime": "0",
"huntLicenseText": "",
"thiefOrRanger": "0",
"joinRangerBattle": "0",
"showWorkaholicAlarmLastTwoEnrolls": "1",
"disableWorkaholicAlarm": "0",
"isShowWorkTimer": "1",
"isShowSmithTimer": "1",
"isShowMercTimer": "1",
"isShowHuntTimer": "1",
"isShowThiefTimer": "1",
"workSound": "",
"warlikeSound": "",
"smithSound": "",
"healthSound": "",
"battleType": ""
};
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`, JSON.stringify(defaultOptions)));
Object.keys(defaultOptions).forEach(x => { if(!options.hasOwnProperty(x)) { options[x] = defaultOptions[x]; } });
Object.keys(options).forEach(x => { if(!defaultOptions.hasOwnProperty(x)) { delete options[x]; } });
GM_setValue(`hwmTimersOptions${PlayerId}`, JSON.stringify(options));
//console.log(options);
}
function inBattle() {
if(/warlog\|0/.exec(document.querySelector("html").innerHTML)) {
//flash & html: warlog|0| -> бой происходит сейчас, warlog|1| -> запись боя, |player|7146446| -> id текущего игрока
const playerIdExec = /\|player\|(\d+)\|/.exec(document.querySelector("html").innerHTML);
if(playerIdExec && playerIdExec[1] == PlayerId) {
GM_setValue(`HoldBattle${PlayerId}`, true);
const finalResultDiv = document.getElementById("finalresult_text");
if(finalResultDiv.innerHTML.length <= 10) {
observe(finalResultDiv, parseBattleResultPanel);
}
}
}
}
function parseBattleResultPanel() {
const finalResultDiv = document.getElementById("finalresult_text");
if(finalResultDiv.innerHTML.length > 10) {
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}, UserName: ${GM_getValue("UserName")}`);
if(bold.parentNode.nextSibling.nextSibling.firstChild.innerText == GM_getValue("UserName")) {
result = "win";
}
break;
}
}
checkBattleResults(result);
}
}
function checkBattleResults(result) {
if(gmGetBool(`HoldBattle${PlayerId}`)) {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
console.log(`battleType: ${options.battleType}, result: ${result}`);
switch(options.battleType) {
case "thief":
if(result == "fail") {
GM_setValue(`thiefTimeoutEnd${PlayerId}`, Date.now() + 60 * 60000 * options.customTimeRate * options.abuBlessRate);
} else {
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`);
}
break;
case "hunt":
setHuntTimeout();
break;
case "merc":
setMercTimeout(result);
break;
}
if(result == "win" && options.battleType != "leader") {
updateOption("enrollNumber", "0");
}
updateOption("battleType", "");
GM_deleteValue(`HoldBattle${PlayerId}`);
}
}
function setTexts() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
var obj;
if(isEn) {
obj = {
healthNotificationEnabled: 'Army restore alarm on',
onceHealthNotificationEnabled: 'Alarm once at army restore',
workNotificationEnabled: 'Workshift alarm on',
notificationDisabled: 'Alarm off',
smithNotificationEnabled: 'Blacksmith alarm on',
mercNotificationEnabled: 'Mercenaries Guild alarm on',
regexp_timegn0: /Come back in (\d+) minutes\./,
regexp_timegn1: /\. Time left: (\d+) minutes\./,
regexp_timegn2: /ou have (\d+) minutes left/,
regexp_timegn3: /\. Time left: (\d+) minutes\./,
regexp_timegn4: /still have (\d+) minutes/,
regexp_timegn5: /you still have \d+ attempts and (\d+) minutes/,
huntNotificationEnabled: 'Hunters Guild alarm on',
regexp_go_timer: 'Next hunt available in',
thiefNotificationEnabled: 'Thieves Guild alarm on',
rangerNotificationEnabled: 'Rangers Guild alarm on',
regexp_timegre: /Come in (\d+) min/,
time_home: /You may enroll again in (\d+) min/,
workPlace: 'Work place:',
alert_health: 'Troops ready: 100%',
workMessage: 'LG: You may enroll again',
smithMessage: 'BS: Blacksmith works are finished',
mercMessage: 'MG: Mercenaries Guild has a quest for you',
huntMessage: 'HG: You notice traces ...',
thiefMessage: options.thiefOrRanger == '0' ? 'TG: You may set an ambush' : 'RG: Rangers Guild has a quest for you',
audio_file: 'Audio file ',
alarm_mode: '<b>Timer alarm mode</b>:',
alarm_mode_sound: 'audio',
alarm_mode_alert: 'message',
alarm_mode_both: 'notification',
alarm_mode_none: 'both',
h_t: 'health',
gonv_t: 'MHT(R)G',
workTimerPanelCaption: 'LG',
smithTimerPanelCaption: 'BS',
smithWelcome: 'To Blacksmith',
mercTimerPanelCaption: 'MG',
mercWelcome: 'To Mercenaries\' Guild',
huntTimerPanelCaption: 'HG',
huntTimerPanelTitle: 'To Hunters\' Guild',
thiefTimerPanelCaption: 'TG',
thiefWelcome: 'To Thieves\' Guild',
rangerTimerPanelCaption: 'RG',
rangerWelcome: 'To Rangers Guild post',
manaWelcome: 'Settings',
successfullyEnrolled: 'You have successfully enrolled',
currentlyUnemployed: 'You are currently unemployed',
regexp_map_go: 'During the journey you have access to the',
huntLicenseExpirationMessage: 'The license expires ',
alert_go_lic_exp: 'HG: Hunter license has expired',
alert_prem_exp: 'Abu-Bakir\'s Charm has expired',
st_start: 'All settings adjustments will apply after page is reloaded',
st_null_timers: 'Reset all timers',
st_gv_n_time: 'Set TG/RG timer for once to',
st_percent_faster: 'Quests HG, MG, TG, RG more often',
joinRangerBattleText: 'Immediately initiate Rangers\' guild battle on arrival',
st_show_timers: 'Show timers:',
st_work_trudogolik_show: 'Notify about workaholic penalty only 2 workshifts away',
st_work_trudogolik_off: 'Turn off all notifications on workaholic penalty',
st_predupr_go_lic: '<b>Hunter license</b> is detected automatically in Hunters\' Guild',
st_go_timer_hide: 'Hide',
st_disable_multiple_alarms: 'Disable repeat signals for ' + disable_alarm_delay + ' sec',
workaholic_penalty: 'Workaholic penalty',
regexp_sm: /Completion time: (\d+)-(\d+) (\d+):(\d+)/,
uze_ustroen: 'You are already employed\.',
uze_ustroen2: 'Less than one hour passed since last enrollment\. Please wait\.',
uze_ustroen3: 'No vacancies\.'
};
} else {
obj = {
healthNotificationEnabled: 'Будет предупреждение о восстановлении армии',
onceHealthNotificationEnabled: 'Установить единоразово предупреждение о восстановлении армии',
workNotificationEnabled: 'Будет предупреждение о конце рабочего часа',
notificationDisabled: 'Не будет предупреждения',
smithNotificationEnabled: 'Будет предупреждение о завершении работ в Кузнице',
mercNotificationEnabled: 'Будет предупреждение Гильдии Наемников',
regexp_timegn0: /Приходи через (\d+) мин/,
regexp_timegn1: /Осталось времени: (\d+) минут/,
regexp_timegn2: /тебя осталось (\d+) минут/,
regexp_timegn3: /у тебя еще есть (\d+) минут/,
regexp_timegn4: /\. Осталось (\d+) минут\./,
regexp_timegn5: /осталось \d+ попыток и (\d+) минут/,
huntNotificationEnabled: 'Будет предупреждение Гильдии Охотников',
regexp_go_timer: 'Следующая охота будет доступна через',
thiefNotificationEnabled: 'Будет предупреждение Гильдии Воров',
rangerNotificationEnabled: 'Будет предупреждение Гильдии Рейнджеров',
regexp_timegre: /приходи через (\d+) мин/,
time_home: /Вы можете устроиться на работу через (\d+)/,
workPlace: 'Место работы:',
alert_health: 'Готовность армии: 100%',
workMessage: 'ГР: Пора на работу',
smithMessage: 'ГК: Работа в Кузнице завершена',
mercMessage: 'ГН: Для Вас есть задание в Гильдии Наемников',
huntMessage: 'ГО: Вы увидели следы ...',
thiefMessage: options.thiefOrRanger == '0' ? 'ГВ: Вы можете устроить засаду' : 'ГРж: Есть задание в Гильдии Рейнджеров',
audio_file: 'Звук сигнала ',
alarm_mode: '<b>Режим оповещения</b> окончания таймера:',
alarm_mode_sound: 'звук',
alarm_mode_alert: 'сообщение',
alarm_mode_both: 'оповещение',
alarm_mode_none: 'отключен',
h_t: 'здоровья',
gonv_t: 'ГОНВ(Рж)',
workTimerPanelCaption: 'ГР',
smithTimerPanelCaption: 'ГК',
smithWelcome: 'В Кузницу',
mercTimerPanelCaption: 'ГН',
mercWelcome: 'В здание Гильдии Наемников',
huntTimerPanelCaption: 'ГО',
huntTimerPanelTitle: 'В здание Гильдии Охотников',
thiefTimerPanelCaption: 'ГВ',
thiefWelcome: 'В здание Гильдии Воров',
rangerTimerPanelCaption: 'ГРж',
rangerWelcome: 'В здание Гильдии Рейнджеров',
manaWelcome: 'Настройки',
successfullyEnrolled: 'Вы устроены на работу',
currentlyUnemployed: 'Вы нигде не работаете',
regexp_map_go: 'Во время пути Вам доступны',
huntLicenseExpirationMessage: 'Лицензия истекает ',
alert_go_lic_exp: 'ГО: Лицензия охотника истекла',
alert_prem_exp: 'Благословение Абу-Бекра истекло',
workaholic_penalty: 'Штраф трудоголика',
regexp_sm: /Завершение работы: (\d+)-(\d+) (\d+):(\d+)/,
st_start: 'Все изменения будут видны после перезагрузки страницы',
st_null_timers: 'Обнулить все таймеры',
st_gv_n_time: 'Единоразово установить таймер ГВ/ГРж равным',
st_percent_faster: 'Задания ГО, ГН, ГВ, ГРж чаще на',
joinRangerBattleText: 'По прибытии вступать в бои Гильдии Рейнджеров',
st_show_timers: '<b>Отображать:</b>',
st_work_trudogolik_show: '<b>Показывать</b> штраф трудоголика только <b>за 2 часа</b>',
st_work_trudogolik_off: '<b>Отключить</b> ВСЕ уведомления о штрафе трудоголика',
st_predupr_go_lic: '<b>Лицензия охотника</b> определяется автоматически (в Гильдии Охотников)',
st_go_timer_hide: '<b>Скрывать</b>',
st_disable_multiple_alarms: 'Запретить повторные сигналы в течении ' + disable_alarm_delay + ' секунд',
uze_ustroen: 'Вы уже устроены\.',
uze_ustroen2: 'Прошло меньше часа с последнего устройства на работу\. Ждите\.',
uze_ustroen3: 'Нет рабочих мест\.'
};
}
return obj;
}
function createTimersPanel() {
const shContainer = document.querySelector("div.sh_container");
const sh_MenuPanel = document.querySelector("div.sh_MenuPanel");
const dragonLeft = document.querySelector("img[src*='i/top'][src*='/dragon__left']"); // https://dcdn1.heroeswm.ru/i/top_ny_rus/dragon__left_.jpg
const dragonRight = document.querySelector("img[src*='i/top'][src*='/dragon__right']");
//document.querySelector("img.mm_decor1") // https://dcdn.heroeswm.ru/i/new_top_ny/mm_decor1.png
let folder = "https://dcdn2.heroeswm.ru/i/top_ny_rus/line/";
const img_link = document.querySelector("img[src*='i/top'][src*='/line/t_end']");
if(img_link) {
folder = /(\S*\/line\/)/.exec(img_link.src)[1];
}
const newYearSuffix = document.querySelector("img[src*='i/top_ny']") || document.querySelector("img[src*='i/new_top_ny']") ? "_" : ""; // если новый год
//console.log(`folder: ${folder}, newYearSuffix: ${newYearSuffix}, ${folder}t_end${newYearSuffix}.jpg`); // folder: https://dcdn2.heroeswm.ru/i/top_ny_rus/line/, newYearSuffix: _
let container = dragonLeft?.parentNode || sh_MenuPanel;
let timersContainerWidth;
let zIndex = 0;
let leftMargin = 0;
let topMargin = 0;
let height;
if(isNewInterface) {
timersContainerWidth = shContainer.getBoundingClientRect().width - 30 * 2;
topMargin = -67;
leftMargin = 159;
zIndex = 2;
height = 26;
//GM_addStyle(`.noTransition { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important; }`);
//Array.from(document.querySelectorAll(".mm_item")).forEach(x => { x.classList.add('noTransition'); x.style.marginTop = "18px"; }); window.innerHeight; // Не получилось убрать плавный сдвиг меню вниз
document.querySelector("div#ResourcesPanel").style.height = "20px";
} else {
timersContainerWidth = dragonRight.getBoundingClientRect().left - dragonLeft.getBoundingClientRect().left + 124;
topMargin = -26;
leftMargin = -43;
height = 26;
}
let timersHtml = `
<style>
.hwm_tb * {font-size: 11px; color: #f5c137;}
.hwm_tb_cell {border-collapse: collapse; background-color: #6b6b69;}
.hwm_tb_cell TD {padding: 0px;}
.cell_t {height: 3px; background: url(${folder}t_top_bkg${newYearSuffix}.jpg);}
.cell_c {white-space: nowrap; height: 18px; background: url(${folder}t_com_bkg${newYearSuffix}.jpg); font-weight: bold;}
.cell_b {height: 5px; background: url(${folder}t_bot_bkg${newYearSuffix}.jpg); text-align: center;}
.cell_b IMG {width: 17px; height: 5px;}
</style>
<table cellpadding=0 cellspacing=0 align="center" class="hwm_tb" style="width: ${timersContainerWidth}px;">
<tr>
<td>
<table width="100%" cellpadding=0 cellspacing=0 style="background: url(${folder}t_bkg${newYearSuffix}.jpg);">
<tr valign=middle align=center>
<td width=5 style="overflow: hidden;">
<img src="${folder}t_end${newYearSuffix}.jpg" alt="" width=9 height=${height}px style="margin:0px 0px 0px -4px;">
</td>`;
const timersWidths = { "health": { width: 44 }, "mana": { width: 44, closeWidth: "5", closeStyle: 'style="overflow: hidden;"', closeImageStyle: 'style="margin:0px -4px 0px 0px;"' } };
for(const tag of timerNames) {
const timerName = `${tag}Timer`;
timersHtml += `
<td id="${timerName}Cell" ${timersWidths[tag] ? `width: ${timersWidths[tag].width}px` : ""}>
<table class="hwm_tb_cell">
<tr>
<td class="cell_t" />
</tr>
<tr>
<td class="cell_c">
<span style="cursor: pointer;" id="${timerName}PanelCaption">${texts[`${timerName}PanelCaption`] ? texts[`${timerName}PanelCaption`] + ":" : ""}</span>
<a id="${timerName}Panel" href="javascript: void(0);" style="text-decoration: none;">00:00</a>
</td>
</tr>
<tr>
<td class="cell_b">
<img src="${folder}t_center${newYearSuffix}.jpg">
</td>
</tr>
</table>
</td>
<td id="${timerName}CloseCell" width="${timersWidths[tag]?.closeWidth || "9"}px" ${timersWidths[tag]?.closeStyle || ""}>
<img src="${folder}t_end${newYearSuffix}.jpg" width=9 height="${height}px" ${timersWidths[tag]?.closeImageStyle || ""}>
</td>
`;
}
timersHtml += `
</tr>
</table>
</td>
</tr>
</table>`;
const timersPanel = addElement("div", container, { style: `position: absolute; margin: ${topMargin}px 0px 0px ${leftMargin}px; text-align: center; z-index: ${zIndex};`, innerHTML: timersHtml });
timersPanel.querySelector('#healthTimerPanel').addEventListener("click", function() { updateOption("healthNotification", x => x.healthNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector('#workTimerPanelCaption').addEventListener("click", function() { updateOption("workNotification", x => x.workNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector('#smithTimerPanelCaption').addEventListener("click", function() { updateOption("smithNotification", x => x.smithNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector('#mercTimerPanelCaption').addEventListener("click", function() { updateOption("mercNotification", x => x.mercNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector('#huntTimerPanelCaption').addEventListener("click", function() { updateOption("huntNotification", x => x.huntNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector('#thiefTimerPanelCaption').addEventListener("click", function() { updateOption("thiefNotification", x => x.thiefNotification == 'yes' ? 'no' : 'yes'); timersPanelDataBind(); });
timersPanel.querySelector("#manaTimerPanel").addEventListener("click", settings);
}
function timersPanelDataBind() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
const healthTimerPanel = document.getElementById('healthTimerPanel');
healthTimerPanel.style.color = options.healthNotification == 'yes' ? '#ff9c00' : '#f5c137';
healthTimerPanel.title = options.healthNotification == 'yes' ? texts.healthNotificationEnabled : texts.onceHealthNotificationEnabled;
const workTimerPanelCaption = document.getElementById('workTimerPanelCaption');
workTimerPanelCaption.style.color = options.workNotification == 'yes' ? '#FF0000' : '#f5c137';
workTimerPanelCaption.title = options.workNotification == 'yes' ? texts.workNotificationEnabled : texts.notificationDisabled;
const workTimerPanel = document.getElementById('workTimerPanel');
let workTimerPanelTtitle = options.abuBlessInfo;
if(options.enrollNumber) {
if(workTimerPanelTtitle) {
workTimerPanelTtitle += '\n';
}
workTimerPanelTtitle += texts.workaholic_penalty + ": " + (9 - Number(options.enrollNumber));
if(options.disableWorkaholicAlarm == '0' && options.enrollNumber > 8) {
workTimerPanel.style.color = '#ff9c00';
}
}
workTimerPanel.title = workTimerPanelTtitle;
if(GM_getValue(`LastWorkObjectId${PlayerId}`)) {
workTimerPanel.href = `object-info.php?id=${GM_getValue(`LastWorkObjectId${PlayerId}`)}`;
}
const smithTimerPanelCaption = document.getElementById('smithTimerPanelCaption');
smithTimerPanelCaption.style.color = options.smithNotification == 'yes' ? '#FF0000' : '#f5c137';
smithTimerPanelCaption.title = options.smithNotification == 'yes' ? texts.smithNotificationEnabled : texts.notificationDisabled;
const smithTimerPanel = document.getElementById('smithTimerPanel');
smithTimerPanel.href = "/mod_workbench.php?type=repair";
smithTimerPanel.title = texts.smithWelcome;
const mercTimerPanelCaption = document.getElementById('mercTimerPanelCaption');
mercTimerPanelCaption.style.color = options.mercNotification == 'yes' ? '#FF0000' : '#f5c137';
mercTimerPanelCaption.title = options.mercNotification == 'yes' ? texts.mercNotificationEnabled : texts.notificationDisabled;
const mercTimerPanel = document.getElementById('mercTimerPanel');
mercTimerPanel.href = "/mercenary_guild.php";
mercTimerPanel.title = texts.mercWelcome;
const huntTimerPanelCaption = document.getElementById('huntTimerPanelCaption');
huntTimerPanelCaption.innerText = texts.huntTimerPanelCaption;
huntTimerPanelCaption.style.color = options.huntNotification == 'yes' ? '#FF0000' : '#f5c137';
huntTimerPanelCaption.title = options.huntNotification == 'yes' ? texts.huntNotificationEnabled : texts.notificationDisabled;
const huntTimerPanel = document.getElementById('huntTimerPanel');
let huntTimerPanelTitle = texts.huntTimerPanelTitle;
if(texts.huntLicenseText) {
huntTimerPanelTitle += '\n' + texts.huntLicenseExpirationMessage + options.huntLicenseText;
}
huntTimerPanel.href = "/hunter_guild.php";
huntTimerPanel.title = huntTimerPanelTitle;
const thiefTimerPanelCaption = document.getElementById('thiefTimerPanelCaption');
thiefTimerPanelCaption.style.color = options.thiefNotification == 'yes' ? '#FF0000' : '#f5c137';
thiefTimerPanelCaption.title = options.thiefNotification == 'yes' ? (options.thiefOrRanger == '0' ? texts.thiefNotificationEnabled : texts.rangerNotificationEnabled) : texts.notificationDisabled;
thiefTimerPanelCaption.innerText = options.thiefOrRanger == '0' ? texts.thiefTimerPanelCaption : texts.rangerTimerPanelCaption;
const thiefTimerPanel = document.getElementById('thiefTimerPanel');
thiefTimerPanel.title = options.thiefOrRanger == '0' ? texts.thiefWelcome : texts.rangerWelcome;
thiefTimerPanel.href = options.thiefOrRanger == '0' ? "/thief_guild.php" : "/ranger_guild.php"
const manaTimerPanel = document.getElementById('manaTimerPanel');
manaTimerPanel.title = texts.manaWelcome;
document.getElementById("workTimerCell").style.display = document.getElementById("workTimerCloseCell").style.display = (options.isShowWorkTimer == "1" ? '' : "none");
document.getElementById("smithTimerCell").style.display = document.getElementById("smithTimerCloseCell").style.display = (options.isShowSmithTimer == "1" ? '' : "none");
document.getElementById("mercTimerCell").style.display = document.getElementById("mercTimerCloseCell").style.display = (options.isShowMercTimer == "1" ? '' : "none");
document.getElementById("huntTimerCell").style.display = document.getElementById("huntTimerCloseCell").style.display = (options.isShowHuntTimer == "1" ? '' : "none");
document.getElementById("thiefTimerCell").style.display = document.getElementById("thiefTimerCloseCell").style.display = (options.isShowThiefTimer == "1" ? '' : "none");
}
function timersDataBind() { timerNames.forEach(x => document.getElementById(`${x}TimerPanel`).innerHTML = secondsFormat(getSecondsLeft(x))); }
function checkWork() {
if(location.pathname == '/object_do.php' || location.pathname == '/object-info.php') {
if(document.body.innerHTML.match(texts.successfullyEnrolled)) {
setWorkTimeoutEnd();
}
}
if(location.pathname == '/home.php') {
if(document.body.innerHTML.match(texts.currentlyUnemployed)) {
GM_deleteValue(`workTimeoutEnd${PlayerId}`);
return;
}
const workObjectRef = Array.from(document.querySelectorAll("a[href^='object-info.php']")).find(x => getParent(x, "td").innerHTML.includes(isEn ? "Currently employed at:" : "Место работы:"))
const workObjectId = workObjectRef ? getUrlParamValue(workObjectRef.href, "id") : "";
// подхватывание времени окончания работы с home.php и его проверка
var time_home_time = texts.time_home.exec(document.body.innerHTML);
if(time_home_time) {
setWorkTimeoutEnd(getServerTime() + Number(time_home_time[1]) * 60000, workObjectId);
} else {
time_home_time = new RegExp(` ${isEn ? "since" : "с"} (\\d{1,2}:\\d{1,2})`).exec(document.body.innerHTML);
if(time_home_time) {
setWorkTimeoutEnd(parseDate(time_home_time[1], false, true).getTime() + 60 * 60 * 1000, workObjectId);
}
}
}
}
function setWorkTimeoutEnd(workTimeoutEnd, workObjectId) {
workTimeoutEnd = workTimeoutEnd || Date.now() + 60 * 60000;
workObjectId = workObjectId || getUrlParamValue(location.href, "id");
const oldValue = parseInt(GM_getValue(`workTimeoutEnd${PlayerId}`, 0));
if(Math.abs(oldValue - workTimeoutEnd) > 70000) {
GM_setValue(`workTimeoutEnd${PlayerId}`, workTimeoutEnd);
GM_setValue(`LastWorkObjectId${PlayerId}`, workObjectId);
updateOption("enrollNumber", x => Number(x.enrollNumber) + 1);
}
}
function checkPremiumAccount() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
// проверка наличия эффекта блага АБУ Бекра (премиум аккаунт) // skipn=1 это 'Ознакомился' или 'Got it!'
if(location.pathname == '/home.php' && document.querySelector("img[src*='i/icons/attr_defense.png']") && !document.querySelector("a[href*='home.php?skipn=1']")) {
const starImage = document.querySelector("img[src$='i/star_extend.png']") || document.querySelector("img[src$='i/star.png']");
options.abuBlessRate = starImage ? "0.7" : "1";
options.abuBlessExpirationTime = '0';
options.abuBlessInfo = starImage ? starImage.title : '';
if(starImage) {
starImage.align = "absmiddle";
const time_prem = /(\d+-\d+-\d+ \d+:\d+)/.exec(starImage.title);
if(time_prem) {
const abuEnd = parseDate(time_prem[1], true);
console.log(abuEnd);
options.abuBlessExpirationTime = abuEnd.getTime();
}
}
}
if(options.abuBlessInfo && Number(options.abuBlessExpirationTime) < serverNow()) {
options.abuBlessRate = '1';
options.abuBlessExpirationTime = '0';
options.abuBlessInfo = '';
}
GM_setValue(`hwmTimersOptions${PlayerId}`, JSON.stringify(options));
}
function checkHuntLicense() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
var form_f2 = document.querySelector("form[name='f2']");
if(location.pathname == '/hunter_guild.php' && form_f2) {
while(form_f2.tagName != 'TR') {
form_f2 = form_f2.parentNode;
}
options.huntLicenseRate = '1';
options.huntLicenseExpirationTime = '0';
options.huntLicenseText = '';
if(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/.exec(form_f2.innerHTML)) {
if(!form_f2.querySelector("input[type='submit'][onclick*='confirm']")) {
// лицензия МО
options.huntLicenseRate = '' + (50 / 100);
} else {
// лицензия О
options.huntLicenseRate = '' + (75 / 100);
}
const forms = form_f2.querySelectorAll("td");
var time_lic_mo_max = 0;
for(const form of forms) {
if(form.innerHTML.indexOf("<td") != -1) {
continue;
}
var time_lic_mo = /(\d+-\d+-\d+ \d+:\d+)/.exec(form.innerHTML);
if(time_lic_mo) {
const licEndTime = parseDate(time_lic_mo[1], true).getTime();
if(licEndTime > time_lic_mo_max) {
time_lic_mo_max = licEndTime;
options.huntLicenseExpirationTime = licEndTime;
options.huntLicenseText = time_lic_mo[0];
}
}
}
}
}
if(options.huntLicenseText && Number(options.huntLicenseExpirationTime) < serverNow()) {
// лицензия охотника истекла
options.huntLicenseRate = '1';
options.huntLicenseExpirationTime = '0';
options.huntLicenseText = '';
}
GM_setValue(`hwmTimersOptions${PlayerId}`, JSON.stringify(options));
}
function setHuntTimeout(restSeconds, rate = 1) {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
restSeconds = restSeconds || ((getServerDateTime().getHours() < 8 ? 20 : 40) * rate * 60 * options.customTimeRate * options.abuBlessRate * options.huntLicenseRate);
GM_setValue(`huntTimeoutEnd${PlayerId}`, Date.now() + restSeconds * 1000);
}
function skipHunt() {
setHuntTimeout(undefined, 0.5);
const map_hunt_block_div = document.querySelector("div#map_hunt_block_div");
if(map_hunt_block_div) {
observe(map_hunt_block_div, hideNativeHuntTimerPanel, true);
}
}
function checkWorkaholic() {
if(location.pathname == '/object-info.php') {
var parent_trud = document.querySelector("a[href*='objectworkers.php']");
if(parent_trud) {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
const workaholicPenaltyExec = new RegExp(`\\*\\ (0\\.?\\d?) ${isEn ? "workaholic penalty" : "штраф трудоголика"}`).exec(document.body.innerHTML);
// отработано смен
let enrollNumber = Number(options.enrollNumber);
if(workaholicPenaltyExec) {
var workaholicPenalty = Number(workaholicPenaltyExec[1]);
if(workaholicPenalty == 0.8) {
enrollNumber = 9;
} else if(workaholicPenalty == 0.7) {
enrollNumber = 10;
} else if(workaholicPenalty == 0.6) {
enrollNumber = 11;
} else if(workaholicPenalty == 0.5) {
enrollNumber = 12;
} else if(workaholicPenalty == 0.4) {
enrollNumber = 13;
} else if(workaholicPenalty == 0.2) {
enrollNumber = 14;
} else if(workaholicPenalty == 0.1 && enrollNumber < 15) {
enrollNumber = 15;
} else if(workaholicPenalty == 0 && enrollNumber < 48) {
enrollNumber = 48;
}
} else if(enrollNumber > 8) {
enrollNumber = 8;
}
console.log(`oldEnrollNumber: ${options.enrollNumber}, enrollNumber: ${enrollNumber}, workaholicPenalty: ${workaholicPenalty}`);
updateOption("enrollNumber", enrollNumber);
if(options.disableWorkaholicAlarm == '0' && (options.showWorkaholicAlarmLastTwoEnrolls == '0' || enrollNumber >= 7)) {
let alarmText = "";
const limits = [9, 11, 48];
if(enrollNumber < limits[0]) {
alarmText = isEn ? `Workaholic penalty through ${limits[0] - enrollNumber} enrollments` : `Штраф трудоголика через ${limits[0] - enrollNumber} устройств`;
} else if(enrollNumber < limits[1]) {
alarmText = isEn ? `It will be impossible to get a job in production through ${limits[1] - enrollNumber} enrollments` : `Невозможно устроиться на производство будет через ${limits[1] - enrollNumber} устройств`;
} else if(enrollNumber < limits[2]) {
alarmText = isEn ? `The opportunity to get a job is ending through ${limits[2] - enrollNumber} enrollments` : `Возможность устраиваться на работу заканчивается через ${limits[2] - enrollNumber} устройств`;
}
const add_trud = document.createElement('span');
if(enrollNumber >= 7) {
add_trud.setAttribute('style', 'color: red; font-weight: bold;'); // выделить цветом
}
add_trud.innerHTML = alarmText;
parent_trud = parent_trud.parentNode.previousSibling.previousSibling;
parent_trud.parentNode.insertBefore(add_trud, parent_trud);
}
// замена "Уже устроен"
parent_trud = document.querySelector("a[href*='objectworkers.php']").parentNode.parentNode;
if(Date.now() > parseInt(GM_getValue(`workTimeoutEnd${PlayerId}`, 0)) && (parent_trud.innerHTML.match(texts.uze_ustroen) || (texts.uze_ustroen = parent_trud.innerHTML.match(texts.uze_ustroen2)) || (texts.uze_ustroen = parent_trud.innerHTML.match(texts.uze_ustroen3)))) {
parent_trud.innerHTML = parent_trud.innerHTML.replace(texts.uze_ustroen, '<style>@-webkit-keyframes blink {80% {opacity:0.0;}} @-moz-keyframes blink {80% {opacity:0.0;}} @-o-keyframes blink {80% {opacity:0.0;}} @keyframes blink {80% {opacity:0.0;}}</style><font color=blue style="-webkit-animation: blink 1s steps(1,end) 0s infinite; -moz-animation: blink 1s steps(1,end) 0s infinite; -o-animation: blink 1s steps(1,end) 0s infinite; animation: blink 1s steps(1,end) 0s infinite"><b>' + texts.uze_ustroen + '</b></font>');
}
}
}
}
function checkMercenary() {
if(location.pathname == '/mercenary_guild.php') {
const mercReputation = parseFloat(new RegExp(`${isEn ? "Reputation" : "Репутация"}: <b>([\\d\\.]+)`).exec(document.body.innerHTML)[1]);
GM_setValue(`mercReputation${PlayerId}`, mercReputation);
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
const mercTimeout = (40 - mercReputation * 2) * options.customTimeRate * options.abuBlessRate * 60000;
let newMercTaskRestTimeExec;
if(document.querySelector("a[href^='/mercenary_guild.php?action=accept']")) {
GM_deleteValue(`mercTimeoutEnd${PlayerId}`);
} else if((newMercTaskRestTimeExec = texts.regexp_timegn0.exec(document.body.innerHTML)) || (newMercTaskRestTimeExec = texts.regexp_timegn1.exec(document.body.innerHTML)) || (newMercTaskRestTimeExec = texts.regexp_timegn2.exec(document.body.innerHTML)) || (newMercTaskRestTimeExec = texts.regexp_timegn3.exec(document.body.innerHTML)) || (newMercTaskRestTimeExec = texts.regexp_timegn4.exec(document.body.innerHTML)) || (newMercTaskRestTimeExec = texts.regexp_timegn5.exec(document.body.innerHTML))) {
let restTimeout = Number(newMercTaskRestTimeExec[1]);
if(texts.regexp_timegn0.exec(document.body.innerHTML) && (restTimeout == 19 || restTimeout == 13)) {
restTimeout++;
}
setMercTimeout(null, restTimeout * 60000);
}
}
if(location.pathname == "/map.php") {
const mercTaskTable = getParent(document.querySelector("table.wbwhite center a[href='mercenary_guild.php']"), "table");
if(mercTaskTable) {
const execTaskButton = mercTaskTable.querySelector("div[id^='hunt_but_']");
if(execTaskButton) {
execTaskButton.addEventListener("click", function() { updateOption("battleType", "merc"); });
}
}
}
}
function setMercTimeout(battleResult = null, timeout = undefined) {
console.log(`battleResult: ${battleResult}, timeout: ${timeout}`);
let mercReputation = parseFloat(GM_getValue(`mercReputation${PlayerId}`, 0));
if(battleResult == "win") {
mercReputation = Math.min(mercReputation + 0.5, 10);
GM_setValue(`mercReputation${PlayerId}`, mercReputation);
}
if(battleResult == "fail") {
mercReputation = Math.max(mercReputation - 1, 0);
GM_setValue(`mercReputation${PlayerId}`, mercReputation);
}
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
timeout = timeout || (40 - mercReputation * 2) * options.customTimeRate * options.abuBlessRate * 60000;
const newTimeoutEnd = Date.now() + timeout;
if(Math.abs(parseInt(GM_getValue(`mercTimeoutEnd${PlayerId}`, 0)) - newTimeoutEnd) > 70000) {
GM_setValue(`mercTimeoutEnd${PlayerId}`, newTimeoutEnd);
}
}
function checkRangerGuild() {
if(location.pathname == '/ranger_guild.php') {
if(document.querySelector("a[href^='ranger_guild.php?action=accept']")) {
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`);
updateOption("thiefOrRanger", "1");
}
var time_gv = texts.regexp_timegre.exec(document.body.innerHTML);
if(time_gv) {
time_gv = Number(time_gv[1]) * 60000; // в миллисекундах
const now = Date.now();
var time_gv_temp = time_gv - Math.abs(parseInt(GM_getValue(`thiefTimeoutEnd${PlayerId}`, 0)) - now);
if(Math.abs(time_gv_temp) > 70000) {
GM_setValue(`thiefTimeoutEnd${PlayerId}`, now + time_gv)
updateOption("thiefOrRanger", "1");
}
}
}
if(location.pathname == '/ranger_list.php') {
var link_ranger_attack = document.querySelectorAll("a[href^='ranger_attack.php?join']");
if(link_ranger_attack.length > 0) {
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`)
updateOption("thiefOrRanger", "1");
for(const link_ranger_attackItem of link_ranger_attack) {
link_ranger_attackItem.addEventListener("click", function() { updateOption("battleType", 'thief'); });
}
}
}
}
function checkModWorkebench() {
if(location.pathname == '/mod_workbench.php') {
parseSmithPage(document);
}
}
function parseSmithPage(doc) {
const allb = doc.querySelectorAll("b");
for(const bold of allb) {
if(bold.innerText.includes(isEn ? "Under repair" : "В ремонте")) {
var repairData = bold.innerText;
break;
}
}
if(repairData) {
const restRepairTime = { Hours: 0, Minutes: 0, Seconds: 59 };
//В ремонте: еще 1 ч. 31 мин. //Under repair another 1 h. 17 min.
const hoursRegex = new RegExp(`(\\d+) ${isEn ? "h" : "ч"}\\.`);
const hoursRegexResult = hoursRegex.exec(repairData);
if(hoursRegexResult) {
restRepairTime.Hours = parseInt(hoursRegexResult[1]);
}
const minutesRegex = new RegExp(`(\\d+) ${isEn ? "min" : "мин"}\\.`);
const minutesRegexResult = minutesRegex.exec(repairData);
if(minutesRegexResult) {
restRepairTime.Minutes = parseInt(minutesRegexResult[1]);
}
//console.log(repairData);
//console.log(restRepairTime);
const repairEnd = new Date();
repairEnd.setHours(repairEnd.getHours() + restRepairTime.Hours);
repairEnd.setMinutes(repairEnd.getMinutes() + restRepairTime.Minutes);
repairEnd.setSeconds(repairEnd.getSeconds() + restRepairTime.Seconds);
//console.log(repairEnd);
const savedRepairEnd = GM_getValue(`smithTimeoutEnd${PlayerId}`);
if(!savedRepairEnd || Math.abs(repairEnd.getTime() - parseInt(savedRepairEnd)) / 1000 / 60 > 2) {
GM_setValue(`smithTimeoutEnd${PlayerId}`, repairEnd.getTime());
}
} else {
GM_deleteValue(`smithTimeoutEnd${PlayerId}`);
}
}
function checkThiefAmbush() {
const thief_ambush_cancel = document.querySelector("a[href^='thief_ambush_cancel.php']");
const form_thief_ambush = document.querySelector("form[action='thief_ambush.php']");
if(thief_ambush_cancel || form_thief_ambush) {
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`);
updateOption("thiefOrRanger", "0");
}
if(thief_ambush_cancel) {
updateOption("battleType", "thief"); // Сидим в засаде, будет воровской бой
}
}
function checkRangerAmbush() {
var form_ranger_attack = document.querySelector("form[action='ranger_attack.php']");
if(form_ranger_attack) {
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`);
updateOption("thiefOrRanger", "1");
form_ranger_attack.querySelector("input[type='submit']").addEventListener("click", function() { updateOption("battleType", 'thief'); });
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
if(options.joinRangerBattle == '1') {
setTimeout(function() { updateOption("battleType", 'thief'); form_ranger_attack.submit(); }, 500);
}
}
}
function checkMapHunter() {
const map_hunt_block_div = document.querySelector("div#map_hunt_block_div");
if(map_hunt_block_div) {
const nativeHuntTimer = map_hunt_block_div.querySelector("div#next_ht_new");
if(nativeHuntTimer) {
setHuntTimeout(windowObject.MapHunterDelta);
} else {
GM_deleteValue(`huntTimeoutEnd${PlayerId}`);
const attackButtons = map_hunt_block_div.querySelectorAll(`div[hint='${isEn ? "Attack" : "Напасть"}'] > img`);
for(const button of attackButtons) {
//console.log(button)
button.addEventListener("click", function() { updateOption("battleType", "hunt"); });
}
const skipButtons = map_hunt_block_div.querySelectorAll(`div[hint^='${isEn ? "Pass" : "Пройти"}'] > img`);
for(const button of skipButtons) {
button.addEventListener("click", function() { skipHunt(); });
}
const callButtons = map_hunt_block_div.querySelectorAll(`div[hint^='${isEn ? "Ask" : "Позвать"}'] > img`);
for(const button of callButtons) {
button.addEventListener("click", function() { setTimeout(function() { Array.from(document.querySelectorAll("form[action='/map.php']")).forEach(x => x.querySelector("input[type='submit']").addEventListener("click", function() { updateOption("battleType", "hunt"); })); }, 200); });
}
}
}
if(mooving && !GM_getValue(`huntTimeoutEnd${PlayerId}`)) {
skipHunt();
}
hideNativeHuntTimerPanel();
}
function hideNativeHuntTimerPanel() {
const next_ht_new = document.querySelector("div#next_ht_new");
if(next_ht_new && gmGetBool("HideHuntTimer")) {
document.querySelector("div#map_hunt_block_div").style.display = "none";
}
}
function parseWaitTime(timeText) {
const restTime = parseTime(timeText);
const date = new Date();
date.setHours(date.getHours() + restTime.Hours);
date.setMinutes(date.getMinutes() + restTime.Minutes);
date.setSeconds(date.getSeconds() + restTime.Seconds);
return date;
}
function parseTime(timeText) {
const time = { Hours: 0, Minutes: 0, Seconds: 0 };
const hoursRegex = new RegExp(`(\\d+) ${isEn ? "h" : "ч"}\\.`);
const hoursRegexResult = hoursRegex.exec(timeText);
if(hoursRegexResult) {
time.Hours = parseInt(hoursRegexResult[1]);
}
const minutesRegex = new RegExp(`(\\d+) ${isEn ? "min" : "мин"}\\.`);
const minutesRegexResult = minutesRegex.exec(timeText);
if(minutesRegexResult) {
time.Minutes = parseInt(minutesRegexResult[1]);
}
const secondsRegex = new RegExp(`(\\d+) ${isEn ? "sec" : "с"}\\.`);
const secondsRegexResult = secondsRegex.exec(timeText);
if(secondsRegexResult) {
time.Seconds = parseInt(secondsRegexResult[1]);
}
return time;
}
function secondsFormat(secondsLeft) {
if(!secondsLeft || secondsLeft < 0) {
return "00:00";
}
const days = Math.floor(secondsLeft / 86400);
const hours = Math.floor((secondsLeft - days * 86400) / 3600);
const minutes = Math.floor((secondsLeft - days * 86400 - hours * 3600) / 60);
const seconds = secondsLeft % 60;
return (days === 0 ? '' : ((days < 10) ? '0' : '') + days + ':') + (days === 0 && hours === 0 ? '' : ((hours < 10) ? '0' : '') + hours + ':') + ((minutes < 10) ? '0' : '') + minutes + ':' + ((seconds < 10) ? '0' : '') + seconds;
}
function getSecondsLeft(timerName) {
//console.log(`${timerName}: ${GM_getValue(`${timerName}TimeoutEnd${PlayerId}`)}`)
if(GM_getValue(`${timerName}TimeoutEnd${PlayerId}`)) {
const result = Math.round((parseInt(GM_getValue(`${timerName}TimeoutEnd${PlayerId}`)) - Date.now()) / 1000);
if(result >= 0) {
return result;
}
}
}
function tick() {
timersDataBind();
const audios = { "health": healthAudio, "work": workAudio, "smith": smithAudio, "merc": warlikeAudio, "hunt": warlikeAudio, "thief": warlikeAudio };
for(const timerName of timerNames) {
const secondsLeft = getSecondsLeft(timerName);
if(secondsLeft == 0) {
GM_deleteValue(`${timerName}TimeoutEnd${PlayerId}`);
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
if(options[`${timerName}Notification`] == 'yes') {
setTimeout(function() { signal(timerName, texts[`${timerName}Message`], audios[timerName]); }, 100);
if(timerName == 'health') {
updateOption("healthNotification", 'no');
timersPanelDataBind();
}
}
}
}
setTimeout(tick, 1000);
}
function signal(timerName, message, sound) {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
if(Date.now() < parseInt(GM_getValue(`${timerName}LastNotificationTime${PlayerId}`, 0)) + 60000) {
return;
}
GM_setValue(`${timerName}LastNotificationTime${PlayerId}`, Date.now());
switch(GM_getValue(`NotificationType${PlayerId}`, '0')) {
case '0':
sound.play();
break;
case '1':
alert(message);
break;
case '2':
GM.notification(message, "ГВД", "https://dcdn.heroeswm.ru/i/rewards/fast_t/3x3_1.png", function() { window.focus(); });
break;
default: //including '3'
}
}
function settings() {
if(showPupupPanel(GM_info.script.name)) {
return;
}
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
const bgcinnerHTML = `
<tr>
<td align="center"> <b>${texts.st_start}</b> </td>
</tr>
<tr>
<td>${texts.st_show_timers} ${texts.workTimerPanelCaption}:<input id=isShowWorkTimerCheckbox type=checkbox>
${texts.smithTimerPanelCaption}:<input id=isShowSmithTimerCheckbox type=checkbox>
${texts.mercTimerPanelCaption}:<input id=isShowMercTimerCheckbox type=checkbox>
${texts.huntTimerPanelCaption}:<input id=isShowHuntTimerCheckbox type=checkbox>
${texts.thiefTimerPanelCaption} (${texts.rangerTimerPanelCaption}):<input id=isShowThiefTimerCheckbox type=checkbox>
</td>
</tr>
<tr>
<td>${texts.joinRangerBattleText}: <input id="joinRangerBattleCheckbox" type=checkbox></td>
</tr>
<tr>
<td>${texts.st_go_timer_hide} "<i>${texts.regexp_go_timer} ..</i>": <input id=go_timer_hide_id type=checkbox></td>
</tr>
<tr>
<td>${texts.st_work_trudogolik_off}: <input id=trudogolik_off_id type=checkbox></td>
</tr>
<tr>
<td>${texts.st_work_trudogolik_show}: <input id=trudogolik_show_id type=checkbox></td>
</tr>
<tr>
<td id="twmTimersSettingsAbuText"></td>
</tr>
<tr>
<td>${texts.st_predupr_go_lic}</td>
</tr>
<tr>
<td>${texts.st_percent_faster} <input id="gv_n_percent" type="number" style="width: 50px;" maxlength="2"> <b>%</b> <input type="submit" id="gv_n_percent_ok" value="ok"></td>
</tr>
<tr>
<td>${texts.st_gv_n_time} <input id="gv_n_time" type="number" style="width: 50px;" maxlength="2"> <b>min</b>
<input type="submit" id="gv_n_time_ok" value="ok"></td>
</tr>
<tr>
<td> <input type="submit" id="null_tr_id" value="${texts.st_null_timers}"> </td>
</tr>
<tr>
<td>${texts.alarm_mode} <input type="radio" name="r_notify_type" id="r_notify_0">${texts.alarm_mode_sound}
<input type="radio" name="r_notify_type" id="r_notify_1">${texts.alarm_mode_alert}
<input type="radio" name="r_notify_type" id="r_notify_2">${texts.alarm_mode_both}
<input type="radio" name="r_notify_type" id="r_notify_3">${texts.alarm_mode_none}
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>${texts.audio_file + texts.workTimerPanelCaption}</td>
<td><input size=55 type="text" id="workSoundInput" value="${options.workSound || ''}"></td>
<td><input size=55 type="button" id="play_audio_gr" value="Play!"> </td>
</tr>
<tr>
<td>${texts.audio_file + texts.gonv_t}</td>
<td><input size=55 type="text" id="warlikeSoundInput" value="${options.warlikeSound || ''}"></td>
<td><input size=55 type="button" id="play_audio_gonv" value="Play!"> </td>
</tr>
<tr>
<td>${texts.audio_file + texts.smithTimerPanelCaption}</td>
<td><input size=55 type="text" id="smithSoundInput" value="${options.smithSound || ''}"></td>
<td><input size=55 type="button" id="play_audio_gk" value="Play!"> </td>
</tr>
<tr>
<td>${texts.audio_file + texts.h_t}</td>
<td><input size=55 type="text" id="healthSoundInput" value="${options.healthSound || ''}"></td>
<td><input size=55 type="button" id="play_audio_h" value="Play!"> </td>
</tr>
</table>
</td>
</tr>
`;
const optionsContainer = createElement("table", { innerHTML: bgcinnerHTML });
optionsContainer.querySelector("#null_tr_id").addEventListener("click", resetTimers);
optionsContainer.querySelector("#gv_n_time_ok").addEventListener("click", function() { if(Number(document.getElementById("gv_n_time").value) >= 0) { GM_setValue(`thiefTimeoutEnd${PlayerId}`, Date.now() + document.getElementById("gv_n_time").value * 60000); } });
optionsContainer.querySelector("#gv_n_percent_ok").addEventListener("click", function() { updateOption("customTimeRate", (100 - document.getElementById("gv_n_percent").value) / 100); settingsDataBind(); });
optionsContainer.querySelector("#joinRangerBattleCheckbox").addEventListener("click", function() { updateOption("joinRangerBattle", this.checked ? '1' : '0'); });
optionsContainer.querySelector("#go_timer_hide_id").addEventListener("click", function() { GM_setValue("HideHuntTimer", this.checked); }, false);
optionsContainer.querySelector("#trudogolik_show_id").addEventListener("click", function() { updateOption("showWorkaholicAlarmLastTwoEnrolls", this.checked ? '1' : '0'); });
optionsContainer.querySelector("#trudogolik_off_id").addEventListener("click", function() { updateOption("disableWorkaholicAlarm", this.checked ? '1' : '0'); });
optionsContainer.querySelector("#isShowWorkTimerCheckbox").addEventListener("click", function() { updateOption("isShowWorkTimer", this.checked ? '1' : '0'); timersPanelDataBind(); });
optionsContainer.querySelector("#isShowSmithTimerCheckbox").addEventListener("click", function() { updateOption("isShowSmithTimer", this.checked ? '1' : '0'); timersPanelDataBind(); });
optionsContainer.querySelector("#isShowMercTimerCheckbox").addEventListener("click", function() { updateOption("isShowMercTimer", this.checked ? '1' : '0'); timersPanelDataBind(); });
optionsContainer.querySelector("#isShowHuntTimerCheckbox").addEventListener("click", function() { updateOption("isShowHuntTimer", this.checked ? '1' : '0'); timersPanelDataBind(); });
optionsContainer.querySelector("#isShowThiefTimerCheckbox").addEventListener("click", function() { updateOption("isShowThiefTimer", this.checked ? '1' : '0'); timersPanelDataBind(); });
optionsContainer.querySelector("#workSoundInput").addEventListener("change", function() { updateOption("workSound", this.value.trim()); workAudio = initAudio(this.value.trim()); });
optionsContainer.querySelector("#warlikeSoundInput").addEventListener("change", function() { updateOption("warlikeSound", this.value.trim()); warlikeAudio = initAudio(this.value.trim()); });
optionsContainer.querySelector("#smithSoundInput").addEventListener("change", function() { updateOption("smithSound", this.value.trim()); smithAudio = initAudio(this.value.trim()); });
optionsContainer.querySelector("#healthSoundInput").addEventListener("change", function() { updateOption("healthSound", this.value.trim()); healthAudio = initAudio(this.value.trim()); });
optionsContainer.querySelector("#play_audio_gr").addEventListener("click", function() { playAudio(document.getElementById("workSoundInput").value); });
optionsContainer.querySelector("#play_audio_gonv").addEventListener("click", function() { playAudio(document.getElementById("warlikeSoundInput").value); });
optionsContainer.querySelector("#play_audio_gk").addEventListener("click", function() { playAudio(document.getElementById("smithSoundInput").value); });
optionsContainer.querySelector("#play_audio_h").addEventListener("click", function() { playAudio(document.getElementById("healthSoundInput").value); });
optionsContainer.querySelector("#r_notify_0").addEventListener("click", function() { if(this.checked) { GM_setValue(`NotificationType${PlayerId}`, "0"); initAudios(); } });
optionsContainer.querySelector("#r_notify_1").addEventListener("click", function() { if(this.checked) { GM_setValue(`NotificationType${PlayerId}`, "1"); } });
optionsContainer.querySelector("#r_notify_2").addEventListener("click", function() { if(this.checked) { GM_setValue(`NotificationType${PlayerId}`, "2"); } });
optionsContainer.querySelector("#r_notify_3").addEventListener("click", function() { if(this.checked) { GM_setValue(`NotificationType${PlayerId}`, "3"); } });
optionsContainer.querySelector(`#r_notify_${GM_getValue(`NotificationType${PlayerId}`, 0)}`).checked = true;
createPupupPanel(GM_info.script.name, `${isEn ? "Options" : "Настройки"} ${GM_info.script.name}`, [[optionsContainer]]);
settingsDataBind();
}
function settingsDataBind() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
document.getElementById("isShowWorkTimerCheckbox").checked = options.isShowWorkTimer == "1";
document.getElementById("isShowSmithTimerCheckbox").checked = options.isShowSmithTimer == "1";
document.getElementById("isShowMercTimerCheckbox").checked = options.isShowMercTimer == "1";
document.getElementById("isShowHuntTimerCheckbox").checked = options.isShowHuntTimer == "1";
document.getElementById("isShowThiefTimerCheckbox").checked = options.isShowThiefTimer == "1";
document.getElementById("joinRangerBattleCheckbox").checked = options.joinRangerBattle == "1";
document.getElementById("go_timer_hide_id").checked = gmGetBool("HideHuntTimer");
document.getElementById("trudogolik_off_id").checked = options.disableWorkaholicAlarm == "1";
document.getElementById("trudogolik_show_id").checked = options.showWorkaholicAlarmLastTwoEnrolls == "1";
document.getElementById("twmTimersSettingsAbuText").innerHTML = options.abuBlessInfo;
document.getElementById("gv_n_percent").value = 100 - options.customTimeRate * 100;
document.getElementById("gv_n_time").value = 60 * options.customTimeRate * options.abuBlessRate;
}
function initAudios() {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
defaultAudio = new Audio('data:audio/mp3;base64,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');
defaultAudio.preload = 'auto';
workAudio = initAudio(options.workSound);
warlikeAudio = initAudio(options.warlikeSound);
smithAudio = initAudio(options.smithSound);
healthAudio = initAudio(options.healthSound);
}
function initAudio(src) {
if(src && src !== '') {
var audio = new Audio();
audio.src = src;
audio.preload = 'auto';
return audio;
}
return defaultAudio;
}
function playAudio(src) {
if(src && src != '') {
var paudio = new Audio();
paudio.preload = 'auto';
paudio.src = src;
paudio.play();
} else {
defaultAudio.play();
}
}
function updateOption(key, val) {
const options = JSON.parse(GM_getValue(`hwmTimersOptions${PlayerId}`));
if(typeof val == "function") {
options[key] = val(options);
} else {
options[key] = val;
}
if(key == "battleType") {
console.log(`battleType: ${options[key]}`);
}
GM_setValue(`hwmTimersOptions${PlayerId}`, JSON.stringify(options));
}
function resetTimers() {
GM_deleteValue(`workTimeoutEnd${PlayerId}`);
GM_deleteValue(`smithTimeoutEnd${PlayerId}`);
GM_deleteValue(`mercTimeoutEnd${PlayerId}`);
GM_deleteValue(`huntTimeoutEnd${PlayerId}`);
GM_deleteValue(`thiefTimeoutEnd${PlayerId}`);
}
function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
function addElement(type, parent, data) {
let el = createElement(type, data);
if(parent) {
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 GM_addStyle(css) { addElement("style", document.head, { type: "text/css", innerHTML: css }); }
function getParent(element, parentType, number = 1) {
if(!element) {
return;
}
let result = element;
let foundNumber = 0;
while(result = result.parentNode) {
if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
foundNumber++;
if(foundNumber == number) {
return result;
}
}
}
}
function getServerTime() { return Date.now() + parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
function getServerDateTime() { return new Date(getServerTime()); }
function toServerTime(clientTime) { return clientTime - parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
function serverNow() { return toServerTime(Date.now()); }
async function requestServerTime() {
if(parseInt(GM_getValue("LastClientServerTimeDifferenceRequestDate", 0)) + 60 * 60 * 1000 < Date.now()) {
GM_setValue("LastClientServerTimeDifferenceRequestDate", Date.now());
const responseText = await getRequestText("/time.php");
const responseParcing = /now (\d+)/.exec(responseText); //responseText: now 1681711364 17-04-23 09:02
if(responseParcing) {
GM_setValue("ClientServerTimeDifference", Date.now() - parseInt(responseParcing[1]) * 1000);
}
} else {
setTimeout(requestServerTime, 60 * 60 * 1000);
}
}
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;
}
function observe(target, handler, once = false) {
const config = { childList: true, subtree: true };
const ob = new MutationObserver(async function(mut, observer) {
observer.disconnect();
if(handler.constructor.name === 'AsyncFunction') {
await handler();
} else {
handler();
}
if(!once) {
observer.observe(target, config);
}
});
ob.observe(target, config);
}
function createPupupPanel(panelName, panelTitle, fieldsMap, panelToggleHandler) {
const backgroundPopupPanel = addElement("div", document.body, { id: panelName + "1", style: "position: fixed; left: 0pt; width: 100%; background: none repeat scroll 0% 0% gray; opacity: 0.5; top: 0px; height: 100%; display: block; z-index: 200;" });
backgroundPopupPanel.addEventListener("click", function() { hidePupupPanel(panelName, panelToggleHandler); });
const popupPanel = addElement("div", document.body, { id: panelName + "2", style: `position: fixed; width: 650px; background: none repeat scroll 0% 0%; background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); left: ${((document.body.offsetWidth - 650) / 2)}px; top: 150px; display: block; z-index: 200; border: 4mm ridge rgba(211, 220, 50, .6);` });
const contentDiv = addElement("div", popupPanel, { id: panelName + "3", style: "border: 1px solid #abc; padding: 5px; margin: 2px; display: flex; flex-wrap: wrap;" });
if(panelTitle) {
addElement("b", contentDiv, { innerText: panelTitle, style: "text-align: center; margin: auto; width: 90%; display: block;" });
}
const divClose = addElement("div", contentDiv, { id: panelName + "close", title: "Close", innerText: "x", style: "border: 1px solid #abc; width: 15px; height: 15px; text-align: center; cursor: pointer;" });
divClose.addEventListener("click", function() { hidePupupPanel(panelName, panelToggleHandler); });
addElement("div", contentDiv, { style: "flex-basis: 100%; height: 0;"});
if(fieldsMap) {
let contentTable = addElement("table", contentDiv);
for(const rowData of fieldsMap) {
if(rowData.length == 0) { // Спомощью передачи пустой стороки-массива, указываем, что надо начать новую таблицу после брейка
addElement("div", contentDiv, { style: "flex-basis: 100%; height: 0;"});
contentTable = addElement("table", contentDiv);
continue;
}
const row = addElement("tr", contentTable);
for(const cellData of rowData) {
const cell = addElement("td", row);
if(cellData) {
if(typeof(cellData) == "string") {
cell.innerText = cellData;
} else {
cell.appendChild(cellData);
}
}
}
}
}
if(panelToggleHandler) {
panelToggleHandler(true);
}
return contentDiv;
}
function showPupupPanel(panelName, panelToggleHandler) {
let backgroundPopupPanel = document.getElementById(panelName + "1");
let popupPanel = document.getElementById(panelName + "2");
if(backgroundPopupPanel) {
backgroundPopupPanel.style.display = popupPanel.style.display = 'block';
if(panelToggleHandler) {
panelToggleHandler(true);
}
return true;
}
return false;
}
function hidePupupPanel(panelName, panelToggleHandler) {
let backgroundPopupPanel = document.getElementById(panelName + "1");
let popupPanel = document.getElementById(panelName + "2");
backgroundPopupPanel.style.display = popupPanel.style.display = 'none';
if(panelToggleHandler) {
panelToggleHandler(false);
}
}
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(`healthTimeoutEnd${PlayerId}`, Date.now() + restSeconds * 1000);
} else {
GM_deleteValue(`healthTimeoutEnd${PlayerId}`);
}
return [heart, maxHeart, timeHeart];
}
}
async function initUserName() {
if(GM_getValue("TransporterUserName")) {
GM_deleteValue("UserName");
GM_deleteValue("TransporterUserName");
}
if(location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) {
//console.log(document.querySelector("h1").innerText)
GM_setValue("UserName", document.querySelector("h1").innerText);
}
if(location.pathname == "/home.php") {
//console.log(document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText)
GM_setValue("UserName", document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText);
}
if(!GM_getValue("UserName")) {
const doc = await getRequest(`/pl_info.php?id=${PlayerId}`);
GM_setValue("UserName", doc.querySelector("h1").innerText);
}
}
function parseDate(dateString, isFuture = false, isPast = 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) {
var 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;
}
}
}
if(dateStrings.length > 2) {
const letterDateExec = /(\d{2}):(\d{2}) (\d{2}) (.{3,4})/.exec(dateString);
if(letterDateExec) {
//console.log(letterDateExec)
day = parseInt(letterDateExec[3]);
//const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
const monthShortNames = ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сент', 'окт', 'ноя', 'дек'];
month = monthShortNames.findIndex(x => x.toLowerCase() == letterDateExec[4].toLowerCase());
if(isPast && (new Date(year, month, day, hours, minutes, seconds)).getTime() > Date.now()) {
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 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 getRequestText(url, overrideMimeType = "text/html; charset=windows-1251") {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
onload: function(response) { resolve(response.responseText); },
onerror: function(error) { reject(error); }
});
});
}