// ==UserScript==
// @name TimeNpc
// @namespace https://github.com/MyRequiem/comfortablePlayingInGW
// @description На главной странице выводит время, оставшееся до взятия квеста и сcылку на NPC, у которого в последний раз брали квест. Звуковое оповещение. Умеет выводить список NPC с информацией о них для каждого острова.
// @id comfortablePlayingInGW@MyRequiem
// @updateURL https://raw.githubusercontent.com/MyRequiem/comfortablePlayingInGW/master/separatedScripts/TimeNpc/timeNpc.meta.js
// @downloadURL https://raw.githubusercontent.com/MyRequiem/comfortablePlayingInGW/master/separatedScripts/TimeNpc/timeNpc.user.js
// @include https://*gwars*/me.php*
// @include https://*gwars*/me/*
// @include https://*gwars*/npc.php?id=*
// @grant none
// @license MIT
// @version 2.37-140522
// @author MyRequiem [https://www.gwars.io/info.php?id=2095458]
// ==/UserScript==
/*global unsafeWindow */
/*jslint browser: true, maxlen: 80, vars: true, nomen: true, plusplus: true,
devel: true, regexp: true
*/
/*eslint-env browser */
/*eslint no-useless-escape: 'warn', linebreak-style: ['error', 'unix'],
quotes: ['error', 'single'], semi: ['error', 'always'],
eqeqeq: 'error', curly: 'error'
*/
/*jscs:disable requireMultipleVarDecl, requireVarDeclFirst */
/*jscs:disable disallowKeywords, disallowDanglingUnderscores */
/*jscs:disable validateIndentation */
(function () {
'use strict';
// ================= НАСТРОЙКИ ==========================
var soundNPC = 17; // номер звука, когда пора делать квест (0 - без звука)
// ============== КОНЕЦ НАСТРОЕК ========================
/**
* @class General
* @constructor
*/
var General = function () {
/**
* @property root
* @type {Object}
*/
this.root = this.getRoot();
/**
* @property doc
* @type {Object}
*/
this.doc = this.root.document;
/**
* @property loc
* @type {String}
*/
this.loc = this.root.location.href;
/**
* @property st
* @type {Object}
*/
this.st = this.root.localStorage;
/**
* @property STNAME
* @type {String}
*/
this.STNAME = 'timeNpc';
/**
* @property imgPath
* @type {String}
*/
this.imgPath = 'https://raw.githubusercontent.com/MyRequiem/' +
'comfortablePlayingInGW/master/imgs/';
/**
* @property domain
* @type {String}
*/
this.domain = this.doc.domain;
};
/**
* @lends General.prototype
*/
General.prototype = {
/**
* @method getRoot
* @return {Object}
*/
getRoot: function () {
var rt = typeof unsafeWindow;
return rt !== 'undefined' ? unsafeWindow : window;
},
/**
* @method setData
* @param {Array} data
*/
setData: function (data) {
this.st.setItem(this.STNAME, data.join('|'));
},
/**
* @method getData
* @return {Array}
*/
getData: function () {
var stData = this.st.getItem(this.STNAME);
if (stData) {
return stData.split('|');
}
stData = ['1', '', ''];
this.setData(stData);
return stData;
},
/**
* @method $
* @param {string} id
* @return {HTMLElement|null}
*/
$: function (id) {
return this.doc.querySelector('#' + id);
}
};
var general = new General();
/**
* @class AjaxQuery
* @constructor
*/
var AjaxQuery = function () {
/**
* @method init
* @param {String} url
* @param {Function} onsuccess
* @param {Function} onfailure
*/
this.init = function (url, onsuccess, onfailure) {
var xmlHttpRequest = new XMLHttpRequest();
if (!xmlHttpRequest) {
general.root.console.log('Error create xmlHttpRequest !!!');
return;
}
xmlHttpRequest.open('GET', url, true);
xmlHttpRequest.send(null);
var timeout = general.root.setTimeout(function () {
xmlHttpRequest.abort();
}, 10000);
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState === 4) {
clearTimeout(timeout);
if (xmlHttpRequest.status === 200) {
onsuccess(xmlHttpRequest);
} else {
onfailure();
}
}
};
};
};
/**
* @class PlaySound
* @constructor
*/
var PlaySound = function () {
/**
* @method init
* @param {int|String} sound
*/
this.init = function (sound) {
if (sound && sound !== '0') {
var audio = general.$('cpingw_audio');
if (!audio) {
audio = general.doc.createElement('audio');
audio.setAttribute('id', 'cpingw_audio');
var divAudio = general.doc.createElement('div');
divAudio.setAttribute('style', 'display: none;');
divAudio.appendChild(audio);
general.doc.body.appendChild(divAudio);
}
audio.volume = 0.3;
audio.src = 'https://raw.githubusercontent.com/MyRequiem/' +
'comfortablePlayingInGW/master/sounds/' + sound + '.ogg';
// noinspection JSIgnoredPromiseFromCall
audio.play();
}
};
};
/**
* @class TimeNpc
* @constructor
*/
var TimeNpc = function () {
/**
* @property imgPath
* @type {String}
*/
this.imgPath = general.imgPath + 'TimeNpc/';
/**
* @property npc
* @type {Object}
*/
this.npc = {
g: ['2', '3', '6', '8', '10', '12'],
z: ['1', '4', '5', '7', '9', '11'],
p: ['16', '17', '18', '19', '20']
};
/**
* @property tm
* @type {int}
*/
this.tm = 1000;
/**
* @method clearNPCData
*/
this.clearNPCData = function () {
general.$('dataNPC').innerHTML = '';
};
/**
* @method setCloseButton
*/
this.setCloseButton = function () {
general.$('dataNPC').innerHTML += '
|
';
general.$('npsDataClose').
addEventListener('click', this.clearNPCData, false);
general.$('imgSoundNPC').removeAttribute('checkscan');
};
/**
* @method scanNPC
* @param {int} ind
* @param {Array} npcs
*/
this.scanNPC = function (ind, npcs) {
if (!ind) {
if (general.$('imgSoundNPC').getAttribute('checkscan')) {
return;
}
this.clearNPCData();
general.$('imgSoundNPC').setAttribute('checkscan', 'yes');
}
var url = 'https://' + general.domain + '/npc.php?id=' + npcs[ind],
_this = this,
tr,
td;
tr = general.doc.createElement('tr');
td = general.doc.createElement('td');
td.setAttribute('style', 'text-align: center;');
td.setAttribute('colspan', '3');
td.innerHTML = '';
tr.appendChild(td);
general.$('dataNPC').appendChild(tr);
new AjaxQuery().init(url, function (xml) {
var spanContent = general.doc.createElement('span');
spanContent.innerHTML = xml.responseText;
if (/Вы находитесь в пути/.test(spanContent.innerHTML)) {
general.$('dataNPC').lastElementChild.innerHTML = 'Вы в пути. Данные NPC не ' +
'доступны. | ';
_this.setCloseButton();
return;
}
var cssSelector1 = 'td[class="wb"][colspan="3"]' +
'[bgcolor="#f0fff0"]',
cssSelector2 = 'a[href*="/syndicate.php?id="]',
cssSelector3 = 'td[class="wb"][align="left" ]' +
'[width="100%"]>b',
syndLink = spanContent.querySelector(cssSelector1).
querySelector(cssSelector2),
nameNPC = spanContent.querySelector(cssSelector3).innerHTML;
general.$('dataNPC').lastElementChild.innerHTML = '' +
' | ' + nameNPC + ' | ' +
'' +
syndLink.nextSibling.nodeValue.replace(/^\s*/, '') +
' | ';
ind++;
if (npcs[ind]) {
general.root.setTimeout(function () {
_this.scanNPC(ind, npcs);
}, _this.tm);
return;
}
_this.setCloseButton();
}, function () {
general.root.setTimeout(function () {
if (!ind) {
general.$('imgSoundNPC').removeAttribute('checkscan');
}
_this.scanNPC(ind, npcs);
}, _this.tm);
});
};
/**
* @method getTimeNow
* @return {int}
*/
this.getTimeNow = function () {
return new Date().getTime();
};
/**
* @method goQuest
*/
this.goQuest = function () {
var stData = general.getData();
general.$('timerNPC').innerHTML = '' +
'Взять квест';
if (stData[0]) {
new PlaySound().init(soundNPC);
}
};
/**
* @method showTimerNPC
* @param {int} sec
*/
this.showTimerNPC = function (sec) {
var timer = general.$('spanTimer');
// при переходе на личного NPC таймера не будет
if (timer) {
var s = sec,
h = Math.floor(s / 3600);
s -= h * 3600;
var min = Math.floor(s / 60);
s -= min * 60;
h = h < 10 ? '0' + h : h;
min = min < 10 ? '0' + min : min;
s = s < 10 ? '0' + s : s;
general.$('spanTimer').innerHTML = h + ':' + min + ':' + s;
sec -= 1;
var _this = this;
if (sec > -1) {
general.root.setTimeout(function () {
_this.showTimerNPC(sec);
}, 1000);
} else {
this.goQuest();
}
}
};
/**
* @method init
*/
this.init = function () {
// на главной странице личного NPC
if (/\?nid=\d+/.test(general.loc)) {
return;
}
/**
* localStorage
* [0] - звук вкл/выкл
* [1] - ID NPC, у которого последний раз брали квест
* [2] - время
*/
var stData = general.getData();
if (/gwars.*\/me(\/|\.php)/.test(general.loc)) {
var mainDiv = general.doc.createElement('div'),
target = general.doc.querySelector('td[rowspan="3"]' +
'[valign="top"][bgcolor="#e9ffe9"]>' +
'div[style="padding-left:5px"]>' +
'a[href$="/home.friends.php"]').previousElementSibling,
onoff = stData[0] ? 'On' : 'Off';
mainDiv.setAttribute('style', 'font-size: 8pt; ' +
'padding-left: 16px;');
target.parentNode.insertBefore(mainDiv, target);
mainDiv.innerHTML = '[Z][G][P] ' +
'';
var _this = this;
general.$('imgSoundNPC').addEventListener('click', function () {
var data = general.getData(),
d = data[0],
s = d ? 'Sound Off' : 'Sound On',
img = this;
img.src = _this.imgPath +
(d ? 'soundOff.png' : 'soundOn.png');
img.setAttribute('title', s);
img.setAttribute('alt', s);
data[0] = d ? '' : '1';
general.setData(data);
}, false);
general.$('buttonNPC_Z').addEventListener('click', function () {
_this.scanNPC(0, _this.npc.z);
}, false);
general.$('buttonNPC_G').addEventListener('click', function () {
_this.scanNPC(0, _this.npc.g);
}, false);
general.$('buttonNPC_P').addEventListener('click', function () {
_this.scanNPC(0, _this.npc.p);
}, false);
if (!stData[2]) { // время не установлено
general.$('timerNPC').innerHTML = '' +
'Поговорите с NPC';
} else {
if (this.getTimeNow() >= stData[2]) { // пора делать квест
this.goQuest();
} else { // ждем
general.$('timerNPC').innerHTML = 'NPC: ' +
'[]';
var sec = Math.
ceil((+stData[2] - this.getTimeNow()) / 1000);
this.showTimerNPC(sec);
}
}
return;
}
var talkNPC = general.doc.
querySelector('td[class="wb"][valign="top"]'),
talk = /\?id=(\d+)&talk=1/.exec(general.loc);
// если id у NPC больше 20, то это не наш NPC
if (talkNPC && talk && +talk[1] < 21) {
stData[1] = talk[1];
// говорим с NPC, но время квеста еще не пришло
var timer = /\[подождите (\d+) мин/.exec(talkNPC.innerHTML);
if (timer) {
stData[2] = +timer[1] * 60 * 1000 + this.getTimeNow();
general.setData(stData);
return;
}
// если берем или отказываемся от квеста,
// то стираем время из хранилища
if (/Ваш ответ:/.test(talkNPC.innerHTML)) {
stData[2] = '';
general.setData(stData);
}
}
};
};
new TimeNpc().init();
}());