// ==UserScript==
// @name 咕咕镇数据采集
// @namespace https://greasyfork.org/users/448113
// @version 1.4.1
// @description 咕咕镇数据采集,目前采集已关闭,兼作助手
// @author paraii
// @match https://www.guguzhen.com/*
// @grant GM_xmlhttpRequest
// @connect www.guguzhen.com
// @run-at document-body
// @license MIT License
// ==/UserScript==
// @connect notes.orga.cat
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/js/tooltip.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/js/popover.js
(function() {
'use strict'
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const g_modificationVersion = '2022-05-19 00:30:00';
const g_kfUser = document.getElementsByClassName('icon-user')[0].parentNode.innerText.split(' ')[1];
const g_autoTaskEnabledStorageKey = g_kfUser + '_autoTaskEnabled';
const g_amuletGroupsStorageKey = g_kfUser + '_amulet_groups';
const g_equipmentBGStorageKey = g_kfUser + '_equipment_BG';
const g_beachBGStorageKey = g_kfUser + '_beach_BG';
const g_userDataStorageKeyConfig = [ g_kfUser, g_autoTaskEnabledStorageKey, 'keepcheck', g_amuletGroupsStorageKey,
g_equipmentBGStorageKey, g_beachBGStorageKey, 'beachcheck' ];
const g_userDataStorageKeyExtra = [ 'attribute', 'cardName', 'title', 'over', 'halo_max', 'dataReward' ];
const USER_STORAGE_RESERVED_SEPARATORS = /[:;,|=+*%!#$&?<>{}^`"\\\/\[\]\r\n\t\v\s]/;
const USER_STORAGE_KEY_VALUE_SEPARATOR = ':';
// perform a binary search. array must be sorted, but no matter in ascending or descending order.
// in this manner, you must pass in a proper comparer function for it works properly, aka, if the
// array was sorted in ascending order, then the comparer(a, b) should return a negative value
// while a < b or a positive value while a > b; otherwise, if the array was sorted in descending
// order, then the comparer(a, b) should return a positive value while a < b or a negative value
// while a > b, and in both, if a equals b, the comparer(a, b) should return 0. if you pass nothing
// or null / undefined value as comparer, then you must make sure about that the array was sorted
// in ascending order.
//
// in this particular case, we just want to check whether the array contains the value or not, we
// don't even need to point out the first place where the value appears (if the array actually
// contains the value), so we perform a simplest binary search and return an index (may not the
// first place where the value appears) or a negative value (means value not found) to indicate
// the search result.
function searchElement(array, value, fnComparer) {
if (array?.length > 0) {
fnComparer ??= ((a, b) => a < b ? -1 : (a > b ? 1 : 0));
let li = 0;
let hi = array.length - 1;
while (li <= hi) {
let mi = ((li + hi) >> 1);
let cr = fnComparer(value, array[mi]);
if (cr == 0) {
return mi;
}
else if (cr > 0) {
li = mi + 1;
}
else {
hi = mi - 1;
}
}
}
return -1;
}
// perform a binary insertion. the array and comparer must exactly satisfy as it in the searchElement
// function. this operation behaves sort-stable, aka, the newer inserting element will be inserted
// into the position after any existed equivalent elements.
function insertElement(array, value, fnComparer) {
if (array != null) {
fnComparer ??= ((a, b) => a < b ? -1 : (a > b ? 1 : 0));
let li = 0;
let hi = array.length - 1;
while (li <= hi) {
let mi = ((li + hi) >> 1);
let cr = fnComparer(value, array[mi]);
if (cr >= 0) {
li = mi + 1;
}
else {
hi = mi - 1;
}
}
array.splice(li, 0, value);
return li;
}
return -1;
}
// it's not necessary to have newArray been sorted, but the oldArray must be sorted since we are calling
// searchElement. if there are some values should be ignored in newArray, the comparer(a, b) should be
// implemented as return 0 whenever parameter a equals any of values that should be ignored.
function findNewObjects(newArray, oldArray, fnComparer, findIndices) {
// just in case, i discovered that sometimes if we use array.length directly in for(...) statement
// (either some other statements too), the statement get chances to be executed incorrectly (or just
// console.log can be effected?), don't know why, but we can use a temporary variable to handle this.
let newObjects = [];
let nl = (newArray?.length ?? 0);
for (let i = 0; i < nl; i++) {
if (searchElement(oldArray, newArray[i], fnComparer) < 0) {
newObjects.push(findIndices ? i : newArray[i]);
}
}
return newObjects;
}
// HTTP requests
var g_httpRequests = [];
function httpRequestRegister(request) {
if (request != null) {
g_httpRequests.push(request);
}
}
function httpRequestAbortAll() {
while (g_httpRequests.length > 0) {
g_httpRequests.pop().abort();
}
g_httpRequests = [];
}
function httpRequestClearAll() {
g_httpRequests = [];
}
function objectIdParseNodes(nodes, ids, ignoreEmptyCell) {
for (let node of nodes) {
if (node.className?.endsWith("fyg_mp3")) {
let id = node.getAttribute('onclick')?.match(/\d+/)[0];
if (id != undefined) {
ids.push(id);
}
else if (!ignoreEmptyCell) {
ids.push(-1);
}
}
}
}
const g_postMethod = 'POST'
const g_readUrl = 'https://www.guguzhen.com/fyg_read.php'
const g_postUrl = 'https://www.guguzhen.com/fyg_click.php'
const g_postHeader = { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' , 'Cookie' : document.cookie };
const g_networkTimeoutMS = 120 * 1000;
function beginReadObjects(bagIds, storeIds, ignoreEmptyCell, fnFurtherProcess, fnParams) {
if (bagIds != null || storeIds != null) {
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div = document.createElement('div');
div.innerHTML = response.responseText;
if (bagIds != null) {
objectIdParseNodes(div.children[0].children[1].children, bagIds, ignoreEmptyCell);
}
if (storeIds != null) {
objectIdParseNodes(div.children[1].children[1].children, storeIds, ignoreEmptyCell);
}
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
});
httpRequestRegister(request);
}
else if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
// we wait the response(s) of the previous batch of request(s) to send another batch of request(s)
// rather than simply send them all within an inside foreach - which could cause too many requests
// to server simultaneously, that can be easily treated as D.D.O.S attack and therefor leads server
// to returns http status 503: Service Temporarily Unavailable
// * caution * the parameter 'objects' is required been sorted by their indices in ascending order
const g_maxConcurrentRequestsCount = 5;
var g_objectMoveRequestsCount = 0;
var g_objectMoveTargetSiteFull = false;
var g_func_puti_data = null;
var g_func_puto_data = null;
function beginMoveObjects(objects, bagToStore, fnFurtherProcess, fnParams) {
if (!g_objectMoveTargetSiteFull && objects?.length > 0) {
g_func_puti_data ??= getPostData(/puti\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1);
g_func_puto_data ??= getPostData(/puto\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1);
let ids = [];
while (ids.length < g_maxConcurrentRequestsCount && objects.length > 0) {
let id = objects.pop();
if (id >= 0) {
ids.push(id);
}
}
if ((g_objectMoveRequestsCount = ids.length) > 0) {
while (ids.length > 0) {
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: (bagToStore ? g_func_puti_data : g_func_puto_data).replace('"+id+"', ids.shift()),
onload: response => {
if (response.responseText != 'ok') {
g_objectMoveTargetSiteFull = true;
}
if (--g_objectMoveRequestsCount == 0) {
beginMoveObjects(objects, bagToStore, fnFurtherProcess, fnParams);
}
}
});
httpRequestRegister(request);
}
return;
}
}
g_objectMoveTargetSiteFull = false;
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
// read currently mounted role card and halo informations
// roleInfo = [ roleId, roleName ]
// haloInfo = [ haloPoints, haloSlots, [ haloItem1, haloItem2, … ] ]
function beginReadRoleAndHalo(roleInfo, haloInfo, fnFurtherProcess, fnParams) {
let asyncOperations = 0;
let error = 0;
let requestRole;
let requestHalo;
if (roleInfo != null) {
asyncOperations++;
requestRole = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=9',
onload: response => {
let div = document.createElement('div');
div.innerHTML = response.responseText;
let role = roleMap.get(div.querySelector('div.text-info.fyg_f24.fyg_lh60')?.children[0]?.innerText);
if (role != undefined) {
roleInfo.push(role.id);
roleInfo.push(role.name);
}
asyncOperations--;
},
onerror : err => {
error++;
asyncOperations--;
},
ontimeout : err => {
error++;
asyncOperations--;
}
});
}
if (haloInfo != null) {
asyncOperations++;
requestHalo = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=5',
onload: response => {
let haloPS = response.responseText.match(/<h3>[^\d]*(\d+)[^\d]*(\d+)[^<]+<\/h3>/);
if (haloPS?.length == 3) {
haloInfo.push(parseInt(haloPS[1]));
haloInfo.push(parseInt(haloPS[2]));
}
else {
haloInfo.push(0);
haloInfo.push(0);
}
let halo = [];
for (let item of response.responseText.matchAll(/halotfzt2\((\d+)\)/g)) {
halo.push(item[1]);
}
haloInfo.push(halo);
asyncOperations--;
},
onerror : err => {
error++;
asyncOperations--;
},
ontimeout : err => {
error++;
asyncOperations--;
}
});
}
let timeout = 0;
let timer = setInterval(() => {
if (asyncOperations == 0 || error > 0 || (++timeout * 200) >= g_networkTimeoutMS) {
clearInterval(timer);
if (asyncOperations > 0) {
requestRole?.abort();
requestHalo?.abort();
}
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
}, 200);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// end by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const AMULET_STORAGE_GROUP_SEPARATOR = '|';
const AMULET_STORAGE_GROUPNAME_SEPARATOR = '=';
const AMULET_STORAGE_AMULET_SEPARATOR = ',';
const AMULET_TYPE_ID_FACTOR = 100000000000000;
const AMULET_LEVEL_ID_FACTOR = 10000000000000;
const AMULET_ENHANCEMENT_FACTOR = 1000000000000;
const AMULET_BUFF_MAX_FACTOR = AMULET_ENHANCEMENT_FACTOR;
const g_amuletLevelIds = {
稀有 : 0,
史诗 : 1,
传奇 : 2
};
const g_amuletTypeIds = {
苹果 : 0,
葡萄 : 1,
樱桃 : 2
};
const g_amuletLevelNames = [ '稀有', '史诗', '传奇' ];
const g_amuletTypeNames = [ '苹果', '葡萄', '樱桃' ];
const g_amuletBuffUnits = [ '点', '%', '%' ];
const g_amuletBuffTypeNames = [ '力量', '敏捷', '智力', '体魄', '精神', '意志',
'物理攻击', '魔法攻击', '速度', '生命护盾回复效果', '最大生命值', '最大护盾值',
'固定生命偷取', '固定反伤', '固定暴击几率', '固定技能几率', '物理防御效果', '魔法防御效果' ];
const g_amuletBuffShortMarks = [ 'STR', 'AGI', 'INT', 'VIT', 'SPR', 'MND',
'PATK', 'MATK', 'SPD', 'REC', 'HP', 'SLD',
'LCH', 'RFL', 'CRT', 'SKL', 'PDEF', 'MDEF' ];
const g_amuletBuffTypeOrders = new Map();
g_amuletBuffTypeNames.forEach((item, index) => { g_amuletBuffTypeOrders.set(item, index); });
function Amulet() {
this.id = -1;
this.type = -1;
this.level = 0;
this.enhancement = 0;
this.buffCode = 0;
this.text = null;
this.reset = (() => {
this.id = -1;
this.type = -1;
this.level = 0;
this.enhancement = 0;
this.buffCode = 0;
this.text = null;
});
this.isValid = (() => {
return (this.type >= 0 && this.type <= 2 && this.buffCode > 0);
});
this.fromCode = ((code) => {
if (!isNaN(code)) {
this.type = Math.trunc(code / AMULET_TYPE_ID_FACTOR) % 10;
this.level = Math.trunc(code / AMULET_LEVEL_ID_FACTOR) % 10;
this.enhancement = Math.trunc(code / AMULET_ENHANCEMENT_FACTOR) % 10;
this.buffCode = code % AMULET_BUFF_MAX_FACTOR;
}
else {
this.reset();
}
return (this.isValid() ? this : null);
});
this.fromBuffText = ((text) => {
if (text?.length > 0) {
let nb = text.split(' = ');
if (nb.length == 2) {
this.id = -1;
this.type = g_amuletTypeIds[nb[0].slice(2, 4)];
this.level = g_amuletLevelIds[nb[0].slice(0, 2)];
this.enhancement = parseInt(nb[0].match(/\d+/)[0]);
this.buffCode = 0;
for (let buff of nb[1].replaceAll(/(\+)|( 点)|( %)/g, '').split(', ')) {
let nv = buff.split(' ');
this.buffCode += ((100 ** (g_amuletBuffTypeOrders.get(nv[0]) % 6)) * nv[1]);
}
if (this.isValid()) {
this.text = nb[1];
return this;
}
}
}
this.reset();
return null;
});
this.fromNode = ((node) => {
if (node?.className?.endsWith("fyg_mp3") && node.innerText.indexOf('+') >= 0) {
let id = node.getAttribute('onclick');
let typeName = (node.getAttribute('data-original-title') ?? node.getAttribute('title'));
let content = node.getAttribute('data-content');
if (id != null && typeName?.length > 4 && content?.length > 0 &&
!isNaN(this.type = g_amuletTypeIds[typeName.slice(2, 4)]) &&
!isNaN(this.level = g_amuletLevelIds[typeName.slice(0, 2)]) &&
!isNaN(this.id = parseInt(id.match(/\d+/)[0])) &&
!isNaN(this.enhancement = parseInt(node.innerText.match(/\d+/)[0]))) {
this.buffCode = 0;
this.text = '';
let attr = null;
let regex = /<p[^>]*>([^<]+)<[^>]*>\+(\d+)[^<]*<\/span><\/p>/g;
while ((attr = regex.exec(content))?.length == 3) {
this.buffCode += ((100 ** (g_amuletBuffTypeOrders.get(attr[1]) % 6)) * attr[2]);
this.text += `${this.text.length > 0 ? ', ' : ''}${attr[1]} +${attr[2]} ${g_amuletBuffUnits[this.type]}`;
}
if (this.isValid()) {
return this;
}
}
}
this.reset();
return null;
});
this.fromAmulet = ((amulet) => {
if (amulet?.isValid()) {
this.id = amulet.id;
this.type = amulet.type;
this.level = amulet.level;
this.enhancement = amulet.enhancement;
this.buffCode = amulet.buffCode;
this.text = amulet.text;
}
else {
this.reset();
}
return (this.isValid() ? this : null);
});
this.getCode = (() => {
if (this.isValid()) {
return (this.type * AMULET_TYPE_ID_FACTOR +
this.level * AMULET_LEVEL_ID_FACTOR +
this.enhancement * AMULET_ENHANCEMENT_FACTOR +
this.buffCode);
}
return -1;
});
this.getBuff = (() => {
let buffs = {};
if (this.isValid()) {
let type = this.type * 6;
for (let buff of g_amuletBuffTypeNames.slice(type, type + 6)) {
let v = Math.trunc(this.buffCode / (100 ** (g_amuletBuffTypeOrders.get(buff) % 6))) % 100;
if (v > 0) {
buffs[buff] = v;
}
}
}
return buffs;
});
this.formatName = (() => {
if (this.isValid()) {
return `${g_amuletLevelNames[this.level]}${g_amuletTypeNames[this.type]} (+${this.enhancement})`;
}
return null;
});
this.formatBuff = (() => {
if (this.isValid()) {
if (this.text?.length > 0) {
return this.text;
}
this.text = '';
let buffs = this.getBuff();
for (let buff in buffs) {
this.text += `${this.text.length > 0 ? ', ' : ''}${buff} +${buffs[buff]} ${g_amuletBuffUnits[this.type]}`;
}
}
return this.text;
});
this.formatBuffText = (() => {
if (this.isValid()) {
return this.formatName() + ' = ' + this.formatBuff();
}
return null;
});
this.formatShortMark = (() => {
let text = this.formatBuff()?.replaceAll(/(\+)|( 点)|( %)/g, '');
if (text?.length > 0) {
for (let buff in this.getBuff()) {
text = text.replaceAll(buff, g_amuletBuffShortMarks[g_amuletBuffTypeOrders.get(buff)]);
}
return this.formatName() + ' = ' + text;
}
return null;
});
this.compareTo = ((other, ascType) => {
if (!this.isValid()) {
return 1;
}
else if (!other?.isValid()) {
return -1;
}
else if (this.id >= 0 && this.id == other.id) {
return 0;
}
let delta = other.type - this.type;
if (delta != 0) {
return (ascType ? -delta : delta);
}
let tbuffs = this.formatBuffText().split(' = ')[1].replaceAll(/(\+)|( 点)|( %)/g, '').split(', ');
let obuffs = other.formatBuffText().split(' = ')[1].replaceAll(/(\+)|( 点)|( %)/g, '').split(', ');
let bl = Math.min(tbuffs.length, obuffs.length);
for (let i = 0; i < bl; i++) {
let tbuff = tbuffs[i].split(' ');
let obuff = obuffs[i].split(' ');
if ((delta = g_amuletBuffTypeOrders.get(tbuff[0]) - g_amuletBuffTypeOrders.get(obuff[0])) != 0 ||
(delta = parseInt(obuff[1]) - parseInt(tbuff[1])) != 0) {
return delta;
}
}
if ((delta = obuffs.length - tbuffs.length) != 0 ||
(delta = other.level - this.level) != 0 ||
(delta = other.enhancement - this.enhancement) != 0) {
return delta;
}
return 0;
});
}
function AmuletGroup(persistenceString) {
this.buffSummary = {
力量 : 0,
敏捷 : 0,
智力 : 0,
体魄 : 0,
精神 : 0,
意志 : 0,
物理攻击 : 0,
魔法攻击 : 0,
速度 : 0,
生命护盾回复效果 : 0,
最大生命值 : 0,
最大护盾值 : 0,
固定生命偷取 : 0,
固定反伤 : 0,
固定暴击几率 : 0,
固定技能几率 : 0,
物理防御效果 : 0,
魔法防御效果 : 0
};
this.name = null;
this.items = [];
this.isValid = (() => {
return (this.items.length > 0 && amuletIsValidGroupName(this.name));
});
this.count = (() => {
return this.items.length;
});
this.clear = (() => {
this.items = [];
for (let buff in this.buffSummary) {
this.buffSummary[buff] = 0;
}
});
this.add = ((amulet) => {
if (amulet?.isValid()) {
let buffs = amulet.getBuff();
for (let buff in buffs) {
this.buffSummary[buff] += buffs[buff];
}
return insertElement(this.items, amulet, (a, b) => a.compareTo(b, true));
}
return -1;
});
this.remove = ((amulet) => {
if (this.isValid() && amulet?.isValid()) {
let i = searchElement(this.items, amulet, (a, b) => a.compareTo(b, true));
if (i >= 0) {
let buffs = amulet.getBuff();
for (let buff in buffs) {
this.buffSummary[buff] -= buffs[buff];
}
this.items.splice(i, 1);
return true;
}
}
return false;
});
this.removeId = ((id) => {
if (this.isValid()) {
let i = this.items.findIndex((a) => a.id == id);
if (i >= 0) {
let amulet = this.items[i];
let buffs = amulet.getBuff();
for (let buff in buffs) {
this.buffSummary[buff] -= buffs[buff];
}
this.items.splice(i, 1);
return amulet;
}
}
return null;
});
this.validate = ((amulets) => {
if (this.isValid()) {
let mismatch = 0;
let al = this.items.length;
let i = 0;
if (amulets?.length > 0) {
amulets = amulets.slice().sort((a, b) => a.type != b.type ? a.type - b.type : a.buffCode - b.buffCode);
for ( ; amulets.length > 0 && i < al; i++) {
let mi = searchElement(amulets, this.items[i], (a, b) => a.type != b.type ? a.type - b.type : a.buffCode - b.buffCode);
if (mi >= 0) {
// remove a matched amulet from the amulet pool can avoid one single amulet matches all
// the equivalent objects in the group.
// let's say two (or even more) AGI +5 apples in one group is fairly normal, if we just
// have only one equivalent apple in the amulet pool and we don't remove it when the
// first match happens, then the 2nd apple will get matched later, the consequence would
// be we can never find the mismatch which should be encountered at the 2nd apple
this.items[i].fromAmulet(amulets[mi]);
amulets.splice(mi, 1);
}
else {
mismatch++;
}
}
}
if (i > mismatch) {
this.items.sort((a, b) => a.compareTo(b, true));
}
if (i < al) {
mismatch += (al - i);
}
return (mismatch == 0);
}
return false;
});
this.findIndices = ((amulets) => {
let indices;
let al;
if (this.isValid() && (al = (amulets?.length ?? 0)) > 0) {
let items = this.items.slice().sort((a, b) => a.type != b.type ? a.type - b.type : a.buffCode - b.buffCode);
for (let i = 0; items.length > 0 && i < al; i++) {
let mi;
if (amulets[i]?.id >= 0 &&
(mi = searchElement(items, amulets[i], (a, b) => a.type != b.type ? a.type - b.type : a.buffCode - b.buffCode)) >= 0) {
// similar to the 'validate', remove the amulet from the search list when we found
// a match item in first time to avoid the duplicate founding, e.g. say we need only
// one AGI +5 apple in current group and we actually have 10 of AGI +5 apples in store,
// if we found the first matched itme in store and record it's index but not remove it
// from the temporary searching list, then we will continuously reach this kind of
// founding and recording until all those 10 AGI +5 apples are matched and processed,
// this obviously ain't the result what we expected
(indices ??= []).push(i);
items.splice(mi, 1);
}
}
}
return indices;
});
this.parse = ((persistenceString) => {
this.clear();
if (persistenceString?.length > 0) {
let elements = persistenceString.split(AMULET_STORAGE_GROUPNAME_SEPARATOR);
if (elements.length == 2) {
let name = elements[0].trim();
if (amuletIsValidGroupName(name)) {
let items = elements[1].split(AMULET_STORAGE_AMULET_SEPARATOR);
let il = items.length;
for (let i = 0; i < il; i++) {
if (this.add((new Amulet()).fromCode(parseInt(items[i]))) < 0) {
this.clear();
break;
}
}
if (this.count() > 0) {
this.name = name;
}
}
}
}
return (this.count() > 0);
});
this.formatBuffSummary = ((linePrefix, lineSuffix, lineSeparator) => {
if (this.isValid()) {
let str = '';
let nl = '';
for (let buff of g_amuletBuffTypeNames) {
let v = this.buffSummary[buff];
if (v > 0) {
str += `${nl}${linePrefix}${buff} +${v} ${g_amuletBuffUnits[Math.trunc(g_amuletBuffTypeOrders.get(buff) / 6)]}${lineSuffix}`;
nl = lineSeparator;
}
}
return str;
}
return '';
});
this.formatItems = ((linePrefix, erroeLinePrefix, lineSuffix, errorLineSuffix, lineSeparator) => {
if (this.isValid()) {
let str = '';
let nl = '';
for (let amulet of this.items) {
str += `${nl}${amulet.id < 0 ? erroeLinePrefix : linePrefix}${amulet.formatBuffText()}` +
`${amulet.id < 0 ? errorLineSuffix : lineSuffix}`;
nl = lineSeparator;
}
return str;
}
return '';
});
this.getDisplayStringLineCount = (() => {
if (this.isValid()) {
let lines = 0;
for (let buff of g_amuletBuffTypeNames) {
if (this.buffSummary[buff] > 0) {
lines++;
}
}
return lines + this.items.length;
}
return 0;
});
this.formatPersistenceString = (() => {
if (this.isValid()) {
let codes = [];
for (let amulet of this.items) {
codes.push(amulet.getCode());
}
return `${this.name}${AMULET_STORAGE_GROUPNAME_SEPARATOR}${codes.join(AMULET_STORAGE_AMULET_SEPARATOR)}`;
}
return '';
});
this.parse(persistenceString);
}
function AmuletGroupCollection(persistenceString) {
this.items = {};
this.itemCount = 0;
this.count = (() => {
return this.itemCount;
});
this.contains = ((name) => {
return (this.items[name] != undefined);
});
this.add = ((item) => {
if (item?.isValid()) {
if (!this.contains(item.name)) {
this.itemCount++;
}
this.items[item.name] = item;
return true;
}
return false;
});
this.remove = ((name) => {
if (this.contains(name)) {
delete this.items[name];
this.itemCount--;
return true;
}
return false;
});
this.clear = (() => {
for (let name in this.items) {
delete this.items[name];
}
this.itemCount = 0;
});
this.get = ((name) => {
return this.items[name];
});
this.rename = ((oldName, newName) => {
if (amuletIsValidGroupName(newName)) {
let group = this.items[oldName];
if (this.remove(oldName)) {
group.name = newName;
return this.add(group);
}
}
return false;
});
this.toArray = (() => {
let groups = [];
for (let name in this.items) {
groups.push(this.items[name]);
}
return groups;
});
this.parse = ((persistenceString) => {
this.clear();
if (persistenceString?.length > 0) {
let groupStrings = persistenceString.split(AMULET_STORAGE_GROUP_SEPARATOR);
let gl = groupStrings.length;
for (let i = 0; i < gl; i++) {
if (!this.add(new AmuletGroup(groupStrings[i]))) {
this.clear();
break;
}
}
}
return (this.count() > 0);
});
this.formatPersistenceString = (() => {
let str = '';
let ns = '';
for (let name in this.items) {
str += (ns + this.items[name].formatPersistenceString());
ns = AMULET_STORAGE_GROUP_SEPARATOR;
}
return str;
});
this.parse(persistenceString);
}
function amuletIsValidGroupName(groupName) {
return (groupName?.length > 0 && groupName.length < 32 && groupName.search(USER_STORAGE_RESERVED_SEPARATORS) < 0);
}
function amuletSaveGroups(groups) {
if (groups?.count() > 0) {
localStorage.setItem(g_amuletGroupsStorageKey, groups.formatPersistenceString());
}
else {
localStorage.removeItem(g_amuletGroupsStorageKey);
}
}
function amuletLoadGroups() {
return new AmuletGroupCollection(localStorage.getItem(g_amuletGroupsStorageKey));
}
function amuletClearGroups() {
localStorage.removeItem(g_amuletGroupsStorageKey);
}
function amuletSaveGroup(group) {
if (group?.isValid()) {
let groups = amuletLoadGroups();
if (groups.add(group)) {
amuletSaveGroups(groups);
}
}
}
function amuletLoadGroup(groupName) {
return amuletLoadGroups().get(groupName);
}
function amuletDeleteGroup(groupName) {
let groups = amuletLoadGroups();
if (groups.remove(groupName)) {
amuletSaveGroups(groups);
}
}
function amuletCreateGroupFromArray(groupName, amulets) {
if (amulets?.length > 0 && amuletIsValidGroupName(groupName)) {
let group = new AmuletGroup(null);
for (let amulet of amulets) {
if (group.add(amulet) < 0) {
group.clear();
break;
}
}
if (group.count() > 0) {
group.name = groupName;
return group;
}
}
return null;
}
function amuletNodesToArray(nodes, array) {
let amulet;
for (let node of nodes) {
if ((amulet ??= new Amulet()).fromNode(node)?.isValid()) {
array.push(amulet);
amulet = null;
}
}
}
function beginReadAmulets(bagAmulets, storeAmulets, fnFurtherProcess, fnParams) {
if (bagAmulets != null || storeAmulets != null) {
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div = document.createElement('div');
div.innerHTML = response.responseText;
if (bagAmulets != null) {
amuletNodesToArray(div.children[0].children[1].children, bagAmulets);
}
if (storeAmulets != null) {
amuletNodesToArray(div.children[1].children[1].children, storeAmulets);
}
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
});
httpRequestRegister(request);
}
else if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
function beginMoveAmulets({ groupName, amulets, unload, proc, params }) {
let indices = amuletLoadGroup(groupName)?.findIndices(amulets)?.sort((a, b) => b - a);
let ids;
while (indices?.length > 0) {
(ids ??= []).push(amulets[indices.pop()].id);
}
beginMoveObjects(ids, unload, proc, params);
}
function beginLoadAmuletGroupFromStore(groupName, fnFurtherProcess, fnParams) {
let amulets = [];
beginReadAmulets(null, amulets, beginMoveAmulets,
{ groupName : groupName, amulets : amulets, unload : false, proc : fnFurtherProcess, params : fnParams });
}
function beginUnloadAmuletGroupFromBag(groupName, fnFurtherProcess, fnParams) {
let amulets = [];
beginReadAmulets(amulets, null, beginMoveAmulets,
{ groupName : groupName, amulets : amulets, unload : true, proc : fnFurtherProcess, params : fnParams });
}
function beginClearBag(fnFurtherProcess, fnParams) {
function beginClearBagObjects({ objects, proc, params }) {
beginMoveObjects(objects, true, proc, params);
}
let objects = [];
beginReadObjects(objects, null, true, beginClearBagObjects,
{ objects : objects, proc : fnFurtherProcess, params : fnParams });
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// end by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const g_genericPopupContainerId = 'generic-popup-container';
const g_genericPopupClass = 'generic-popup';
const g_genericPopupId = g_genericPopupClass;
const g_genericPopupContentContainerId = 'generic-popup-content-container';
const g_genericPopupContentClass = 'generic-popup-content';
const g_genericPopupContentId = g_genericPopupContentClass;
const g_genericPopupFixedContentId = 'generic-popup-content-fixed';
const g_genericPopupProgressClass = g_genericPopupClass;
const g_genericPopupProgressId = 'generic-popup-progress';
const g_genericPopupProgressContentClass = 'generic-popup-content-progress';
const g_genericPopupProgressContentId = g_genericPopupProgressContentClass;
const g_genericPopupTopLineDivClass = 'generic-popup-top-line-container';
const g_genericPopupTitleTextClass = 'generic-popup-title-text';
const g_genericPopupTitleTextId = g_genericPopupTitleTextClass;
const g_genericPopupTitleButtonContainerId = 'generic-popup-title-button-container';
const g_genericPopupFootButtonContainerId = 'generic-popup-foot-button-container';
const g_genericPopupBackgroundColor = '#ebf2f9';
const g_genericPopupBorderColor = '#3280fc';
const g_genericPopupTitleTextColor = '#ffffff';
const g_genericPopupStyle =
`<style>
.${g_genericPopupClass} {
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, .5);
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 9999;
display: none;
justify-content: center;
align-items: center;
}
.${g_genericPopupContentClass} {
width: 100%;
background-color: ${g_genericPopupBackgroundColor};
box-sizing: border-box;
padding: 0px 30px;
color: black;
}
.${g_genericPopupProgressContentClass} {
width: 400px;
height: 200px;
background-color: ${g_genericPopupBackgroundColor};
box-sizing: border-box;
border: 2px solid ${g_genericPopupBorderColor};
border-radius: 5px;
display: table;
}
#${g_genericPopupProgressContentId} {
height: 100%;
width: 100%;
color: #0000c0;
font-size: 24px;
font-weight: bold;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.${g_genericPopupTopLineDivClass} {
width: 100%;
padding: 20px 0px;
border-top: 2px groove #d0d0d0;
}
.generic-popup-title-foot-container {
width: 100%;
height: 40px;
background-color: ${g_genericPopupBorderColor};
padding: 0px 30px;
display: table;
}
.${g_genericPopupTitleTextClass} {
height: 100%;
color: ${g_genericPopupTitleTextColor};
font-size: 18px;
display: table-cell;
text-align: left;
vertical-align: middle;
}
</style>`;
const g_genericPopupHTML =
`${g_genericPopupStyle}
<div class="${g_genericPopupClass}" id="${g_genericPopupId}">
<div style="border:2px solid ${g_genericPopupBorderColor};border-radius:5px;">
<div class="generic-popup-title-foot-container">
<span class="${g_genericPopupTitleTextClass}" id="${g_genericPopupTitleTextId}"></span>
<div id="${g_genericPopupTitleButtonContainerId}" style="float:right;margin-top:6px;"></div>
</div>
<div id="${g_genericPopupContentContainerId}">
<div class="${g_genericPopupContentClass}" id="${g_genericPopupFixedContentId}" style="display:none;"></div>
<div class="${g_genericPopupContentClass}" id="${g_genericPopupContentId}"></div>
</div>
<div class="generic-popup-title-foot-container">
<div id="${g_genericPopupFootButtonContainerId}" style="float:right;margin-top:8px;"></div>
</div>
</div>
</div>
<div class="${g_genericPopupProgressClass}" id="${g_genericPopupProgressId}">
<div class="${g_genericPopupProgressContentClass}"><span id="${g_genericPopupProgressContentId}"></span></div>
</div>`;
if (document.getElementById(g_genericPopupContainerId) == null) {
let genericPopupContainer = document.createElement('div');
genericPopupContainer.id = g_genericPopupContainerId;
genericPopupContainer.innerHTML = g_genericPopupHTML;
document.body.appendChild(genericPopupContainer);
}
function genericPopupInitialize() {
document.getElementById(g_genericPopupContainerId).innerHTML = g_genericPopupHTML;
}
function genericPopupReset() {
let fixedContent = document.getElementById(g_genericPopupFixedContentId);
fixedContent.style.display = 'none';
fixedContent.innerHTML = '';
document.getElementById(g_genericPopupTitleTextId).innerText = '';
document.getElementById(g_genericPopupContentId).innerHTML = '';
document.getElementById(g_genericPopupTitleButtonContainerId).innerHTML = '';
document.getElementById(g_genericPopupFootButtonContainerId).innerHTML = '';
}
function genericPopupSetContent(title, content) {
document.getElementById(g_genericPopupTitleTextId).innerText = title;
document.getElementById(g_genericPopupContentId).innerHTML = content;
}
function genericPopupSetFixedContent(content) {
let fixedContent = document.getElementById(g_genericPopupFixedContentId);
fixedContent.style.display = 'block';
fixedContent.innerHTML = content;
}
function genericPopupAddButton(text, width, clickProc, addToTitle) {
let btn = document.createElement('button');
btn.innerText = text;
btn.onclick = clickProc;
if (width != null && width > 0) {
width = width.toString();
btn.style.width = width + (width.endsWith('px') || width.endsWith('%') ? '' : 'px');
}
else {
btn.style.width = 'auto';
}
document.getElementById(addToTitle
? g_genericPopupTitleButtonContainerId
: g_genericPopupFootButtonContainerId).appendChild(btn);
}
function genericPopupAddCloseButton(width, text, addToTitle) {
genericPopupAddButton(text?.length > 0 ? text : '关闭', width, (() => { genericPopupClose(true); }), addToTitle);
}
function genericPopupSetContentSize(height, width, scrollable) {
height = (height?.toString() ?? '100%');
width = (width?.toString() ?? '100%');
document.getElementById(g_genericPopupContentContainerId).style.width
= width + (width.endsWith('px') || width.endsWith('%') ? '' : 'px');
let content = document.getElementById(g_genericPopupContentId);
content.style.height = height + (height.endsWith('px') || height.endsWith('%') ? '' : 'px');
content.style.overflow = (scrollable ? 'auto' : 'hidden');
}
function genericPopupShowModal(clickOutsideToClose) {
genericPopupClose(false);
let popup = document.getElementById(g_genericPopupId);
if (clickOutsideToClose) {
popup.onclick = ((event) => {
if (event.target == popup) {
genericPopupClose(true);
}
});
}
else {
popup.onclick = null;
}
popup.style.display = "flex";
}
function genericPopupClose(reset) {
genericPopupCloseProgressMessage();
let popup = document.getElementById(g_genericPopupId);
popup.style.display = "none";
if (reset) {
genericPopupReset();
}
httpRequestClearAll();
}
function genericPopupShowProgressMessage(progressMessage) {
genericPopupClose(false);
document.getElementById(g_genericPopupProgressContentId).innerText = (progressMessage?.length > 0 ? progressMessage : '请稍候…');
document.getElementById(g_genericPopupProgressId).style.display = "flex";
}
function genericPopupCloseProgressMessage() {
document.getElementById(g_genericPopupProgressId).style.display = "none";
}
//
// generic task-list based progress popup
//
const g_genericPopupTaskListId = 'generic-popup-task-list';
const g_genericPopupTaskItemId = 'generic-popup-task-item-';
const g_genericPopupTaskWaiting = '×';
const g_genericPopupTaskCompleted = '√';
const g_genericPopupTaskCompletedWithError = '!';
const g_genericPopupColorTaskIncompleted = '#c00000';
const g_genericPopupColorTaskCompleted = '#0000c0';
const g_genericPopupColorTaskCompletedWithError = 'red';
var g_genericPopupIncompletedTaskCount = 0;
function genericPopupTaskListPopupSetup(title, popupWidth, tasks, fnCancelRoutine, cancelButtonText, cancelButtonWidth) {
g_genericPopupIncompletedTaskCount = tasks.length;
genericPopupSetContent(title, `<div style="padding:15px 0px 15px 0px;"><ul id="${g_genericPopupTaskListId}"></ul></div>`);
let indicatorList = document.getElementById(g_genericPopupTaskListId);
for (let i = 0; i < g_genericPopupIncompletedTaskCount; i++) {
let li = document.createElement('li');
li.id = g_genericPopupTaskItemId + i;
li.style.color = g_genericPopupColorTaskIncompleted;
li.innerHTML = `<span>${g_genericPopupTaskWaiting}</span><span> ${tasks[i]} </span><span></span>`;
indicatorList.appendChild(li);
}
if (fnCancelRoutine != null) {
genericPopupAddButton(cancelButtonText?.length > 0 ? cancelButtonText : '取消', cancelButtonWidth, fnCancelRoutine, false);
}
genericPopupSetContentSize(Math.min(g_genericPopupIncompletedTaskCount * 20 + 30, unsafeWindow.innerHeight - 400), popupWidth, true);
}
function genericPopupTaskSetState(index, state) {
let item = document.getElementById(g_genericPopupTaskItemId + index)?.lastChild;
if (item != undefined) {
item.innerText = state;
}
}
function genericPopupTaskComplete(index, error) {
let li = document.getElementById(g_genericPopupTaskItemId + index);
if (li?.firstChild?.innerText == g_genericPopupTaskWaiting) {
li.firstChild.innerText = (error ? g_genericPopupTaskCompletedWithError : g_genericPopupTaskCompleted);
li.style.color = (error ? g_genericPopupColorTaskCompletedWithError : g_genericPopupColorTaskCompleted);
g_genericPopupIncompletedTaskCount--;
}
}
function genericPopupTaskCheckCompletion() {
return (g_genericPopupIncompletedTaskCount == 0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// end by zyxboy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
var headersPOST = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie': document.cookie };
var user = document.getElementsByClassName('icon-user')[0].parentNode.innerText.split(' ')[1];
console.log(user)
if (localStorage.getItem(user) == null) {
localStorage.setItem(user, '{"dataIndex":{"battleInfoNow":"0","battleInfoBefore":"0","battleInfoBack":"0"},"dataBind":{"0":"0"},"dataBeachSift":{"0":"0"}}');
}
function getUserData() {
return JSON.parse(localStorage.getItem(user));
}
function setUserData(json) {
localStorage.setItem(user, JSON.stringify(json));
}
function eqToAbbr(name) {
let abbr = 0;
switch (name[name.length - 1]) {
case '杖':
switch (name[name.length - 2]) {
case '短':
abbr = 'STAFF';
break;
case '法':
abbr = 'WAND';
break;
}
break;
case '剑':
switch (name[name.length - 2]) {
case '之':
abbr = 'SWORD';
break;
case '重':
abbr = 'CLAYMORE';
break;
}
break;
case '刃':
abbr = 'BLADE';
break;
case '首':
abbr = 'DAGGER';
break;
case '盾':
abbr = 'SHIELD';
break;
case '套':
switch (name[name.length - 3]) {
case '者':
abbr = 'GLOVES';
break;
case '鹫':
abbr = 'VULTURE';
break;
}
break;
case '环':
abbr = 'BRACELET';
break;
case '袍':
abbr = 'CLOAK';
break;
case '巾':
abbr = 'SCARF';
break;
case '饰':
abbr = 'TIARA';
break;
case '带':
abbr = 'RIBBON';
break;
default:
switch (name[name.length - 2]) {
case '短':
abbr = 'BOW';
break;
case '杀':
abbr = 'ASSBOW';
break;
case '布':
abbr = 'CLOTH';
break;
case '皮':
abbr = 'LEATHER';
break;
case '铁':
abbr = 'PLATE';
break;
case '重':
abbr = 'THORN';
break;
}
}
return abbr;
}
function readEquipmentDOM(responseText) {
let div0 = document.createElement('div');
div0.innerHTML = `${responseText}</div>`;
div0.innerHTML = `${div0.children[0].children[1].innerHTML}${div0.children[1].children[1].innerHTML}`;
return div0;
}
function getEquipmentInfo(nodes) {
let data = new Array();
if (nodes.length > 0) {
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].className.split(' ').length != 3 || nodes[i].innerText.indexOf('+') != -1) {
continue;
}
let atrr = nodes[i].getAttribute('data-content').match(/>\s*\d+%\s*</g);
let title = 0;
title = nodes[i].getAttribute('data-original-title');
if (title == null) {
title = nodes[i].getAttribute('title');
}
let lv = title.match(/>\d+</g)[0];
let name = title.substr(title.lastIndexOf('>') + 1);
let mys = nodes[i].getAttribute('data-content').match(/\[神秘属性\]/);
if (mys != null) {
mys = 1;
} else {
mys = 0;
}
let id = nodes[i].getAttribute('onclick');
if (id != null) {
id = id.match(/\d+/)[0];
}
name = eqToAbbr(name);
data.push(new Array(name, lv.replaceAll(/[<>]/g, ''), atrr[0].replaceAll(/[\s<>%]/g, ''), atrr[1].replaceAll(/[\s<>%]/g, ''),
atrr[2].replaceAll(/[\s<>%]/g, ''), atrr[3].replaceAll(/[\s<>%]/g, ''), mys, id));
}
}
return data;
}
var equKey = new Array('BLADE', 'ASSBOW', 'WAND', 'STAFF', 'DAGGER', 'CLAYMORE', 'SHIELD', 'BOW', 'SWORD', 'BOUND_0',
'GLOVES', 'BRACELET', 'VULTURE', 'BOUND_1', 'CLOAK', 'THORN', 'PLATE', 'LEATHER', 'CLOTH', 'BOUND_2', 'SCARF', 'TIARA', 'RIBBON');
var fullName = new Array('狂信者的荣誉之刃', '反叛者的刺杀弓', '光辉法杖', '探险者短杖', '幽梦匕首', '陨铁重剑', '荆棘剑盾', '探险者短弓', '探险者之剑', 'BOUND_0',
'探险者手套', '命师的传承手环', '秃鹫手套', 'BOUND_1', '旅法师的灵光袍', '战线支撑者的荆棘重甲', '铁甲', '皮甲', '布甲', 'BOUND_2', '探险者头巾', '占星师的发饰', '天使缎带');
//
// by zyxboy
var typedict = [];
var typedicttype = 0;
var roleMap = new Map();
function initializeRoleBindings() {
roleMap.set('舞', { id : 3000 , name : '舞' , shortMark : 'WU' });
roleMap.set('默', { id : 3001 , name : '默' , shortMark : 'MO' });
roleMap.set('琳', { id : 3002 , name : '琳' , shortMark : 'LIN' });
roleMap.set('艾', { id : 3003 , name : '艾' , shortMark : 'AI' });
roleMap.set('梦', { id : 3004 , name : '梦' , shortMark : 'MENG' });
roleMap.set('薇', { id : 3005 , name : '薇' , shortMark : 'WEI' });
roleMap.set('伊', { id : 3006 , name : '伊' , shortMark : 'YI' });
roleMap.set('冥', { id : 3007 , name : '冥' , shortMark : 'MING' });
roleMap.set('命', { id : 3008 , name : '命' , shortMark : 'MIN' });
roleMap.set('希', { id : 3009 , name : '希' , shortMark : 'XI' });
let roles = Array.from(roleMap.values());
for (let role of roles) {
roleMap.set(role.id, role);
roleMap.set(role.id.toString(), role);
roleMap.set(role.shortMark, role);
}
let udata = getUserData();
for (let key in udata.dataBind) {
if (roleMap.get(key) == undefined) {
delete udata.dataBind[key];
}
}
setUserData(udata);
}
initializeRoleBindings();
// end by zyxboy
//
var sortdict = [];
var fullNameOf = [];
for (let i = 0; i < equKey.length; i++) {
//
// by zyxboy
if (equKey[i].startsWith('BOUND_')) {
typedicttype++;
}
typedict[equKey[i]] = typedicttype;
// end by zyxboy
//
sortdict[equKey[i]] = i;
fullNameOf[equKey[i]] = fullName[i];
}
function sortEqByName(e1, e2) {
try {
let name1 = undefined;
let title1 = e1.getAttribute('data-original-title');
if (title1 != null || (title1 = e1.getAttribute('title')) != null) {
name1 = eqToAbbr(title1.substr(title1.lastIndexOf('>') + 1));
e1.setAttribute('data-abbr', sortdict[name1]);
}
let name2 = undefined;
let title2 = e2.getAttribute('data-original-title');
if (title2 != null || (title2 = e2.getAttribute('title')) != null) {
name2 = eqToAbbr(title2.substr(title2.lastIndexOf('>') + 1));
e2.setAttribute('data-abbr', sortdict[name2]);
}
if (!name1 && !name2) {
return ((new Amulet()).fromNode(e1)?.compareTo((new Amulet()).fromNode(e2)) ?? 1);
}
else if (!name1) {
return 1;
}
else if (!name2) {
return -1;
}
else if (name1 == name2) {
return parseInt(title1.match(/>(\d+)</)[1]) - parseInt(title2.match(/>(\d+)</)[1]);
}
else if (typedict[name1] == typedict[name2]) {
return (sortdict[name1] - sortdict[name2]);
}
return (typedict[name1] - typedict[name2]);
}
catch {
console.log(e1);
}
}
function getPostData(p1, p2) {
let data = -1;
let sc = document.getElementsByTagName('script');
for (let i = 0; i < sc.length; i++) {
let func = sc[i].innerText.match(p1);
if (func != null) {
data = func[0].match(p2)[0];
break;
}
}
return data;
}
function wishExpireTip() {
GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: `f=19`,
onload: response => {
let cost = response.responseText.split('#')[0];
if (parseInt(cost) < 200) {
let h = document.getElementsByClassName('panel-heading')[0];
h.innerHTML += '<span style="text-align:center;display:block;background-color:red">※许愿池已过期</span>';
}
}
});
}
if (window.location.pathname == '/fyg_index.php') {
let userData = getUserData();
let dataIndex = userData.dataIndex;
let waitForCol = setInterval(() => {
let colmd4 = document.getElementsByClassName('col-md-4');
if (colmd4?.length > 0 && colmd4[0]?.children?.length > 5) {
clearInterval(waitForCol);
let px = colmd4[0].children[5];
let p0 = document.createElement(px.tagName);
p0.innerText = '对玩家战斗(上次查看)';
p0.className = px.className;
let sp = document.createElement(px.children[0].tagName);
sp.className = px.children[0].className;
dataIndex.battleInfoNow = px.children[0].innerText;
if (dataIndex.battleInfoNow == dataIndex.battleInfoBefore) {
sp.innerText = dataIndex.battleInfoBack;
}
else {
sp.innerText = dataIndex.battleInfoBefore;
dataIndex.battleInfoBack = dataIndex.battleInfoBefore;
dataIndex.battleInfoBefore = dataIndex.battleInfoNow
setUserData(userData);
}
p0.appendChild(sp);
colmd4[0].appendChild(p0);
}
}, 200);
const USER_DATA_xPORT_SEPARATOR = '\n';
function importUserConfigData() {
genericPopupSetContent(
'导入内容',
`<b><div style="color:#0000c0;padding:15px 0px 10px;">
请将从其它系统中使用同一帐号导出的内容填入文本框中并执行导入操作</div></b>
<div style="height:330px;"><textarea id="user_data_persistence_string"
style="height:100%;width:100%;resize:none;"></textarea></div>`);
genericPopupAddButton(
'执行导入',
0,
(() => {
let userData = document.getElementById("user_data_persistence_string").value.split(USER_DATA_xPORT_SEPARATOR);
if (userData.length > 0) {
if (confirm('导入操作会覆盖已有的用户配置(护符组定义、卡片装备光环护符绑定、海滩装备筛选配置等等),要继续吗?')) {
let backup = [];
let importedItems = [];
let illegalItems = [];
g_userDataStorageKeyConfig.forEach((item, index) => {
backup[index] = localStorage.getItem(item);
});
userData.forEach((item) => {
if ((item = item.trim()).length > 0) {
let key = item.slice(0, item.indexOf(USER_STORAGE_KEY_VALUE_SEPARATOR));
if (g_userDataStorageKeyConfig.indexOf(key) >= 0) {
if (illegalItems.length == 0) {
localStorage.setItem(key, item.substring(key.length + 1));
importedItems.push(key);
}
}
else {
illegalItems.push(key);
}
}
});
if (illegalItems.length > 0) {
importedItems.forEach((item) => {
let index = g_userDataStorageKeyConfig.indexOf(item);
if (index >= 0 && backup[index] != null) {
localStorage.setItem(item, backup[index]);
}
else {
localStorage.removeItem(item);
}
});
alert('输入内容格式有误,有非法项目导致导入失败,请检查:\n [ ' + illegalItems.join(' ]\n [ ') + ' ]');
}
else if (importedItems.length > 0) {
alert('导入已完成:\n [ ' + importedItems.join(' ]\n [ ') + ' ]');
genericPopupClose(true);
window.location.reload();
}
else {
alert('输入内容格式有误,导入失败,请检查!');
}
}
}
else {
alert('输入内容格式有误,导入失败,请检查!');
}
}),
true);
genericPopupAddCloseButton(80);
genericPopupSetContentSize(400, 600, false);
genericPopupShowModal(true);
}
function exportUserConfigData() {
genericPopupSetContent(
'导出内容',
`<b><div id="user_data_export_tip" style="color:#0000c0;padding:15px 0px 10px;">
请勿修改任何导出内容,将其保存为纯文本在其它系统中使用相同的帐号执行导入操作</div></b>
<div style="height:330px;"><textarea id="user_data_persistence_string" readonly="true"
style="height:100%;width:100%;resize:none;"></textarea></div>`);
genericPopupAddButton(
'复制导出内容至剪贴板',
0,
(() => {
let tipContainer = document.getElementById('user_data_export_tip');
let tipColor = tipContainer.style.color;
let tipString = tipContainer.innerText;
tipContainer.style.color = '#ff0000';
document.querySelector('#user_data_persistence_string').select();
if (document.execCommand('copy')) {
tipContainer.innerText = '导出内容已复制到剪贴板';
}
else {
tipContainer.innerText = '复制失败,这可能是因为浏览器没有剪贴板访问权限,请进行手工复制(CTRL+A, CTRL+C)';
}
setTimeout((() => {
tipContainer.style.color = tipColor;
tipContainer.innerText = tipString;
}), 3000);
}),
true);
genericPopupAddCloseButton(80);
let userData = [];
g_userDataStorageKeyConfig.forEach((item) => {
let value = localStorage.getItem(item);
if (value != null) {
userData.push(`${item}${USER_STORAGE_KEY_VALUE_SEPARATOR}${value}`);
}
});
document.getElementById("user_data_persistence_string").value = userData.join(USER_DATA_xPORT_SEPARATOR);
genericPopupSetContentSize(400, 600, false);
genericPopupShowModal(true);
}
function clearUserData() {
if (confirm('这将清除所有用户配置(护符组定义、卡片装备光环护符绑定、海滩装备筛选配置等等)和数据,要继续吗?')) {
g_userDataStorageKeyConfig.concat(g_userDataStorageKeyExtra).forEach((item) => {
localStorage.removeItem(item);
});
alert('用户配置和数据已全部清除!');
window.location.reload();
}
}
let waitForUserd = setInterval(() => {
let userd = document.getElementById('userd');
if (userd?.children?.length > 0) {
clearInterval(waitForUserd);
let globalDataBtnContainer = document.createElement(userd.tagName);
globalDataBtnContainer.id = 'global-data-button-container';
globalDataBtnContainer.className = userd.className;
globalDataBtnContainer.style.borderTop = '2px solid #d0d0d0';
let versionLabel = document.createElement(userd.firstChild.tagName);
versionLabel.innerText = '插件版本:';
versionLabel.className = userd.firstChild.className;
let versionText = document.createElement(userd.firstChild.children[0].tagName);
versionText.className = userd.firstChild.children[0].className;
versionText.innerText = g_modificationVersion;
versionLabel.appendChild(versionText);
globalDataBtnContainer.appendChild(versionLabel);
let importBtn = document.createElement('button');
importBtn.innerHTML = '导入用户配置数据';
importBtn.style.height = '35px';
importBtn.style.width = '100%';
importBtn.style.marginBottom = '1px';
importBtn.onclick = (() => {
importUserConfigData();
});
globalDataBtnContainer.appendChild(importBtn);
let exportBtn = document.createElement('button');
exportBtn.innerHTML = '导出用户配置数据';
exportBtn.style.height = '35px';
exportBtn.style.width = '100%';
exportBtn.style.marginBottom = '1px';
exportBtn.onclick = (() => {
exportUserConfigData();
});
globalDataBtnContainer.appendChild(exportBtn);
let eraseBtn = document.createElement('button');
eraseBtn.innerHTML = '清除用户数据';
eraseBtn.style.height = '35px';
eraseBtn.style.width = '100%';
eraseBtn.onclick = (() => {
clearUserData();
});
globalDataBtnContainer.appendChild(eraseBtn);
userd.parentNode.appendChild(globalDataBtnContainer);
}
}, 200);
} else if (window.location.pathname == '/fyg_equip.php') {
let btnc1 = document.createElement('button');
let timeoutWaitForCard = 0;
btnc1.innerText = '导出计算器';
btnc1.onclick = () => {};
let waitForBackpacks = setInterval(() => {
if (document.getElementById('backpacks')?.children?.length > 0) {
clearInterval(waitForBackpacks);
wishExpireTip();
let div00 = document.createElement('div');
div00.id = 'equipmentDiv';
div00.innerHTML =
`<p><div style="padding:0px 0px 10px 15px;float:right;"><label for="equipment_BG" style="margin-right:5px;">使用深色背景</label>
<input type="checkbox" id="equipment_BG" /></div></p>
<p><button type="button" class="btn btn-block collapsed" data-toggle="collapse" data-target="#eq4">护符
<i class="icon icon-caret-down"></i></button></p>
<div class="in" id="eq4"></div>
<p><button type="button" class="btn btn-block collapsed" data-toggle="collapse" data-target="#eq0">武器装备
<i class="icon icon-caret-down"></i></button></p>
<div class="in" id="eq0"></div>
<p><button type="button" class="btn btn-block collapsed" data-toggle="collapse" data-target="#eq1">手臂装备
<i class="icon icon-caret-down"></i></button></p>
<div class="in" id="eq1"></div>
<p><button type="button" class="btn btn-block collapsed" data-toggle="collapse" data-target="#eq2">身体装备
<i class="icon icon-caret-down"></i></button></p>
<div class="in" id="eq2"></div>
<p><button type="button" class="btn btn-block collapsed" data-toggle="collapse" data-target="#eq3">头部装备
<i class="icon icon-caret-down"></i></button></p>
<div class="in" id="eq3"></div>
<p><button type="button" id="collapse-backpacks-store" class="btn btn-block collapsed">仓库
<i class="icon icon-caret-down"></i></button></p>`;
function changeEquipmentDivStyle() {
$('#equipmentDiv .backpackDiv').css({
'background-color': equipmentBG ? 'black' : '#ffe5e0'
});
$('#equipmentDiv .storeDiv').css({
'background-color': equipmentBG ? 'black' : '#ddf4df'
});
$('#equipmentDiv .btn-light').css({
'background-color': equipmentBG ? 'black' : 'white'
});
$('#equipmentDiv .popover-content-show').css({
'background-color': equipmentBG ? 'black' : 'white'
});
$('#equipmentDiv .popover-title').css({
'color': equipmentBG ? 'black' : 'white'
});
$('#equipmentDiv .bg-special').css({
'background-color': equipmentBG ? 'black' : '#8666b8',
'color': equipmentBG ? '#c0c0c0' : 'white',
'border-bottom': equipmentBG ? '1px solid grey' : 'none'
});
$('#equipmentDiv .btn-equipment .pull-right').css({
'color': equipmentBG ? 'black' : 'white'
});
$('#equipmentDiv .btn-equipment .bg-danger.with-padding').css({
'color': equipmentBG ? 'black' : 'white'
});
}
let equipmentBG = div00.querySelector('#equipment_BG').checked = (localStorage.getItem(g_equipmentBGStorageKey) == 'true');
div00.querySelector('#equipment_BG').addEventListener(
'click',
() => {
localStorage.setItem(g_equipmentBGStorageKey, equipmentBG = document.querySelector('#equipment_BG').checked);
changeEquipmentDivStyle();
},
false);
let eqbtns = null;
function addCollapse() {
let waitForBtn = setInterval(() => {
if (document.getElementById('carding')?.innerText?.indexOf('读取中') < 0 &&
document.getElementById('backpacks')?.innerText?.indexOf('读取中') < 0) {
eqbtns = document.querySelector("#carding > div.row > div.fyg_tc")?.children;
if (eqbtns?.length > 0 && eqbtns[0].className.endsWith('fyg_mp3')) {
clearInterval(waitForBtn);
let eqstore = document.querySelector("#backpacks > div.alert-success > div.content").querySelectorAll(".fyg_mp3");
for (let i = 0; i < eqstore.length; i++) {
if (eqstore[i].className.split(' ').length == 3) {
eqstore[i].dataset.instore = 1;
}
}
eqbtns =
Array.from(eqbtns).concat(
Array.from(document.querySelector("#backpacks > div.alert-danger > div.content")
.querySelectorAll(".fyg_mp3")).sort(sortEqByName)).concat(
Array.from(eqstore).sort(sortEqByName));
for (let i = eqbtns.length - 1; i >= 0; i--) {
if (eqbtns[i].className.split(' ').length != 3) {
eqbtns.splice(i, 1);
}
}
if (!(document.getElementsByClassName('collapsed')?.length > 0)) {
document.getElementById('backpacks')
.insertBefore(div00, document.getElementById('backpacks').firstChild.nextSibling);
}
for (let i = eqbtns.length - 1; i >= 0; i--) {
if (eqbtns[i].className.split(' ')[0] == 'popover') {
eqbtns.splice(i, 1);
break;
}
}
let ineqBackpackDiv =
`<div class="backpackDiv" style="padding:10px;margin-bottom:10px;"></div>` +
`<div class="storeDiv" style="padding:10px;"></div>`;
let eqDivs = [ div00.querySelector('#eq0'),
div00.querySelector('#eq1'),
div00.querySelector('#eq2'),
div00.querySelector('#eq3'),
div00.querySelector('#eq4') ];
eqDivs.forEach((item) => { item.innerHTML = ineqBackpackDiv; });
let ineq = 0;
for (let i = 0; i < eqbtns.length; i++) {
if (eqbtns[i].innerText == '空') {
continue;
}
let btn0 = document.createElement('button');
btn0.className = 'btn btn-light';
btn0.style.minWidth = '200px';
btn0.style.marginRight = '5px';
btn0.style.marginBottom = '5px';
btn0.style.padding = '0px';
btn0.style.textAlign = 'left';
btn0.style.boxShadow = 'none';
btn0.style.lineHeight = '150%';
btn0.style.borderColor = getComputedStyle(eqbtns[i]).getPropertyValue('background-color');
btn0.setAttribute('onclick', eqbtns[i].getAttribute('onclick'));
let storeText = '';
if (eqbtns[i].dataset.instore == 1) {
storeText = '【仓】';
}
let enhancements = eqbtns[i].innerText;
if (enhancements.indexOf('+') == -1) {
enhancements = '';
}
btn0.innerHTML =
`<h3 class="popover-title" style="color:white;background-color: ${btn0.style.borderColor}">
${storeText}${eqbtns[i].dataset.originalTitle}${enhancements}</h3>
<div class="popover-content-show" style="padding:10px 10px 0px 10px;">${eqbtns[i].dataset.content}</div>`;
if (btn0.children[1].lastChild.nodeType == 3) { //清除背景介绍文本
btn0.children[1].lastChild.remove();
}
if (eqbtns[i].innerText.indexOf('+') >= 0) {
ineq = 4;
}
else {
let a = parseInt(eqbtns[i].dataset.abbr);
if (isNaN(a)) {
let title1 = (eqbtns[i].getAttribute('data-original-title') ?? eqbtns[i].getAttribute('title'));
a = sortdict[eqToAbbr(title1.substr(title1.lastIndexOf('>') + 1))];
}
if (a >= sortdict.BOUND_0 && a < sortdict.BOUND_1) {
ineq = 1;
}
else if (a >= sortdict.BOUND_1 && a < sortdict.BOUND_2) {
ineq = 2;
}
else if (a >= sortdict.BOUND_2) {
ineq = 3;
}
else {
ineq = 0;
}
btn0.className += ' btn-equipment';
}
(storeText == '' ? eqDivs[ineq].firstChild : eqDivs[ineq].firstChild.nextSibling).appendChild(btn0);
}
function inputAmuletGroupName(defaultGroupName) {
let groupName = prompt('请输入护符组名称(不超过31个字符,请仅使用大、小写英文字母、数字、连字符、下划线及中文字符):',
defaultGroupName);
if (amuletIsValidGroupName(groupName)) {
return groupName;
}
else if (groupName != null) {
alert('名称不符合命名规则,信息未保存。');
}
return null;
}
function refreshEquipmentPage(fnFurtherProcess) {
let asyncOperations = 1;
let asyncObserver = new MutationObserver(() => { asyncObserver.disconnect(); asyncOperations = 0; });
asyncObserver.observe(document.getElementById('backpacks'), { childList : true, subtree : true });
unsafeWindow.eqlip(1);
unsafeWindow.eqbp(1);
let timer = setInterval(() => {
if (asyncOperations == 0) {
clearInterval(timer);
genericPopupClose(true);
if (fnFurtherProcess != null) {
fnFurtherProcess();
}
}
}, 200);
}
function queryAmulets(bag, store) {
let count = 0;
if (bag != null) {
amuletNodesToArray(document.querySelector("#backpacks > div.alert-danger > div.content")
.querySelectorAll(".fyg_mp3"), bag);
count += bag.length;
}
if (store != null) {
amuletNodesToArray(document.querySelector("#backpacks > div.alert-success > div.content")
.querySelectorAll(".fyg_mp3"), store);
count += store.length;
}
return count;
}
function showAmuletGroupsPopup() {
function beginSaveBagAsGroup(groupName, update) {
let amulets = [];
queryAmulets(amulets, null);
createAmuletGroup(groupName, amulets, update);
showAmuletGroupsPopup();
}
genericPopupClose(true);
let bag = [];
let store = [];
if (queryAmulets(bag, store) == 0) {
alert('护符信息加载异常,请检查!');
refreshEquipmentPage(null);
return;
}
let amulets = bag.concat(store);
let bagGroup = amuletCreateGroupFromArray('当前背包', bag);
let groups = amuletLoadGroups();
if (bagGroup == null && groups.count() == 0) {
alert('背包为空,且未找到预保存的护符组信息!');
return;
}
genericPopupSetContent('护符组管理', '<div id="popup_amulet_groups" style="margin-top:15px;"></div>');
let amuletContainer = document.getElementById('popup_amulet_groups');
if (bagGroup != null) {
let err = !bagGroup.validate(bag);
let groupDiv = document.createElement('div');
groupDiv.className = g_genericPopupTopLineDivClass;
groupDiv.id = 'popup_amulet_group_bag';
groupDiv.innerHTML =
`<b id="popup_amulet_group_bag_name" style="color:${err ? "red" : "blue"};
font-size:20px;">当前背包内容 [${bagGroup.count()}]</b>`;
let saveBagGroupBtn = document.createElement('button');
saveBagGroupBtn.innerText = '保存为护符组';
saveBagGroupBtn.style.float = 'right';
saveBagGroupBtn.onclick = (() => {
let groupName = inputAmuletGroupName('');
if (groupName != null) {
beginSaveBagAsGroup(groupName, false);
}
});
groupDiv.appendChild(saveBagGroupBtn);
let groupInfoDiv = document.createElement('div');
groupInfoDiv.innerHTML =
`<hr><ul style="color:#000080;">${bagGroup.formatBuffSummary('<li>', '</li>', '')}</ul>
<hr><ul>${bagGroup.formatItems('<li>', '<li style="color:red;">', '</li>', '</li>', '')}<ul>`;
groupDiv.appendChild(groupInfoDiv);
amuletContainer.appendChild(groupDiv);
}
let li = 0
let groupArray = groups.toArray();
let gl = (groupArray?.length ?? 0);
if (gl > 0) {
groupArray = groupArray.sort((a, b) => a.name < b.name ? -1 : 1);
for (let i = 0; i < gl; i++) {
let err = !groupArray[i].validate(amulets);
let groupDiv = document.createElement('div');
groupDiv.className = g_genericPopupTopLineDivClass;
groupDiv.id = 'popup_amulet_group_' + i;
groupDiv.innerHTML =
`<b id="popup_amulet_group_${i}_name" style="color:${err ? "red" : "blue"};
font-size:20px;">${groupArray[i].name} [${groupArray[i].count()}]</b>`;
let amuletDeleteGroupBtn = document.createElement('button');
amuletDeleteGroupBtn.innerText = '删除';
amuletDeleteGroupBtn.style.float = 'right';
amuletDeleteGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
if (confirm(`删除护符组 "${groupName}" 吗?`)) {
amuletDeleteGroup(groupName);
showAmuletGroupsPopup();
}
});
groupDiv.appendChild(amuletDeleteGroupBtn);
let amuletModifyGroupBtn = document.createElement('button');
amuletModifyGroupBtn.innerText = '编辑';
amuletModifyGroupBtn.style.float = 'right';
amuletModifyGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
modifyAmuletGroup(groupName);
});
groupDiv.appendChild(amuletModifyGroupBtn);
let importAmuletGroupBtn = document.createElement('button');
importAmuletGroupBtn.innerText = '导入';
importAmuletGroupBtn.style.float = 'right';
importAmuletGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
let persistenceString = prompt('请输入护符组编码(一般由工具软件自动生成,表现形式为一组由逗号分隔的数字序列)');
if (persistenceString != null) {
let group = new AmuletGroup(`${groupName}${AMULET_STORAGE_GROUPNAME_SEPARATOR}${persistenceString}`);
if (group.isValid()) {
let groups = amuletLoadGroups();
if (groups.add(group)) {
amuletSaveGroups(groups);
showAmuletGroupsPopup();
}
else {
alert('保存失败!');
}
}
else {
alert('输入的护符组编码无效,请检查!');
}
}
});
groupDiv.appendChild(importAmuletGroupBtn);
let renameAmuletGroupBtn = document.createElement('button');
renameAmuletGroupBtn.innerText = '更名';
renameAmuletGroupBtn.style.float = 'right';
renameAmuletGroupBtn.onclick = (() => {
let oldName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
let groupName = inputAmuletGroupName(oldName);
if (groupName != null && groupName != oldName) {
let groups = amuletLoadGroups();
if (!groups.contains(groupName) || confirm(`护符组 "${groupName}" 已存在,要覆盖吗?`)) {
if (groups.rename(oldName, groupName)) {
amuletSaveGroups(groups);
showAmuletGroupsPopup();
}
else {
alert('更名失败!');
}
}
}
});
groupDiv.appendChild(renameAmuletGroupBtn);
let updateAmuletGroupBtn = document.createElement('button');
updateAmuletGroupBtn.innerText = '更新';
updateAmuletGroupBtn.style.float = 'right';
updateAmuletGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
if (confirm(`用当前背包内容替换 "${groupName}" 护符组预定内容吗?`)) {
beginSaveBagAsGroup(groupName, true);
}
});
groupDiv.appendChild(updateAmuletGroupBtn);
let unamuletLoadGroupBtn = document.createElement('button');
unamuletLoadGroupBtn.innerText = '入仓';
unamuletLoadGroupBtn.style.float = 'right';
unamuletLoadGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
genericPopupShowProgressMessage('卸载中,请稍候…');
beginUnloadAmuletGroupFromBag(groupName, refreshEquipmentPage, showAmuletGroupsPopup);
});
groupDiv.appendChild(unamuletLoadGroupBtn);
let amuletLoadGroupBtn = document.createElement('button');
amuletLoadGroupBtn.innerText = '装备';
amuletLoadGroupBtn.style.float = 'right';
amuletLoadGroupBtn.onclick = (() => {
let groupName = document.getElementById(`popup_amulet_group_${i}_name`).innerText.split(' ')[0];
genericPopupShowProgressMessage('加载中,请稍候…');
beginLoadAmuletGroupFromStore(groupName, refreshEquipmentPage, showAmuletGroupsPopup);
});
groupDiv.appendChild(amuletLoadGroupBtn);
let groupInfoDiv = document.createElement('div');
groupInfoDiv.innerHTML =
`<hr><ul style="color:#000080;">${groupArray[i].formatBuffSummary('<li>', '</li>', '')}</ul>
<hr><ul>${groupArray[i].formatItems('<li>', '<li style="color:red;">', '</li>', '</li>', '')}<ul>`;
groupDiv.appendChild(groupInfoDiv);
amuletContainer.appendChild(groupDiv);
li += groupArray[i].getDisplayStringLineCount();
}
}
if (bagGroup != null) {
gl++;
li += bagGroup.getDisplayStringLineCount();
}
genericPopupAddButton('新建护符组', 0, (() => { modifyAmuletGroup(null); }), true);
genericPopupAddButton(
'导入新护符组',
0,
(() => {
let groupName = inputAmuletGroupName('');
if (groupName != null) {
let persistenceString = prompt('请输入护符组编码(一般由工具软件自动生成,表现形式为一组由逗号分隔的数字序列)');
if (persistenceString != null) {
let group = new AmuletGroup(`${groupName}${AMULET_STORAGE_GROUPNAME_SEPARATOR}${persistenceString}`);
if (group.isValid()) {
let groups = amuletLoadGroups();
if (!groups.contains(groupName) || confirm(`护符组 "${groupName}" 已存在,要覆盖吗?`)) {
if (groups.add(group)) {
amuletSaveGroups(groups);
showAmuletGroupsPopup();
}
else {
alert('保存失败!');
}
}
}
else {
alert('输入的护符组编码无效,请检查!');
}
}
}
}),
true);
genericPopupAddButton(
'清空背包',
0,
(() => {
genericPopupShowProgressMessage('处理中,请稍候…');
beginClearBag(refreshEquipmentPage, showAmuletGroupsPopup);
}),
true);
genericPopupAddCloseButton(80);
genericPopupSetContentSize(Math.min((li * 20) + (gl * 160) + 60, Math.max(unsafeWindow.innerHeight - 200, 400)),
Math.min(1000, Math.max(unsafeWindow.innerWidth - 100, 600)),
true);
genericPopupShowModal(true);
}
function modifyAmuletGroup(groupName) {
function refreshAmuletListDivHeight() {
let amuletListDiv = amuletList.parentNode;
amuletListDiv.style.height
= (amuletListDiv.parentNode.offsetHeight - amuletListDiv.offsetTop - 3) + 'px';
}
function refreshGroupAmuletListDivHeight() {
let groupAmuletListDiv = groupAmuletList.parentNode;
groupAmuletListDiv.style.height
= (groupAmuletListDiv.parentNode.offsetHeight - groupAmuletListDiv.offsetTop - 3) + 'px';
}
function refreshAmuletList() {
let type = amuletFilterList.value;
amuletList.innerHTML = '';
for (let am of amulets) {
if (type == -1 || am.type == type) {
let item = document.createElement('li');
item.setAttribute('original-id', am.id);
item.innerText = am.formatBuffText();
amuletList.appendChild(item);
}
}
}
function refreshGroupAmuletSummary() {
let count = group.count();
if (count > 0) {
groupSummary.innerHTML = group.formatBuffSummary('<li>', '</li>', '');
groupSummary.style.display = 'block';
}
else {
groupSummary.style.display = 'none';
groupSummary.innerHTML = '';
}
refreshGroupAmuletListDivHeight();
amuletCount.innerText = count;
}
function refreshGroupAmuletList() {
groupAmuletList.innerHTML = '';
for (let am of group.items) {
if (am.id >= 0) {
let item = document.createElement('li');
item.setAttribute('original-id', am.id);
item.innerText = am.formatBuffText();
groupAmuletList.appendChild(item);
}
}
}
function refreshGroupAmuletDiv() {
refreshGroupAmuletSummary();
refreshGroupAmuletList();
}
function moveAmuletItem(e) {
let li = e.target;
if (li.tagName == 'LI') {
let from = li.parentNode;
let id = li.getAttribute('original-id');
from.removeChild(li);
if (from == amuletList) {
let i = searchElement(amulets, id, (a, b) => a - b.id);
let am = amulets[i];
amulets.splice(i, 1);
groupAmuletList.insertBefore(li, groupAmuletList.children.item(group.add(am)));
}
else {
let am = group.removeId(id);
insertElement(amulets, am, (a, b) => a.id - b.id);
let type = amuletFilterList.value;
if (type < 0 || am.type == type) {
for (var item = amuletList.firstChild;
item?.getAttribute('original-id') <= am.id;
item = item.nextSibling);
amuletList.insertBefore(li, item);
}
}
refreshGroupAmuletSummary();
groupChanged = true;
}
}
let bag = [];
let store = [];
if (queryAmulets(bag, store) == 0) {
alert('获取护符信息失败,请检查!');
return;
}
let amulets = bag.concat(store).sort((a, b) => a.compareTo(b));
amulets.forEach((e, i) => { e.id = i; });
let displayName = groupName;
if (!amuletIsValidGroupName(displayName)) {
displayName = '(未命名)';
groupName = null;
}
else if (displayName.length > 20) {
displayName = displayName.slice(0, 19) + '…';
}
let groupChanged = false;
let group = amuletLoadGroup(groupName);
if (!group?.isValid()) {
group = new AmuletGroup(null);
group.name = '(未命名)';
groupName = null;
}
else {
group.validate(amulets);
while (group.removeId(-1) != null) {
groupChanged = true;
}
for (let am of group.items) {
let i = searchElement(amulets, am, (a, b) => a.id - b.id);
if (i >= 0) {
amulets.splice(i, 1);
}
}
}
genericPopupClose(true);
let fixedConent =
'<br><b><span style="margin-left:10px;font-size:18px;color:blue;">双击护符条目以进行添加或移除操作</span>' +
'<span style="margin-right:10px;font-size:18px;color:blue;float:right;">共 ' +
'<span id="amulet_count" style="color:#800020;">0</span> 个护符</span></b>';
let mainContent =
'<style> ul > li:hover { background-color:#bbddff; } </style>' +
'<div style="display:block;height:100%;width:100%;">' +
'<div style="position:relative;display:block;float:left;height:96%;width:49%;' +
'margin-top:10px;border:1px solid #000000;">' +
'<div style="display:block;width:100%;padding:10px 10px;border-bottom:2px groove #d0d0d0;' +
'margin-bottom:10px;">' +
'<select id="amulet_filter" style="display:inline;width:100%;color:blue;text-align:center;">' +
'</select>' +
'</div>' +
'<div style="position:absolute;display:block;height:1px;width:100%;overflow:scroll;">' +
'<ul id="amulet_list" style="cursor:pointer;"></ul>' +
'</div>' +
'</div>' +
'<div style="position:relative;display:block;float:right;height:96%;width:49%;' +
'margin-top:10px;border:1px solid #000000;">' +
'<div id="group_summary" style="display:block;width:100%;padding:10px 5px;' +
'border-bottom:2px groove #d0d0d0;color:#000080;margin-bottom:10px;"></div>' +
'<div style="position:absolute;display:block;height:1px;width:100%;overflow:scroll;">' +
'<ul id="group_amulet_list" style="cursor:pointer;"></ul>' +
'</div>' +
'</div>' +
'</div>';
genericPopupSetFixedContent(fixedConent);
genericPopupSetContent('编辑护符组 - ' + displayName, mainContent);
let amuletCount = document.getElementById('amulet_count');
let amuletFilterList = document.getElementById('amulet_filter');
let amuletList = document.getElementById('amulet_list');
let groupSummary = document.getElementById('group_summary');
let groupAmuletList = document.getElementById('group_amulet_list');
let op = document.createElement('option');
op.value = -1;
op.innerText = '全部护符类型';
amuletFilterList.appendChild(op);
for (let amuletType in g_amuletTypeIds) {
op = document.createElement('option');
op.value = g_amuletTypeIds[amuletType];
op.innerText = amuletType;
amuletFilterList.appendChild(op);
}
refreshAmuletList();
refreshGroupAmuletDiv();
amuletFilterList.addEventListener('change', refreshAmuletList, false);
amuletList.addEventListener('dblclick', moveAmuletItem, false);
groupAmuletList.addEventListener('dblclick', moveAmuletItem, false);
genericPopupAddButton(
'清空护符组',
0,
(() => {
if (group.count() > 0) {
for (let am of group.items) {
insertElement(amulets, am, (a, b) => a.id - b.id);
}
group.clear();
refreshAmuletList();
refreshGroupAmuletDiv();
groupChanged = true;
}
}),
true);
if (amuletIsValidGroupName(groupName)) {
genericPopupAddButton(
'另存为',
80,
(() => {
if (!group.isValid()) {
alert('护符组内容存在错误,请检查!');
return;
}
let gn = inputAmuletGroupName(groupName);
if (gn == null) {
return;
}
let groups = amuletLoadGroups();
if (groups.contains(gn) && !confirm(`护符组 "${gn}" 已存在,要覆盖吗?`)) {
return;
}
group.name = gn;
if (groups.add(group)) {
amuletSaveGroups(groups);
showAmuletGroupsPopup();
}
else {
alert('保存失败!');
}
}),
false);
}
genericPopupAddButton(
'确认',
80,
(() => {
if (!groupChanged && group.isValid()) {
showAmuletGroupsPopup();
return;
}
else if (!group.isValid()) {
alert('护符组内容存在错误,请检查!');
return;
}
let groups = amuletLoadGroups();
if (!amuletIsValidGroupName(groupName)) {
let gn = inputAmuletGroupName(displayName);
if (gn == null || (groups.contains(gn) && !confirm(`护符组 "${gn}" 已存在,要覆盖吗?`))) {
return;
}
group.name = gn;
}
if (groups.add(group)) {
amuletSaveGroups(groups);
showAmuletGroupsPopup();
}
else {
alert('保存失败!');
}
}),
false);
genericPopupAddButton(
'取消',
80,
(() => {
if (!groupChanged || confirm('护符组内容已修改,不保存吗?')) {
showAmuletGroupsPopup();
}
}),
false);
genericPopupSetContentSize(Math.min(800, Math.max(unsafeWindow.innerHeight - 200, 500)),
Math.min(1000, Math.max(unsafeWindow.innerWidth - 100, 600)),
false);
genericPopupShowModal(false);
refreshAmuletListDivHeight();
refreshGroupAmuletListDivHeight();
}
function createAmuletGroup(groupName, amulets, update) {
let group = amuletCreateGroupFromArray(groupName, amulets);
if (group != null) {
let groups = amuletLoadGroups();
if (update || !groups.contains(groupName) || confirm(`护符组 "${groupName}" 已存在,要覆盖吗?`)) {
if (groups.add(group)) {
amuletSaveGroups(groups);
genericPopupClose(true);
return true;
}
else {
alert('保存失败!');
}
}
}
else {
alert('保存异常,请检查!');
}
genericPopupClose(true);
return false;
}
function formatAmuletsString() {
let bag = [];
let store = [];
let exportLines = [];
if (queryAmulets(bag, store) > 0) {
let amulets = bag.concat(store).sort((a, b) => a.compareTo(b));
let amuletIndex = 1;
for (let amulet of amulets) {
exportLines.push(`${('00' + amuletIndex).slice(-3)} - ${amulet.formatShortMark()}`);
amuletIndex++;
}
}
return (exportLines.length > 0 ? exportLines.join('\n') : '');
}
function exportAmulets() {
genericPopupSetContent(
'护符导出',
`<b><div id="amulet_export_tip" style="color:#0000c0;padding:15px 0px 10px;">
请勿修改任何导出内容,将其保存为纯文本在其它相应工具中使用</div></b>
<div style="height:330px;"><textarea id="amulet_persistence_string" readonly="true"
style="height:100%;width:100%;resize:none;"></textarea></div>`);
genericPopupAddButton(
'复制导出内容至剪贴板',
0,
(() => {
let tipContainer = document.getElementById('amulet_export_tip');
let tipColor = tipContainer.style.color;
let tipString = tipContainer.innerText;
tipContainer.style.color = '#ff0000';
document.querySelector('#amulet_persistence_string').select();
if (document.execCommand('copy')) {
tipContainer.innerText = '导出内容已复制到剪贴板';
}
else {
tipContainer.innerText = '复制失败,这可能是因为浏览器没有剪贴板访问权限,请进行手工复制(CTRL+A, CTRL+C)';
}
setTimeout((() => {
tipContainer.style.color = tipColor;
tipContainer.innerText = tipString;
}), 3000);
}),
true);
genericPopupAddCloseButton(80);
document.getElementById("amulet_persistence_string").value = formatAmuletsString();
genericPopupSetContentSize(400, 600, false);
genericPopupShowModal(true);
}
let amuletButtonsGroupContainer = document.getElementById('amulet_management_btn_group');
if (amuletButtonsGroupContainer == null) {
amuletButtonsGroupContainer = document.createElement('div');
amuletButtonsGroupContainer.id = 'amulet_management_btn_group';
amuletButtonsGroupContainer.style.width = '100px';
amuletButtonsGroupContainer.style.float = 'right';
amuletButtonsGroupContainer.style.marginTop = '10px';
document.getElementById('backpacks').children[0].appendChild(amuletButtonsGroupContainer);
let exportAmuletsBtn = document.createElement('button');
exportAmuletsBtn.innerText = '导出护符';
exportAmuletsBtn.style.width = '100%';
exportAmuletsBtn.style.marginBottom = '1px';
exportAmuletsBtn.onclick = (() => {
exportAmulets();
});
amuletButtonsGroupContainer.appendChild(exportAmuletsBtn);
let beginClearBagBtn = document.createElement('button');
beginClearBagBtn.innerText = '清空背包';
beginClearBagBtn.style.width = '100%';
beginClearBagBtn.style.marginBottom = '1px';
beginClearBagBtn.onclick = (() => {
genericPopupShowProgressMessage('处理中,请稍候…');
beginClearBag(refreshEquipmentPage, null);
});
amuletButtonsGroupContainer.appendChild(beginClearBagBtn);
let amuletSaveGroupBtn = document.createElement('button');
amuletSaveGroupBtn.innerText = '存为护符组';
amuletSaveGroupBtn.style.width = '100%';
amuletSaveGroupBtn.style.marginBottom = '1px';
amuletSaveGroupBtn.onclick = (() => {
let groupName = inputAmuletGroupName('');
if (groupName != null) {
let amulets = [];
if (queryAmulets(amulets, null) == 0) {
alert('保存失败,请检查背包内容!');
}
else if (createAmuletGroup(groupName, amulets, false)) {
alert('保存成功。');
}
}
});
amuletButtonsGroupContainer.appendChild(amuletSaveGroupBtn);
let manageAmuletGroupBtn = document.createElement('button');
manageAmuletGroupBtn.innerText = '管理护符组';
manageAmuletGroupBtn.style.width = '100%';
manageAmuletGroupBtn.style.marginBottom = '1px';
manageAmuletGroupBtn.onclick = (() => {
genericPopupInitialize();
showAmuletGroupsPopup();
});
amuletButtonsGroupContainer.appendChild(manageAmuletGroupBtn);
let clearAmuletGroupBtn = document.createElement('button');
clearAmuletGroupBtn.innerText = '清除护符组';
clearAmuletGroupBtn.style.width = '100%';
clearAmuletGroupBtn.onclick = (() => {
if (confirm('要删除全部已保存的护符组信息吗?')) {
amuletClearGroups();
alert('已删除全部预定义护符组信息。');
}
});
amuletButtonsGroupContainer.appendChild(clearAmuletGroupBtn);
document.getElementById('collapse-backpacks-store').onclick = (() => {
if ($('#backpacks > div.alert.alert-success.with-icon').css('display') == 'none') {
$('#backpacks > div.alert.alert-success.with-icon').show();
} else {
$('#backpacks > div.alert.alert-success.with-icon').hide();
}
});
}
$('#equipmentDiv .btn-equipment .bg-danger.with-padding').css({
'max-width': '200px',
'padding': '5px 5px 5px 5px',
'white-space': 'pre-line',
'word-break': 'break-all'
});
changeEquipmentDivStyle();
}
}
}, 500);
}
if (document.getElementsByClassName('nav nav-secondary nav-justified')[0].children[0].className == 'active') {
addCollapse();
}
const g_bindingPopupLinkId = 'binding_popup_link';
const g_cardOnekeyLinkId = 'card_one_key_link';
const g_bindingSolutionId = 'binding_solution_div';
const g_bindingListSelectorId = 'binding_list_selector';
const g_equipOnekeyLinkId = 'equip_one_key_link';
function switchCardTemporarily(roleId) {
let role = roleMap.get(roleId);
if (role == undefined) {
return;
}
genericPopupInitialize();
genericPopupShowProgressMessage('正在切换,请稍候…');
const upcard_data = getPostData(/upcard\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1);
const halosave_data = getPostData(/halosave\(\)\{[\s\S]*\}/m, /data: ".*\+savearr\+.*"/).slice(7, -1);
let roleInfo = [];
let haloInfo = [];
beginReadRoleAndHalo(roleInfo, haloInfo, switchToTempCard, null);
function switchCardCompletion() {
genericPopupClose(true);
window.location.reload();
}
function switchToTempCard() {
if (roleInfo.length == 2 && haloInfo.length == 3) {
const infoHTML =
`<div style="display:block;width:100%;color:#0000c0;text-align:center;font-size:20px;padding-top:50px;"><b>
<p></p><span style="width:100%;">当前卡片已经由 [ ${roleInfo[1]} ] 临时切换至 [ ${roleMap.get(roleId)?.name ?? 'UNKNOW'} ]</span><br><br>
<p></p><span style="width:100%;">请切换至搜刮页面尽快完成搜刮操作</span><br><br>
<p></p><span style="width:100%;">并返回本页面点击“恢复”按钮以恢复之前的卡片和光环设置</span></b></div>`;
genericPopupSetContent(`临时装备卡片 [ ${roleMap.get(roleId)?.name ?? 'UNKNOW'} ]`, infoHTML);
genericPopupSetContentSize(300, 600, false);
genericPopupAddButton('恢复', 80, restoreCardAndHalo, false);
switchCard(roleId, null, genericPopupShowModal, false);
}
else {
alert('无法读取当前装备卡片和光环信息,卡片未切换!');
switchCardCompletion();
}
}
function restoreCardAndHalo() {
genericPopupShowProgressMessage('正在恢复,请稍候…');
switchCard(roleInfo[0], haloInfo[2], switchCardCompletion, null);
}
function switchCard(newRoleId, newHaloArray, fnFurtherProcess, fnParams) {
let cardData = upcard_data.replace('"+id+"', newRoleId);
GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: cardData,
onload: response => {
if (response.responseText == 'ok' || response.responseText == '你没有这张卡片或已经装备中') {
if (newHaloArray?.length > 0) {
let haloData = halosave_data.replace('"+savearr+"', newHaloArray.join());
GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: haloData,
onload: response => {
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
});
return;
}
}
else {
alert('无法完成卡片和光环切换,请尝试手动进行!');
switchCardCompletion();
return;
}
if (fnFurtherProcess != null) {
fnFurtherProcess(fnParams);
}
}
});
}
}
function equipOnekey() {
function sendEquipHttpRequest(eqinfo) {
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div0 = readEquipmentDOM(response.responseText);
let equipment = getEquipmentInfo(div0.children);
let ids = new Array();
for (let i = 0; i < eqinfo.length; i++) {
for (let j = 0; j < equipment.length; j++) {
if (eqinfo[i] == equipment[j].slice(0, -2).join()) {
ids.push(equipment[j]);
break;
}
}
}
let c = ids.length;
let puton_data = getPostData(/puton\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1);
for (let i = 0; i < ids.length; i++) {
request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: puton_data.replace('"+id+"', ids[i][ids[i].length - 1]),
onload: response => {
if (!(g_equipmentOperationError = (response.responseText != 'ok'))) {
c--;
if (c == 0) {
beginLoadAmulets();
}
}
}
});
httpRequestRegister(request);
}
}
});
httpRequestRegister(request);
}
function sendBeginEquipHttpRequest(bind_info) {
let isStore = false;
genericPopupTaskSetState(0, '');
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div0 = readEquipmentDOM(response.responseText);
let equipment = getEquipmentInfo(div0.children);
let equiped = getEquipmentInfo(document.querySelector("#carding > div.row > div.fyg_tc")?.children);
let ids = new Array();
let err = 0;
for (let i = 0; i < 4; i++) {
let exist = 0;
for (let j = 0; j < 4; j++) {
if (bind_info[i] == equiped[j].slice(0, -2).join()) { //已装备
exist = 1;
break;
}
}
if (exist == 0) { //未装备
for (let j = 0; j < equipment.length; j++) {
if (bind_info[i] == equipment[j].slice(0, -2).join()) {
ids.push(equipment[j]);
exist = 1;
break;
}
}
if (exist == 0) {
console.log(bind_info[i]);
alert('有装备不存在,请重新绑定');
err = 1;
window.location.reload();
}
}
}
if (err == 0) {
let c = ids.length;
if (c == 0) {
beginLoadAmulets();
}
let puton_data = getPostData(/puton\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1);
let puto_data = 'c=22' + puton_data.slice(3);
let storeCount = 0;
let storePuton = new Array();
for (let i = 0; i < ids.length; i++) {
request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: puton_data.replace('"+id+"', ids[i][ids[i].length - 1]),
onload: response => {
if (!(g_equipmentOperationError = (response.responseText != 'ok'))) {
c--;
if (c == 0 && !isStore) {
beginLoadAmulets();
} else if (c == 0 && isStore) {
request = sendEquipHttpRequest(storePuton);
}
} else if (response.responseText == '这不是你的装备') {
let item = ids[i].slice(0, -1);
item = new Array(fullNameOf[item[0]], `Lv${item[1]}`, `${item[2]}%`, `${item[3]}%`, `${item[4]}%`, `${item[5]}%`, `${item[6] == 1 ? '神秘' : ''}`).join(' ');
storeCount++;
genericPopupTaskSetState(0, '- 取出仓库……');
request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: puto_data.replace('"+id+"', ids[i][ids[i].length - 1]),
onload: response => {
if (!(g_equipmentOperationError = (response.responseText != 'ok'))) {
g_equipmentFromStoreCount++;
storeCount--;
if (storeCount == 0) {
genericPopupTaskSetState(0, '');
}
isStore = true;
storePuton.push(ids[i].slice(0, 6));
c--;
if (c == 0) {
request = sendEquipHttpRequest(storePuton);
}
} else if (response.responseText == '背包已满。') {
alert(`背包已满,仓库装备\n${item}\n无法取出,请整理背包`);
c--;
if (c == 0 && !isStore) {
beginLoadAmulets();
} else if (c == 0 && isStore) {
request = sendEquipHttpRequest(storePuton);
}
}
}
});
httpRequestRegister(request);
}
}
});
httpRequestRegister(request);
}
}
}
});
httpRequestRegister(request);
}
let g_equipmentOperationError = false;
let g_equipmentFromStoreCount = 0;
let g_equipmentToStoreCount = 0;
let g_amuletGroupsToLoad = null;
let g_originalBagObjectIds = null;
let g_originalStoreObjectIds = null;
let g_scheduledObjectIndices = null;
let g_exchangedBagObjectIds = null;
function roleSetupCleanup() {
httpRequestClearAll();
g_equipmentOperationError = false;
g_amuletGroupsToLoad = null;
g_originalBagObjectIds = null;
g_originalStoreObjectIds = null;
g_scheduledObjectIndices = null;
g_exchangedBagObjectIds = null;
}
function roleSetupCompletion() {
roleSetupCleanup();
genericPopupClose(true);
window.location.reload();
}
function checkForRoleSetupCompletion() {
if (genericPopupTaskCheckCompletion()) {
// delay for the final state can be seen
setTimeout(roleSetupCompletion, 200);
}
}
function amuletLoadCompletion() {
genericPopupTaskComplete(2);
genericPopupTaskSetState(2, '');
checkForRoleSetupCompletion();
}
// 'cause of non-equipment-object's id would change when move it from bag to store, and,
// even in store the object's id still can be changed by many kind of operations.
// so unfortunately, restore the scheduled objects to bag by id will fail in most time,
// and so we use indices instead of id, but there always have chances to produce incorrect
// results, that means you * SHOULD * check the result by yourself manually to make sure
// everything is ok
function beginRestoreScheduledObjects() {
let ids;
let sl = g_originalStoreObjectIds.length;
g_scheduledObjectIndices?.sort((a, b) => b - a);
while (g_scheduledObjectIndices?.length > 0) {
// in some case the equipments that putted on was originally in the bag, but the replaced
// equipments will always been putted in the store, so the scheduled object's indices
// should be recalculated to comply with these situations
let i = g_scheduledObjectIndices.pop() + g_equipmentToStoreCount - g_equipmentFromStoreCount;
if (i < sl && g_originalStoreObjectIds[i] >= 0) {
(ids ??= []).push(g_originalStoreObjectIds[i]);
}
}
beginMoveObjects(ids, false, amuletLoadCompletion, 0);
}
// maximum equipments exchanging count should be 4, and it should be placed at the head of the bag cells,
// on the other hand, when you move an equipment-object to store, it will be placed before non-equipment-object cells,
// and this will not change the order between those non-equipment-objects, they just move backward as a whole group,
// based on this fact, we can consider the indices of the scheduled non-equipment-objects is permanent
function beginStoreExchangedObjects() {
function beginRefreshStoredObjects() {
beginReadObjects(null, g_originalStoreObjectIds = [], true, beginRestoreScheduledObjects, 0);
}
g_originalStoreObjectIds.sort((a, b) => a - b);
g_scheduledObjectIndices = findNewObjects(g_scheduledObjectIndices,
g_originalStoreObjectIds,
(a, b) => a < 0 ? 0 : a - b,
true);
g_originalBagObjectIds.sort((a, b) => a - b);
let ids = findNewObjects(g_exchangedBagObjectIds?.length > 4
? g_exchangedBagObjectIds.slice(0, 4) : g_exchangedBagObjectIds,
g_originalBagObjectIds,
(a, b) => a < 0 ? 0 : a - b,
false);
if (ids?.length > 0) {
g_equipmentToStoreCount = ids.length;
beginMoveObjects(ids,
true,
g_scheduledObjectIndices?.length > 0 ? beginRefreshStoredObjects : amuletLoadCompletion,
0);
}
else if (g_scheduledObjectIndices?.length > 0) {
beginRefreshStoredObjects();
}
else {
amuletLoadCompletion();
}
}
function beginamuletLoadGroups() {
if (g_amuletGroupsToLoad?.length > 0) {
genericPopupTaskSetState(2, `- 加载护符……[${g_amuletGroupsToLoad?.length}]`);
beginLoadAmuletGroupFromStore(g_amuletGroupsToLoad.shift(), beginamuletLoadGroups, 0);
}
else {
amuletLoadCompletion();
}
}
function beginLoadAmulets() {
// equipment task should be completed
genericPopupTaskComplete(0, g_equipmentOperationError);
if (g_amuletGroupsToLoad != null) {
genericPopupTaskSetState(2, '- 清理装备……');
beginClearBag(beginamuletLoadGroups, 0);
}
else {
genericPopupTaskSetState(2, '- 恢复背包……');
beginReadObjects(g_exchangedBagObjectIds = [], null, true, beginStoreExchangedObjects, 0);
}
}
function beginScheduleCells(bindInfo) {
function beginReadScheduledStore(bindInfo) {
genericPopupTaskSetState(2, '');
// use g_scheduledObjectIndices as scheduled store temporarily
// (why i'd like save variable names? it's weird...)
beginReadObjects(null, g_scheduledObjectIndices = [], true, sendBeginEquipHttpRequest, bindInfo);
}
if (g_originalBagObjectIds != null) {
g_equipmentFromStoreCount = 0;
g_equipmentToStoreCount = 0;
let ids;
let freeCellsNeeded = 4;
let il = g_originalBagObjectIds.length - 1;
for (let i = il; i >= 0; i--) {
if (g_originalBagObjectIds[i] == -1) {
if (--freeCellsNeeded == 0) {
genericPopupTaskSetState(2, '');
sendBeginEquipHttpRequest(bindInfo);
break;
}
}
else {
(ids ??= []).push(g_originalBagObjectIds[i]);
if (--freeCellsNeeded == 0) {
beginMoveObjects(ids, true, beginReadScheduledStore, bindInfo);
break;
}
}
}
}
else {
genericPopupTaskSetState(2, '- 调整空间……');
beginReadObjects(g_originalBagObjectIds = [], g_originalStoreObjectIds = [], false, beginScheduleCells, bindInfo);
}
}
function beginRoleSetup(bindInfo) {
if (bindInfo.length > 5 && bindInfo[5].length > 0) {
g_amuletGroupsToLoad = bindInfo[5].split(',');
if (g_amuletGroupsToLoad.length > 0) {
g_originalBagObjectIds = [ -1, -1, -1, -1 ];
genericPopupTaskSetState(2, '- 清理背包……');
beginClearBag(beginScheduleCells, bindInfo);
return;
}
}
g_amuletGroupsToLoad = null;
beginScheduleCells(bindInfo);
}
let bindingElements = document.getElementById(g_bindingListSelectorId)?.value?.split(BINDING_NAME_SEPARATOR);
let roleId = (bindingElements?.length == 2 ? bindingElements[0] : undefined);
let bind_info = (bindingElements?.length == 2 ? bindingElements[1] : undefined);
if (roleId != undefined && bind_info != undefined) {
let upcard_data = getPostData(/upcard\(id\)\{[\s\S]*\}/m, /data: ".*\+id\+.*"/).slice(7, -1).replace('"+id+"', roleId);
GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: upcard_data,
onload: response => {
if (response.responseText == 'ok' || response.responseText == '你没有这张卡片或已经装备中') {
bind_info = bind_info.split(BINDING_ELEMENT_SEPARATOR);
function equipOnekeyQuit() {
genericPopupClose(true);
httpRequestAbortAll();
roleSetupCleanup();
}
genericPopupInitialize();
genericPopupTaskListPopupSetup('更换中……', 300, [ '装备', '光环', '护符' ], equipOnekeyQuit);
beginRoleSetup(bind_info);
let halo = bind_info[4].split(',');
for (let i = 0; i < halo.length; i++) {
switch (halo[i]) {
case '启程之誓':
halo[i] = '101';
break;
case '启程之心':
halo[i] = '102';
break;
case '启程之风':
halo[i] = '103';
break;
case '破壁之心':
halo[i] = '201';
break;
case '破魔之心':
halo[i] = '202';
break;
case '复合护盾':
halo[i] = '203';
break;
case '鲜血渴望':
halo[i] = '204';
break;
case '削骨之痛':
halo[i] = '205';
break;
case '圣眉祝福':
halo[i] = '206';
break;
case '伤口恶化':
halo[i] = '301';
break;
case '精神创伤':
halo[i] = '302';
break;
case '铁甲尖刺':
halo[i] = '303';
break;
case '忍无可忍':
halo[i] = '304';
break;
case '热血战魂':
halo[i] = '305';
break;
case '点到为止':
halo[i] = '306';
break;
case '沸血之志':
halo[i] = '401';
break;
case '波澜不惊':
halo[i] = '402';
break;
case '飓风之力':
halo[i] = '403';
break;
case '红蓝双刺':
halo[i] = '404';
break;
case '荧光护盾':
halo[i] = '405';
break;
case '绝对护盾': //old
halo[i] = '405';
break;
case '后发制人':
halo[i] = '406';
break;
}
}
let halosave_data = getPostData(/halosave\(\)\{[\s\S]*\}/m, /data: ".*\+savearr\+.*"/).slice(7, -1).replace('"+savearr+"', halo.join());
let request = GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: halosave_data,
onload: response => {
genericPopupTaskComplete(1, response.responseText != 'ok');
checkForRoleSetupCompletion();
}
});
httpRequestRegister(request);
genericPopupShowModal(false);
}
}
});
}
else {
alert('读取绑定信息失败,无法装备!');
return;
}
}
const BINDING_NAME_DEFAULT = '(未命名)';
const BINDING_SEPARATOR = ';';
const BINDING_NAME_SEPARATOR = '=';
const BINDING_ELEMENT_SEPARATOR = '|';
function showBindingPopup() {
let roleId = roleMap.get(document.querySelector('#backpacks > div.row > div.col-md-3 > span.text-info.fyg_f24')?.innerText)?.id;
let roleLv = document.querySelector("#backpacks")?.querySelectorAll(".icon.icon-angle-down.text-primary")[0]
?.innerText?.match(/\d+/)[0];
let roleHs = document.querySelector("#backpacks")?.querySelectorAll(".icon.icon-angle-down.text-primary")[2]
?.innerText?.match(/\d+/)[0];
if (roleId == undefined || roleLv == undefined || roleHs == undefined) {
alert('读取卡片信息失败,无法执行绑定操作!');
return;
}
let bind_info = null;
let ud = getUserData();
if (ud.dataBind[roleId] != null) {
bind_info = ud.dataBind[roleId];
}
genericPopupInitialize();
genericPopupShowProgressMessage('读取中,请稍候…');
const highlightBackgroundColor = '#80c0f0';
const bindingNameHTML =
`<div style="width:100%;padding:20px 0px;"><b>
<span style="color:#0000ff;">绑定方案名称(不超过31个字符,请仅使用大、小写英文字母、数字、连字符、下划线及中文字符):</span>
<span id="binding_name_tips" style="margin-left:10px;color:#ff0000;"></span></b><br>
<div style="width:100%;"><input type="text" id="binding_name" maxlength="31"
list="binding_list" style="display:inline-block;width:98%;margin-top:15px;"></input></div>
<datalist id="binding_list"></datalist></div>`;
const bindingHTML =
`<style> .equipment_label { display:inline-block; width:15%; }
.equipment_selector { display:inline-block; width:84%; color:#145ccd; float:right; }
div > li { cursor:pointer; } div > li:hover { background-color:#bbddff; } </style>
<div class="${g_genericPopupTopLineDivClass}">
<span class="equipment_label">武器装备:</span><select class="equipment_selector"></select><br><br>
<span class="equipment_label">手臂装备:</span><select class="equipment_selector"></select><br><br>
<span class="equipment_label">身体装备:</span><select class="equipment_selector"></select><br><br>
<span class="equipment_label">头部装备:</span><select class="equipment_selector"></select></div>
<div class="${g_genericPopupTopLineDivClass}" style="display:flex;position:relative;"><div id="halo_selector"></div></div>
<div class="${g_genericPopupTopLineDivClass}" id="amulet_selector" style="display:none;"><div></div></div>`;
genericPopupSetContent(`${roleMap.get(roleId)?.name ?? 'UNKNOW'} - ${roleLv} 级`, bindingHTML);
genericPopupSetFixedContent(bindingNameHTML);
let eq_selectors = document.querySelectorAll('select.equipment_selector');
let asyncOperations = 2;
let equipmentCount = 0;
let haloMax = 0;
GM_xmlhttpRequest({ //获取装备
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div0 = readEquipmentDOM(response.responseText);
let equipment = getEquipmentInfo(div0.children);
equipment = equipment.concat(getEquipmentInfo(document.querySelector("#carding > div.row > div.fyg_tc")?.children));
equipmentCount = equipment.length;
let e = new Array(new Array(), new Array(), new Array(), new Array());
let origin = new Array(new Array(), new Array(), new Array(), new Array());
equipment.sort((e1, e2) => {
if (e1[0] == e2[0]) {
return (parseInt(e2[1]) - parseInt(e1[1]));
}
else if (typedict[e1[0]] == typedict[e2[0]]) {
return (e1[0] < e2[0] ? -1 : 1);
}
return (typedict[e1[0]] - typedict[e2[0]]);
});
equipment.forEach(item => {
let i = typedict[item[0]];
origin[i].push(item)
e[i].push(new Array(fullNameOf[item[0]], `Lv${item[1]}`, `${item[2]}%`, `${item[3]}%`, `${item[4]}%`, `${item[5]}%`, `${item[6] == 1 ? '神秘' : ''}`));
});
for (let i = 0; i < 4; i++) {
for (let j = 0; j < e[i].length; j++) {
let op0 = document.createElement('option');
op0.innerText = e[i][j].join(' ');
op0.value = origin[i][j].slice(0, -2).join(',');
eq_selectors[i].appendChild(op0);
}
}
asyncOperations--;
}
});
let currentHalo = [];
beginReadRoleAndHalo(
null,
currentHalo,
() => {
haloMax = currentHalo[0];
roleHs = currentHalo[1];
let halo =
`天赋点:<span style="color:#0000c0;"><span id="halo_points">0</span> / ${haloMax}</span>,
技能位:<span style="color:#0000c0;"><span id="halo_slots">0</span> / ${roleHs}</span>`;
document.getElementById('halo_selector').innerHTML =
`<style> .halo_group { display:block; width:25%; float:left; text-align:center; border-left:1px solid grey; }
div > a { display:inline-block; width:90px; } div > a:hover { background-color:#bbddff; } </style>
<div>${halo}</div>
<p></p>
<div class="halo_group">
<a href="#" class="halo_item">启程之誓 10</a>
<a href="#" class="halo_item">启程之心 10</a>
<a href="#" class="halo_item">启程之风 10</a></div>
<div class="halo_group">
<a href="#" class="halo_item">破壁之心 30</a>
<a href="#" class="halo_item">破魔之心 30</a>
<a href="#" class="halo_item">复合护盾 30</a>
<a href="#" class="halo_item">鲜血渴望 30</a>
<a href="#" class="halo_item">削骨之痛 30</a>
<a href="#" class="halo_item">圣盾祝福 30</a></div>
<div class="halo_group">
<a href="#" class="halo_item">伤口恶化 50</a>
<a href="#" class="halo_item">精神创伤 50</a>
<a href="#" class="halo_item">铁甲尖刺 50</a>
<a href="#" class="halo_item">忍无可忍 50</a>
<a href="#" class="halo_item">热血战魂 50</a>
<a href="#" class="halo_item">点到为止 50</a></div>
<div class="halo_group" style="border-right:1px solid grey;">
<a href="#" class="halo_item">沸血之志 100</a>
<a href="#" class="halo_item">波澜不惊 100</a>
<a href="#" class="halo_item">飓风之力 100</a>
<a href="#" class="halo_item">红蓝双刺 100</a>
<a href="#" class="halo_item">荧光护盾 100</a>
<a href="#" class="halo_item">后发制人 100</a></div>`;
function selector_halo() {
let hp = parseInt(haloPoints.innerText);
let hs = parseInt(haloSlots.innerText);
if ($(this).attr('item-selected') != 1) {
$(this).attr('item-selected', 1);
$(this).css('background-color', highlightBackgroundColor);
hp += parseInt($(this).text().split(' ')[1]);
hs++;
}
else {
$(this).attr('item-selected', 0);
$(this).css('background-color', g_genericPopupBackgroundColor);
hp -= parseInt($(this).text().split(' ')[1]);
hs--;
}
haloPoints.innerText = hp;
haloSlots.innerText = hs;
haloPoints.style.color = (hp <= haloMax ? '#0000c0' : 'red');
haloSlots.style.color = (hs <= roleHs ? '#0000c0' : 'red');
}
haloPoints = document.getElementById('halo_points');
haloSlots = document.getElementById('halo_slots');
$('.halo_item').each(function(i, e) {
$(e).on('click', selector_halo);
$(e).attr('original-item', $(e).text().split(' ')[0]);
});
asyncOperations--;
},
null);
function unbindAll() {
if (confirm('这将清除本卡片全部绑定方案,继续吗?')) {
let ud = getUserData();
if (ud.dataBind[roleId] != null) {
delete ud.dataBind[roleId];
}
setUserData(ud);
bindingName.value = BINDING_NAME_DEFAULT;
bindingList.innerHTML = '';
refreshBindingSelector(roleId);
alert('解除全部绑定成功!');
}
};
function deleteBinding() {
if (isValidBindingName(bindingName.value)) {
bindings = [];
let found = false;
$(".binding_name_item").each((index, item) => {
if (item.value == bindingName.value) {
bindingList.removeChild(item);
found = true;
}
else {
bindings.push(`${item.value}${BINDING_NAME_SEPARATOR}${item.innerText}`);
}
});
if (found) {
let bn = bindingName.value;
let bi = null;
let ud = getUserData();
if (bindings.length > 0) {
ud.dataBind[roleId] = bindings.join(BINDING_SEPARATOR);
bindingName.value = bindingList.children[0].value;
bi = bindingList.children[0].innerText;
}
else if(ud.dataBind[roleId] != null) {
delete ud.dataBind[roleId];
bindingName.value = BINDING_NAME_DEFAULT;
}
setUserData(ud);
refreshBindingSelector(roleId);
representBinding(bi);
alert(bn + ':解绑成功!');
}
else {
alert('方案名称未找到!');
}
}
else {
alert('方案名称不符合规则!');
}
};
function saveBinding() {
if (isValidBindingName(bindingName.value)) {
let equ = new Array();
let halo = new Array();
let sum = 0;
eq_selectors.forEach((eq) => {
equ.push(eq.value);
});
$(".halo_item").each(function(i, e) {
if ($(e).attr('item-selected') == 1) {
let ee = e.innerText.split(' ');
sum += parseInt(ee[1]);
halo.push($(e).attr("original-item"));
}
});
let h = parseInt(haloMax);
if (equ.length == 4 && sum <= h && halo.length <= parseInt(roleHs)) {
let amuletArray = [];
$(".amulet_item").each(function(i, e) {
if ($(e).attr('item-selected') == 1) {
amuletArray[parseInt(e.lastChild.innerText) - 1] = ($(e).attr("original-item"));
}
});
let bind_info = new Array(equ[0], equ[1], equ[2], equ[3], halo.join(','),
amuletArray.join(',')).join(BINDING_ELEMENT_SEPARATOR);
let newBinding = true;
bindings = [];
$(".binding_name_item").each((index, item) => {
if (item.value == bindingName.value) {
item.innerText = bind_info;
newBinding = false;
}
bindings.push(`${item.value}${BINDING_NAME_SEPARATOR}${item.innerText}`);
});
if (newBinding) {
let op0 = document.createElement('option');
op0.className = 'binding_name_item';
op0.innerText = bind_info;
op0.value = bindingName.value;
for (var op = bindingList.firstChild; op?.value < op0.value; op = op.nextSibling);
bindingList.insertBefore(op0, op);
bindings.push(`${op0.value}${BINDING_NAME_SEPARATOR}${op0.innerText}`);
}
let ud = getUserData();
ud.dataBind[roleId] = bindings.join(BINDING_SEPARATOR);
setUserData(ud);
refreshBindingSelector(roleId);
alert(bindingName.value + ':绑定成功!');
}
else {
alert('有装备未选或天赋错误!');
}
}
else {
alert('方案名称不符合规则!');
}
}
function isValidBindingName(bindingName) {
return (bindingName?.length > 0 && bindingName.length < 32 && bindingName.search(USER_STORAGE_RESERVED_SEPARATORS) < 0);
}
function validateBindingName() {
bindingNameTips.innerText = isValidBindingName(bindingName.value) ? '' : '方案名称不符合规则,请检查。';
}
function validateBinding() {
if (isValidBindingName(bindingName.value)) {
bindingNameTips.innerText = '';
let ol = bindingList.children.length;
for (let i = 0; i < ol; i++) {
if (bindingName.value == bindingList.children[i].value) {
representBinding(bindingList.children[i].innerText);
break;
}
}
}
else {
bindingNameTips.innerText = '方案名称不符合规则,请检查。';
}
}
function representBinding(items) {
if (items?.length > 0) {
let elements = items.split(BINDING_ELEMENT_SEPARATOR);
if (elements.length > 3) {
let v = elements.slice(0, 4);
eq_selectors.forEach((eq) => {
for (let op of eq.childNodes) {
if (v.indexOf(op.value) >= 0) {
eq.value = op.value;
break;
}
}
});
}
if (elements.length > 4) {
let hp = 0;
let hs = 0;
let v = elements[4].split(',');
$('.halo_item').each((index, item) => {
let s = (v.indexOf($(item).attr('original-item')) < 0 ? 0 : 1);
$(item).attr('item-selected', s);
$(item).css('background-color', s == 0 ? g_genericPopupBackgroundColor : highlightBackgroundColor);
hp += (s == 0 ? 0 : parseInt($(item).text().split(' ')[1]));
hs += s;
});
haloPoints.innerText = hp;
haloSlots.innerText = hs;
haloPoints.style.color = (hp <= haloMax ? '#0000c0' : 'red');
haloSlots.style.color = (hs <= roleHs ? '#0000c0' : 'red');
}
selectedAmuletGroupCount = 0;
if (elements.length > 5 && amuletCount != null) {
let ac = 0;
let v = elements[5].split(',');
$('.amulet_item').each((index, item) => {
let j = v.indexOf($(item).attr('original-item'));
let s = (j < 0 ? 0 : 1);
$(item).attr('item-selected', s);
$(item).css('background-color', s == 0 ? g_genericPopupBackgroundColor : highlightBackgroundColor);
item.lastChild.innerText = (j < 0 ? '' : j + 1);
selectedAmuletGroupCount += s;
ac += (s == 0 ? 0 : parseInt($(item).text().match(/\[(\d+)\]/)[1]));
});
amuletCount.innerText = ac;
}
}
}
function selector_amulet() {
let ac = parseInt(amuletCount.innerText);
let tc = parseInt($(this).text().match(/\[(\d+)\]/)[1]);
if ($(this).attr('item-selected') != 1) {
$(this).attr('item-selected', 1);
$(this).css('background-color', highlightBackgroundColor);
this.lastChild.innerText = ++selectedAmuletGroupCount;
ac += tc;
}
else {
$(this).attr('item-selected', 0);
$(this).css('background-color', g_genericPopupBackgroundColor);
let i = parseInt(this.lastChild.innerText);
this.lastChild.innerText = '';
ac -= tc;
if (i < selectedAmuletGroupCount) {
$(".amulet_item").each((index, item) => {
var j;
if ($(item).attr('item-selected') == 1 && (j = parseInt(item.lastChild.innerText)) > i) {
item.lastChild.innerText = j - 1;
}
});
}
selectedAmuletGroupCount--;
}
amuletCount.innerText = ac;
}
let bindingList = document.getElementById('binding_list');
let bindingName = document.getElementById('binding_name');
let bindingNameTips = document.getElementById('binding_name_tips');
let haloPoints = null;
let haloSlots = null;
let amuletContainer = document.getElementById('amulet_selector');
let amuletCount = null;
let amuletGroups = amuletLoadGroups();
let selectedAmuletGroupCount = 0;
let al = (amuletGroups?.count() ?? 0);
if (al > 0) {
amuletContainer.style.display = 'block';
amuletContainer = amuletContainer.firstChild;
amuletContainer.innerHTML =
'护符组:已选定 <span id="amulet_count">0</span> 个护符<span style="float:right;margin-right:5px;">加载顺序</span><p></p>';
amuletCount = document.getElementById('amulet_count');
amuletCount.style.color = '#0000c0';
let amuletArray = amuletGroups.toArray().sort((a, b) => a.name < b.name ? -1 : 1);
for (let i = 0; i < al; i++) {
let li0 = document.createElement('li');
li0.className = 'amulet_item';
li0.setAttribute('original-item', amuletArray[i].name);
li0.innerHTML =
`<a href="#">${amuletArray[i].name} [${amuletArray[i].count()}]</a>` +
`<span style="color:#0000c0;width:40;float:right;margin-right:5px;"></span>`;
li0.addEventListener('click', selector_amulet, false);
amuletContainer.appendChild(li0);
}
}
let bindings = null;
if (bind_info != null) {
bindings = bind_info.split(BINDING_SEPARATOR).sort((a, b) => {
a = a.split(BINDING_NAME_SEPARATOR);
b = b.split(BINDING_NAME_SEPARATOR);
a = a.length > 1 ? a[0] : BINDING_NAME_DEFAULT;
b = b.length > 1 ? b[0] : BINDING_NAME_DEFAULT;
return a < b ? -1 : 1;
});
}
else {
bindings = [];
}
bindings.forEach((item) => {
let elements = item.split(BINDING_NAME_SEPARATOR);
let binding = elements[elements.length - 1].split(BINDING_ELEMENT_SEPARATOR);
if (binding.length > 5) {
let amuletGroupNames = binding[5].split(',');
let ag = '';
let sp = '';
let al = amuletGroupNames.length;
for (let i = 0; i < al; i++) {
if (amuletGroups.contains(amuletGroupNames[i])) {
ag += (sp + amuletGroupNames[i]);
sp = ',';
}
}
binding[5] = ag;
elements[elements.length - 1] = binding.join(BINDING_ELEMENT_SEPARATOR);
}
let op0 = document.createElement('option');
op0.className = 'binding_name_item';
op0.innerText = elements[elements.length - 1];
op0.value = elements.length > 1 ? elements[0] : BINDING_NAME_DEFAULT;
bindingList.appendChild(op0);
});
bindingName.addEventListener('input', validateBindingName, false);
bindingName.addEventListener('change', validateBinding, false);
genericPopupSetContentSize(Math.min(al * 20 + (al > 0 ? 70 : 0) + 380, unsafeWindow.innerHeight - 400), 600, true);
genericPopupAddButton('解除绑定', 0, deleteBinding, true);
genericPopupAddButton('全部解绑', 0, unbindAll, true);
genericPopupAddButton('绑定', 80, saveBinding, false);
genericPopupAddCloseButton(80);
let timer = setInterval(() => {
if (asyncOperations == 0) {
clearInterval(timer);
httpRequestClearAll();
if (bindingList.children.length > 0) {
bindingName.value = bindingList.children[0].value;
representBinding(bindingList.children[0].innerText);
}
else {
bindingName.value = BINDING_NAME_DEFAULT;
}
genericPopupCloseProgressMessage();
genericPopupShowModal(true);
}
}, 200);
};
function refreshBindingSelector(roleId) {
let bindingsolutionDiv = document.getElementById(g_bindingSolutionId);
let bindingList = document.getElementById(g_bindingListSelectorId);
let bindings = null;
let bind_info = getUserData().dataBind[roleId];
if (bind_info != null) {
bindings = bind_info.split(BINDING_SEPARATOR).sort((a, b) => {
a = a.split(BINDING_NAME_SEPARATOR);
b = b.split(BINDING_NAME_SEPARATOR);
a = a.length > 1 ? a[0] : BINDING_NAME_DEFAULT;
b = b.length > 1 ? b[0] : BINDING_NAME_DEFAULT;
return a < b ? -1 : 1;
});
}
bindingList.innerHTML = '';
if (bindings?.length > 0) {
bindings.forEach((item) => {
let elements = item.split(BINDING_NAME_SEPARATOR);
let op0 = document.createElement('option');
op0.value = roleId + BINDING_NAME_SEPARATOR + elements[elements.length - 1];
op0.innerText = (elements.length > 1 ? elements[0] : BINDING_NAME_DEFAULT);
bindingList.appendChild(op0);
});
bindingsolutionDiv.style.display = 'inline-block';
}
else {
bindingsolutionDiv.style.display = 'none';
}
}
function addBindBtn() {
let mountedRoleId = roleMap.get(document.getElementById('carding')
?.querySelector('div.text-info.fyg_f24.fyg_lh60')
?.children[0]?.innerText)?.id;
let roleId = document.querySelector('#backpacks > div.row > button.btn.btn-info.btn-block.btn-lg.dropdown-toggle')
?.getAttribute('onclick')?.match(/\d+/)[0];
unsafeWindow.bindingLinks = ((e) => {
if (e?.parentNode?.id == g_cardOnekeyLinkId) {
switchCardTemporarily(roleId);
}
else if (e?.parentNode?.id == g_bindingPopupLinkId) {
showBindingPopup();
}
else if (e?.parentNode?.id == g_equipOnekeyLinkId) {
equipOnekey();
}
});
let bindingAnchor = document.querySelector('#backpacks > div.row > div.col-md-12').parentNode.nextSibling;
let bindingContainer = document.createElement('div');
bindingContainer.className = 'btn-group';
bindingContainer.style.display = 'block';
bindingContainer.style.width = '100%';
bindingContainer.style.marginTop = '15px';
bindingContainer.style.fontSize = '18px';
bindingContainer.style.padding = '10px';
bindingContainer.style.borderRadius = '5px';
bindingContainer.style.color = '#0000c0';
bindingContainer.style.backgroundColor = '#ebf2f9';
bindingAnchor.parentNode.insertBefore(bindingContainer, bindingAnchor);
let cardLink = document.createElement('span');
cardLink.setAttribute('class', 'fyg_lh30');
cardLink.id = g_cardOnekeyLinkId;
cardLink.style.width = '15%';
cardLink.style.textAlign = 'left';
cardLink.style.display = 'inline-block';
cardLink.innerHTML =
`<a href="#" style="text-decoration:underline;"`+
`${mountedRoleId != roleId ? ' onclick="bindingLinks(this);">临时装备此卡' : '>此卡已经装备'}</a>`;
bindingContainer.appendChild(cardLink);
let bindingLink = document.createElement('span');
bindingLink.setAttribute('class', 'fyg_lh30');
bindingLink.id = g_bindingPopupLinkId;
bindingLink.style.width = '25%';
bindingLink.style.textAlign = 'left';
bindingLink.style.display = 'inline-block';
bindingLink.innerHTML =
'<a href="#" style="text-decoration:underline;" onclick="bindingLinks(this);">绑定(装备 光环 护符)</a>';
bindingContainer.appendChild(bindingLink);
let bindingsolutionDiv = document.createElement('div');
bindingsolutionDiv.id = g_bindingSolutionId;
bindingsolutionDiv.style.display = 'none';
bindingsolutionDiv.style.width = '60%';
let bindingList = document.createElement('select');
bindingList.id = g_bindingListSelectorId;
bindingList.style.width = '80%';
bindingList.style.color = '#0000c0';
bindingList.style.textAlign = 'center';
bindingList.style.display = 'inline-block';
bindingsolutionDiv.appendChild(bindingList);
let applyLink = document.createElement('span');
applyLink.setAttribute('class', 'fyg_lh30');
applyLink.id = g_equipOnekeyLinkId;
applyLink.style.width = '20%';
applyLink.style.textAlign = 'right';
applyLink.style.display = 'inline-block';
applyLink.innerHTML =
'<a href="#" style="text-decoration:underline;" onclick="bindingLinks(this);">应用此方案</a>';
bindingsolutionDiv.appendChild(applyLink);
bindingContainer.appendChild(bindingsolutionDiv);
refreshBindingSelector(roleId);
}
let observer = new MutationObserver((mutationsList, observer) => {
let page = document.getElementsByClassName('nav nav-secondary nav-justified')[0].children;
let index = 0;
for (let i = 0; i < 4; i++) {
if (page[i].className == 'active') {
index = i;
}
}
switch (index) {
case 0:
$('.pop_main').hide();
btnc1.onclick = () => {
$('.pop_main').show()
$('.pop_con').css({ 'top': 0, 'opacity': 0 })
$('.pop_con').animate({ 'top': '50%', 'opacity': 1 })
try {
let equip = document.querySelector("#carding > div.row > div.fyg_tc").children;
let bag = Array.from(document.querySelector("#backpacks > div.alert-danger > div.content")
.querySelectorAll(".fyg_mp3")).concat(
Array.from(document.querySelector("#backpacks > div.alert-success > div.content")
.querySelectorAll(".fyg_mp3")));
let bagdata = getEquipmentInfo(bag);
let data = getEquipmentInfo(equip);
bagdata = bagdata.concat(data).sort((e1, e2) => {
//
// by zyxboy
// return sortdict[e1[0]] - sortdict[e2[0]];
if (e1[0] == e2[0]) {
return (parseInt(e1[1]) - parseInt(e2[1]));
}
else if (typedict[e1[0]] == typedict[e2[0]]) {
return (e1[0] < e2[0] ? -1 : 1);
}
return (typedict[e1[0]] - typedict[e2[0]]);
// end by zyxboy
//
});
d.innerHTML =
`<div class="pop_main" style="padding:0px 10px;">
<div class="pop_con"><a href="#">× 折叠 ×</a>
<div style="width:200px;padding:5px;margin-top:10px;margin-bottom:10px;color:red;border:1px solid grey">已装备:</div>
<div class="pop_text">/</div>
<div class="pop_text">/</div>
<div class="pop_text">/</div>
<div class="pop_text">/</div>
<div class="pop_text" style="width:200px;padding:5px;margin-top:10px;margin-bottom:10px;color:red;border:1px solid grey;">全部:</div>
${new Array(bagdata.length + 1).join('<div class="pop_text">/</div>')}
<div class="pop_text" style="width:200px;padding:5px;margin-top:10px;margin-bottom:10px;color:red;border:1px solid grey;">护符:</div>
<div class="pop_text">/</div><hr>
<a href="#">× 折叠 ×</a></div></div>`;
$('.pop_con a').click(() => {
$('.pop_con').animate({ 'top': 0, 'opacity': 0 }, () => {
$('.pop_main').hide()
})
})
$('.pop_main').show()
$('.pop_con').css({ 'top': 0, 'opacity': 0 })
$('.pop_con').animate({ 'top': '50%', 'opacity': 1 })
let text = $('.pop_text');
text[0].innerText = `${data[0].slice(0, -1).join(' ')}`;
text[1].innerText = `${data[1].slice(0, -1).join(' ')}`;
text[2].innerText = `${data[2].slice(0, -1).join(' ')}`;
text[3].innerText = `${data[3].slice(0, -1).join(' ')}`;
for (let i = 0; i < bagdata.length; i++) {
text[5 + i].innerText = `${bagdata[i].slice(0, -1).join(' ')}`;
}
let amulet = document.getElementById('backpacks').lastChild.children[1].innerText.match(/\+\d+/g);
let amuletAbbr = new Array('STR', 'AGI', 'INT', 'VIT', 'SPR', 'MND', 'PATK', 'MATK', 'SPD',
'REC', 'HP', 'SLD', 'LCH', 'RFL', 'CRT', 'SKL', 'PDEF', 'MDEF');
for (let i = amulet.length - 1; i >= 0; i--) {
if (amulet[i][1] == '0') {
amulet.splice(i, 1);
} else {
amulet[i] = amuletAbbr[i] + amulet[i];
}
}
text[6 + bagdata.length].innerText = `AMULET ${amulet.join(' ').replace(/\+/g, ' ')} ENDAMULET`;
} catch (err) { console.log(err); }
}
try {
if (!(mutationsList[0]?.addedNodes[0]?.className?.split(' ')[0] == 'popover' ||
mutationsList[0]?.removedNodes[0]?.className?.split(' ')[0] == 'popover')) {
addCollapse();
}
} catch (err) {}
break;
case 1: {
$('.pop_main').hide();
let roleId = document.querySelector('#backpacks > div.row > button.btn.btn-info.btn-block.btn-lg.dropdown-toggle')
?.getAttribute('onclick')?.match(/\d+/)[0];
if (roleId?.length > 0) {
btnc1.onclick = () => {
d.innerHTML =
'<div class="pop_main">\n<div class="pop_con">\n<div class="pop_text">0</div>\n' +
'<div class="pop_text">0</div>\n<a href="#">×</a>\n</div>\n<div class="mask"></div>\n</div>';
$('.pop_con a').click(() => {
$('.pop_con').animate({ 'top': 0, 'opacity': 0 }, () => {
$('.pop_main').hide()
})
})
$('.pop_main').show()
$('.pop_con').css({ 'top': 0, 'opacity': 0 })
$('.pop_con').animate({ 'top': '50%', 'opacity': 1 })
let text = $('.pop_text');
let cardInfos = document.querySelector("#backpacks").querySelectorAll(".icon.icon-angle-down.text-primary");
let cardInfo = [ roleMap.get(roleId)?.shortMark ?? 'UNKNOW',
cardInfos[0].innerText.match(/\d+/)[0],
cardInfos[2].innerText.match(/\d+/)[0],
cardInfos[1].innerText.match(/\d+/)[0] ];
let points = [];
for (let i = 1; i <= 6; i++) {
points.push(document.getElementById('sjj' + i).innerText);
}
text[0].innerText = cardInfo.join(' ');
text[1].innerText = points.join(' ');
}
observer.disconnect();
addBindBtn();
observer.observe(document.getElementById('backpacks'), { childList: true, characterData: true });
}
else {
btnc1.onclick = () => {};
}
break;
}
case 2:
$('.pop_main').hide();
btnc1.onclick = () => {
try {
d.innerHTML =
'<div class="pop_main">\n<div class="pop_con">\n<div class="pop_text">0</div>\n' +
'<a href="#">×</a>\n</div>\n<div class="mask"></div>\n</div>';
$('.pop_con a').click(() => {
$('.pop_con').animate({ 'top': 0, 'opacity': 0 }, () => {
$('.pop_main').hide()
})
})
$('.pop_main').show()
$('.pop_con').css({ 'top': 0, 'opacity': 0 })
$('.pop_con').animate({ 'top': '50%', 'opacity': 1 })
let text = $('.pop_text');
let aura = document.getElementsByClassName('btn btn-primary');
let data = new Array();
data.push(aura.length);
for (let i = 0; i < aura.length; i++) {
let t = aura[i].innerText;
t = t.trim();
switch (t[0]) {
case '启':
switch (t[3]) {
case '誓':
data.push('SHI');
break;
case '心':
data.push('XIN');
break;
case '风':
data.push('FENG');
break;
}
break;
case '破':
switch (t[1]) {
case '壁':
data.push('BI');
break;
case '魔':
data.push('MO');
break;
}
break;
case '复':
data.push('DUN');
break;
case '鲜':
data.push('XUE');
break;
case '削':
data.push('XIAO');
break;
case '圣':
data.push('SHENG');
break;
case '伤':
data.push('SHANG');
break;
case '精':
data.push('SHEN');
break;
case '铁':
data.push('CI');
break;
case '忍':
data.push('REN');
break;
case '热':
data.push('RE');
break;
case '点':
data.push('DIAN');
break;
case '沸':
data.push('FEI');
break;
case '波':
data.push('BO');
break;
case '飓':
data.push('JU');
break;
case '红':
data.push('HONG');
break;
case '荧':
data.push('JUE');
break;
case '后':
data.push('HOU');
break;
default:
data.push('NONE');
break;
}
}
text[0].innerText = `${data.join(' ')}`;
} catch (err) {
console.log(err);
}
}
break;
case 3:
$('.pop_main').hide();
btnc1.onclick = () => {}
break;
}
});
observer.observe(document.getElementById('backpacks'), { childList: true, characterData: true });
document.getElementById('backpacks').appendChild(document.createElement('div'));
}
}, 500);
let p = document.getElementsByClassName('panel panel-primary')[1];
p.insertBefore(btnc1, p.children[0]);
let d = document.createElement('div');
d.id = 'alert';
d.innerHTML =
'<div class="pop_main">\n<div class="pop_con">\n<div class="pop_text">0</div>\n' +
'<a href="#">×</a>\n</div>\n<div class="mask"></div>\n</div>';
p.insertBefore(d, p.children[0]);
$('.pop_main').hide();
$('.pop_con a').click(() => {
$('.pop_con').animate({ 'top': 0, 'opacity': 0 }, () => {
$('.pop_main').hide()
})
})
} else if (window.location.pathname == '/fyg_beach.php') {
function insertAfter(newEl, targetEl) {
var parentEl = targetEl.parentNode;
if (parentEl.lastChild == targetEl) {
parentEl.appendChild(newEl);
} else {
parentEl.insertBefore(newEl, targetEl.nextSibling);
}
}
let beachCheck = document.createElement('form');
beachCheck.innerHTML =
`<div class="form-group form-check" style="padding:5px 15px;border-bottom:1px solid grey;">
<label class="form-check-label" for="beachcheck" style="margin-right:5px;">屏蔽垃圾装备</label>
<input type="checkbox" class="form-check-input" id="beachcheck" style="margin-right:15px;" />
<label id="analyze-indicator" style="margin-right:15px;">分析中... </label>
<button button type="button" onclick="siftSetting()">筛选设置</button>
<div style="float:right;"><label for="beach_BG" style="margin-right:5px;">使用深色背景</label>
<input type="checkbox" id="beach_BG" /></div></div>`;
document.getElementsByClassName('panel panel-primary')[2].insertBefore(beachCheck, document.getElementsByClassName('panel panel-primary')[2].children[1]);
let beach_BG = document.querySelector("#beach_BG").checked = (localStorage.getItem(g_beachBGStorageKey) == 'true');
document.querySelector("#beach_BG").addEventListener('click', () => { localStorage.setItem(g_beachBGStorageKey, beach_BG = document.querySelector("#beach_BG").checked); changeBeachStyle(); }, false);
document.querySelector("#beachcheck").addEventListener('click', () => { localStorage.setItem('beachcheck', document.querySelector("#beachcheck").checked) }, false);
document.querySelector("#beachcheck").checked = (localStorage.getItem('beachcheck') == 'true');
let popStyle =
`<style>
.popup {
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, .5);
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 9999;
display: none;
justify-content: center;
align-items: center;
}
.popup-content {
width: 400px;
height: 200px;
background-color: #fff;
box-sizing: border-box;
padding: 10px 30px;
color: black;
}
.topline {
width: 100%;
border-bottom: 1px solid black;
}
</style>`;
let divSetting = document.createElement('div');
divSetting.setAttribute('id', 'siftpage_pop');
let eqs = new Array(fullName.slice(0, sortdict.BOUND_0), fullName.slice(sortdict.BOUND_0 + 1, sortdict.BOUND_1),
fullName.slice(sortdict.BOUND_1 + 1, sortdict.BOUND_2), fullName.slice(sortdict.BOUND_2 + 1));
for (let i = 0; i < 4; i++) {
for (let j = 0; j < eqs[i].length; j++) {
eqs[i][j] =
`<span class="dropdown dropdown-hover">
<button class="btn" type="button" id="btn${eqToAbbr(eqs[i][j])}" data-toggle="dropdown">${eqs[i][j]} <span class="caret">
</span></button>
<ul class="dropdown-menu">
<li><a href="#" class="attri_item">属性1</a></li>
<li><a href="#" class="attri_item">属性2</a></li>
<li><a href="#" class="attri_item">属性3</a></li>
<li><a href="#" class="attri_item">属性4</a></li>
</ul>
</span>
<input type="checkbox" class="form-check-input siftsetting" id="${eqToAbbr(eqs[i][j])}"> `;
}
}
let initSettingHTML =
`<div class="popup-content">
<div class="topline">
<p></p>
<form><div class="form-group form-check">
${eqs[0]}
</div></form>
</div>
<div class="topline">
<p></p>
<form><div class="form-group form-check">
${eqs[1]}
</div></form>
</div>
<div class="topline">
<p></p>
<form><div class="form-group form-check">
${eqs[2]}
</div></form>
</div>
<div class="topline">
<p></p>
<form><div class="form-group form-check">
${eqs[3]}
</div></form>
</div>
<p></p>
<p style="color:red">勾选的装备不会被拾取,有神秘除外</p>
<p style="color:red">勾选的属性不会被对比,即此条属性大于已有装备也不会被拾取,即忽略无用属性</p>
<button type="button" onclick="exitSift()">完成</button>
</div>`;
divSetting.innerHTML =
`${popStyle}
<div class="popup" id="siftpop">
${initSettingHTML}
</div>`;
unsafeWindow.siftSetting = function() {
$('.popup-content').height(Math.min(fullName.length, 19) * 10 + 200);
$('.popup-content').width(700);
$('.popup-content').css('overflow', 'scroll');
function selector_sift() {
if ($(this).text()[0] != '✔') {
$(this).text('✔' + $(this).text());
} else {
$(this).text($(this).text().slice(1));
}
}
$('.attri_item').each(function(i, e) {
$(e).on('click', selector_sift);
});
$('.attri_item').hover(
function() {
$(this).css({ 'color': '#fff', 'background-color': '#3280fc' });
},
function() {
$(this).css({ 'color': '#000', 'background-color': '#fff' });
}
);
let eqchecks = document.getElementsByClassName('form-check-input siftsetting');
let ud = getUserData();
for (let i = 0; i < eqchecks.length; i++) {
if (ud.dataBeachSift == null) {
ud.dataBeachSift = { "PLATE": "true,false,false,false,false", "LEATHER": "true,false,false,false,false", "CLOTH": "true,false,false,false,false" };
setUserData(ud);
} else {
if (ud.dataBeachSift[eqchecks[i].id] != null) {
let s = ud.dataBeachSift[eqchecks[i].id].split(',');
eqchecks[i].checked = (s[0] == 'true');
let attri = eqchecks[i].previousSibling.previousSibling.children[1].children;
for (let i = 0; i < attri.length; i++) {
if (s[1 + i] == 'true') {
attri[i].children[0].innerText = '✔' + attri[i].children[0].innerText;
}
}
}
}
}
document.getElementById('siftpop').style.display = 'flex';
}
unsafeWindow.exitSift = function() {
let eqchecks = document.getElementsByClassName('form-check-input siftsetting');
let ud = getUserData();
for (let i = 0; i < eqchecks.length; i++) {
let checklist = eqchecks[i].previousSibling.previousSibling.children[1].innerText.split('\n')
let checkres = new Array(eqchecks[i].checked, false, false, false, false);
for (let i = 0, j = 1; i < checklist.length; i++) {
if (checklist[i].replace(/\s+/g, '').length > 0) {
if (checklist[i].replace(/\s+/g, '')[0] == '✔') {
checkres[j] = true;
j++;
} else if (checklist[i].replace(/\s+/g, '')[0] == '属') {
checkres[j] = false;
j++;
}
}
}
ud.dataBeachSift[eqchecks[i].id] = `${checkres}`;
}
setUserData(ud);
document.getElementById('siftpop').style.display = 'none';
document.getElementById('siftpop').innerHTML = initSettingHTML;
}
let p2 = document.getElementsByClassName('panel panel-primary')[2];
if (p2.lastChild.id != 'siftpage_pop') {
p2.appendChild(divSetting);
}
let divAmulet = document.createElement('div');
divAmulet.setAttribute('id', 'amuletpage_pop');
let initAmuletHTML =
`<div class="popup-content">
<div class="topline">
<p></p>
</div>
<button type="button" onclick="exitAmulet()">取消</button>
<button type="button" disabled="disabled" onclick="goAmulet()">继续</button>
<span>请稍候...</span>
</div>`;
divAmulet.innerHTML =
`${popStyle}
<div class="popup" id="amuletpop">
${initAmuletHTML}
</div>`;
let toAmuletExit = false;
let continueAmulet = true;
unsafeWindow.exitAmulet = function() {
toAmuletExit = true;
document.getElementById('amuletpop').style.display = 'none';
document.getElementById('amuletpop').innerHTML = initAmuletHTML;
}
unsafeWindow.goAmulet = function() {
continueAmulet = true;
}
let p1 = document.getElementsByClassName('panel panel-primary')[1];
if (p1.lastChild.id != 'amuletpage_pop') {
p1.appendChild(divAmulet);
}
let batbtns = document.getElementsByClassName('panel-body')[1].children[0];
let toAmuletBtn = document.createElement('button');
toAmuletBtn.className = 'btn btn-danger';
toAmuletBtn.innerText = '批量沙滩转护符(背包至少留一个空位)';
let _amuletsID = new Array();
let _equipmentsID = new Array();
let _pickID = new Array();
let _safeid = null;
let _next = -1;
let waitForContinue = null;
toAmuletBtn.onclick = () => {
_amuletsID = new Array();
_equipmentsID = new Array();
_pickID = new Array();
_safeid = null;
_next = -1;
waitForContinue = null;
toAmuletExit = false;
continueAmulet = true;
let bagItems = document.querySelector("#backpacks").children;
if (bagItems != null && bagItems.length > 2 && confirm('确定要把沙滩所有装备转换成护符吗?')) {
for (let i = 0; i < bagItems.length; i++) {
if (bagItems[i].className.split(' ').length == 3 && bagItems[i].innerText.indexOf('+') != -1) {
_amuletsID.push(bagItems[i].getAttribute('onclick').match(/'\d+'/)[0].slice(1, -1));
} else if (bagItems[i].className.split(' ').length == 3 && bagItems[i].innerText.indexOf('+') == -1) {
_equipmentsID.push(bagItems[i].getAttribute('onclick').match(/'\d+'/)[0].slice(1, -1));
}
}
let btns = document.getElementsByClassName('fyg_mp3');
for (let i = 0; i < btns.length; i++) {
if (btns[i].parentNode.id == 'beachall' && btns[i].className.indexOf('btn') != -1) {
let rare = btns[i].className.split(' ')[1];
if (rare != 'fyg_colpz01bg' && rare != 'fyg_colpz02bg') {
_pickID.push(btns[i].getAttribute('onclick').match(/\(\d+\)/)[0].slice(1, -1))
}
}
}
_safeid = getPostData(/sttz\(\)\{[\s\S]*\}/m, /data: ".*"/).slice(12, -1);
let amuletBlock = document.getElementById('amuletpop').children[0].children[0];
let btnExit = document.getElementById('amuletpop').children[0].children[1];
let btnContinue = document.getElementById('amuletpop').children[0].children[2];
let infospan = document.getElementById('amuletpop').children[0].children[3];
function showAmuletPop() {
$('.popup-content').height(Math.min(_pickID.length, 19) * 10 + 200);
$('.popup-content').width(700);
$('.popup-content').css('overflow', 'scroll');
document.getElementById('amuletpop').style.display = 'flex';
}
unsafeWindow.destroyAmulet = (e) => {
let btn = e.parentNode.parentNode.parentNode;
let id = btn.getAttribute('id');
let pirlam_data = `c=9&id=${id}&yz=124&${_safeid}`;
GM_xmlhttpRequest({ //pirl(id)
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: pirlam_data,
onload: response => {
if (response.responseText.indexOf('水') != -1) {
GM_xmlhttpRequest({ //read
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=2',
onload: response => {
_amuletsID.splice(_amuletsID.indexOf(id), 1);
btn.parentNode.removeChild(btn);
}
});
} else {
console.log(`except at destroy: ${response.responseText}`);
}
}
});
}
unsafeWindow.storeAmulet = (e) => {
let btn = e.parentNode.parentNode.parentNode;
let id = btn.getAttribute('id');
let pirlam_data = `c=21&id=${id}&${_safeid}`;
GM_xmlhttpRequest({ //puti(id)
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: pirlam_data,
onload: response => {
if (response.responseText == 'ok') {
GM_xmlhttpRequest({ //read
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: `f=2`,
onload: response => {
_amuletsID.splice(_amuletsID.indexOf(id), 1);
btn.parentNode.removeChild(btn);
}
});
} else {
console.log(`except at store: ${response.responseText}`);
alert('仓库已满');
}
}
});
}
showAmuletPop();
function toAmulet(count, equipmentsID, amuletsID, pickID, safeid) {
infospan.innerText = '请稍候..';
btnContinue.disabled = 'disabled';
if (count == 0) {
infospan.innerText = '';
btnExit.innerText = '完成';
return;
}
if (toAmuletExit) {
return;
}
let stpick_data = `c=1&id=${pickID[count-1]}&${safeid}`;
GM_xmlhttpRequest({ //pick equipment
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: stpick_data,
onload: response => {
if (toAmuletExit) {
return;
}
if (response.responseText != 'ok') {
infospan.innerText = '背包已满,请处理后继续';
btnContinue.disabled = '';
continueAmulet = false;
_next = count;
_equipmentsID = equipmentsID;
_amuletsID = amuletsID;
_pickID = pickID;
_safeid = safeid;
waitForContinue = setInterval(() => {
// $('.amulet_menu').bind('click', () => {
// let id = $(this).parent().parent().parent().attr('id');
// console.log(`splice: ${id}`);
// _amuletsID.splice(_amuletsID.indexOf(id), 1);
// });
if (continueAmulet) {
clearInterval(waitForContinue);
toAmulet(_next, _equipmentsID, _amuletsID, _pickID, _safeid);
} else if (toAmuletExit) {
clearInterval(waitForContinue);
}
}, 200);
//alert('背包已满,请处理后继续');
return;
}
GM_xmlhttpRequest({ //find eqid
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=2',
onload: response => {
if (toAmuletExit) {
return;
}
let eqid = null;
let bagdiv = document.createElement('div');
bagdiv.innerHTML = response.responseText;
for (let i = 0; i < bagdiv.children.length; i++) {
if (bagdiv.children[i].className.split(' ').length == 3 && bagdiv.children[i].innerText.indexOf('+') == -1) {
eqid = bagdiv.children[i].getAttribute('onclick').match(/'\d+'/)[0].slice(1, -1);
if (equipmentsID.length == 0 || equipmentsID.indexOf(eqid) == -1) {
break;
} else {
eqid = null;
}
}
}
let pirleq_data = `c=9&id=${eqid}&yz=124&${safeid}`;
GM_xmlhttpRequest({ //pirl(id)
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: pirleq_data,
onload: response => {
if (toAmuletExit) {
return;
}
GM_xmlhttpRequest({ //find amid
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=2',
onload: response => {
if (toAmuletExit) {
return;
}
let amid = null;
let bagdiv = document.createElement('div');
bagdiv.innerHTML = response.responseText;
for (let i = 0; i < bagdiv.children.length; i++) {
if (bagdiv.children[i].className.split(' ').length == 3 && bagdiv.children[i].innerText.indexOf('+') != -1) {
amid = bagdiv.children[i].getAttribute('onclick').match(/'\d+'/)[0].slice(1, -1);
if (amuletsID.length == 0 || amuletsID.indexOf(amid) == -1) {
//
// by zyxboy
let btnColor = '#00c000';
if (bagdiv.children[i].outerHTML.indexOf('樱桃') != -1 || bagdiv.children[i].outerHTML.indexOf('传奇') != -1) {
btnColor = '#c00000';
}
else if (bagdiv.children[i].outerHTML.indexOf('史诗') != -1){
btnColor = '#c0c000';
}
// end by zyxboy
//
let btn0 = document.createElement('div');
btn0.setAttribute('class', 'btn-group');
btn0.setAttribute('id', amid);
btn0.innerHTML =
`<button type="button" class="btn btn-light dropdown-toggle" data-toggle="dropdown" style="background-color:${btnColor}; padding: 0px; text-align: left; box-shadow: none; line-height: 90%;">
<div class="popover-content-show" style="padding: 10px 10px 0px;">${bagdiv.children[i].dataset.content}</div>
<span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li><a class="amulet_menu" href="#" style="background-color:#FF8C00" onclick="destroyAmulet(this)">销毁</a></li>
<li><a class="amulet_menu" href="#" style="background-color:#00CED1" onclick="storeAmulet(this)">入库</a></li>
</ul>`;
amuletBlock.appendChild(btn0);
amuletsID.push(amid);
break;
} else {
amid = null;
}
}
}
toAmulet(count - 1, equipmentsID, amuletsID, pickID, safeid);
}
});
}
});
}
});
}
});
}
toAmulet(_pickID.length, _equipmentsID, _amuletsID, _pickID, _safeid);
}
}
batbtns.appendChild(toAmuletBtn);
let equipment = new Array();
let equipedbtn = null;
//读取拥有的装备
GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=7',
onload: response => {
let div0 = readEquipmentDOM(response.responseText);
for (let i = div0.children.length - 1; i >= 0; i--) {
if (div0.children[i].className.split(' ').length != 3 || div0.children[i].innerText.indexOf('+') != -1) {
div0.removeChild(div0.children[i]);
}
}
equipedbtn = [].slice.call(div0.children);
let equipbag = getEquipmentInfo(div0.children);
GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=9',
onload: response => {
document.getElementById("analyze-indicator").innerText = '';
let div0 = document.createElement('div');
div0.innerHTML = response.responseText;
equipedbtn = equipedbtn.concat(Array.from(div0.querySelector("div.row > div.fyg_tc")?.children));
equipedbtn.sort(sortEqByName);
let equiped = getEquipmentInfo(div0.querySelector("div.row > div.fyg_tc")?.children);
equipment = equipbag.concat(equiped);
if (equipment.length == 0) {
equipment[0] = -1;
}
}
});
}
});
//分析装备并显示属性
var g_pickingEquipment = false;
function pickEquipment(equipment) {
//
// by zyxboy
if (!(equipedbtn?.length > 0) || !(equipment?.length > 0) || equipment[0] == -1) {
return;
}
let beach_copy = document.getElementById('beach_copy');
if (beach_copy == null)
{
let beachall = document.getElementById('beachall');
beach_copy = beachall.cloneNode();
beachall.style.display = 'none';
beach_copy.id = 'beach_copy';
beach_copy.style.backgroundColor = beach_BG ? 'black' : 'white';
beachall.parentNode.insertBefore(beach_copy, beachall);
let beachCopyObserver = new MutationObserver((mList) => {
if (!g_pickingEquipment && mList?.length == 1 && mList[0].type == 'childList' &&
mList[0].addedNodes?.length == 1 & !(mList[0].removedNodes?.length > 0)) {
let node = mList[0].addedNodes[0];
if (node.hasAttribute('role')) {
// let tipClass = node.previousSibling?.getAttribute('data-tip-class');
// if (tipClass != null && node.className?.indexOf(tipClass) < 0 && node.className.indexOf('bottom') >= 0) {
// node.className += (' ' + tipClass);
// }
// }
// else {
node.remove();
}
}
});
beachCopyObserver.observe(beach_copy, { childList: true });
}
g_pickingEquipment = true;
copyBeach(beach_copy);
if (document.querySelector("#beachcheck").checked) {
//屏蔽鼠标事件
$('#beach_copy .fyg_mp3').css('pointer-events', 'none');
} else {
$('#beach_copy .fyg_mp3').css('pointer-events', 'auto');
}
//if (equipment[0] == -1) return;
// end by zyxboy
//
let btns = beach_copy.getElementsByClassName('fyg_mp3');
let udata = getUserData();
if (udata.dataBeachSift == null) {
udata.dataBeachSift = { "PLATE": "true,false,false,false,false", "LEATHER": "true,false,false,false,false", "CLOTH": "true,false,false,false,false" };
setUserData(udata);
}
for (let i = 0; i < btns.length; i++) {
//
// by zyxboy
if (btns[i].parentNode.id == 'beach_copy' && btns[i].className.indexOf('btn') != -1) {
// end by zyxboy
//
let isFind = false;
let isPick = false;
let sift = new Array(5).fill('false')
let btninfo = getEquipmentInfo(new Array(btns[i]))[0];
if (udata.dataBeachSift != null && udata.dataBeachSift[btninfo[0]] != null) {
sift = udata.dataBeachSift[btninfo[0]].split(',');
}
if (btninfo[6] == 1) {
//神秘必捡
isPick = true;
}
//
// by zyxboy
else if (btns[i].className.indexOf('fyg_colpz04bg') >= 0 || btns[i].className.indexOf('fyg_colpz05bg') >= 0){
// red & yellow
isPick = true;
// end by zyxboy
//
} else if (sift[0] == 'true') {
//筛选设置不捡
isPick = false;
} else {
for (let j = 0; j < equipment.length; j++) {
if (equipment[j][0] == btninfo[0]) {
isFind = true;
let e1 = new Array(parseInt(equipment[j][1]), parseInt(equipment[j][2]), parseInt(equipment[j][3]), parseInt(equipment[j][4]), parseInt(equipment[j][5]));
let e2 = new Array(parseInt(btninfo[1]), parseInt(btninfo[2]), parseInt(btninfo[3]), parseInt(btninfo[4]), parseInt(btninfo[5]));
function product(e1, e2) {
return e1 * e2;
}
function linear(e1, e2, a, b) {
return (e1 / a + b) * e2;
}
let comp = new Array(false, false, false, false);
switch (btninfo[0]) {
case 'BLADE':
comp[0] = linear(e1[0], e1[1], 5, 20) < linear(e2[0], e2[1], 5, 20);
comp[1] = linear(e1[0], e1[2], 5, 20) < linear(e2[0], e2[2], 5, 20);
comp[2] = linear(e1[0], e1[3], 20, 10) < linear(e2[0], e2[3], 20, 10);
comp[3] = linear(e1[0], e1[4], 20, 10) < linear(e2[0], e2[4], 20, 10);
break;
case 'STAFF':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = linear(e1[0], e1[3], 20, 5) < linear(e2[0], e2[3], 20, 5);
comp[3] = linear(e1[0], e1[4], 15, 10) < linear(e2[0], e2[4], 15, 10);
break;
case 'WAND':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'SWORD':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = linear(e1[0], e1[4], 15, 10) < linear(e2[0], e2[4], 15, 10);
break;
case 'CLAYMORE':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = linear(e1[0], e1[3], 5, 30) < linear(e2[0], e2[3], 5, 30);
comp[3] = linear(e1[0], e1[4], 20, 1) < linear(e2[0], e2[4], 20, 1);
break;
case 'SHIELD':
comp[0] = linear(e1[0], e1[1], 15, 10) < linear(e2[0], e2[1], 15, 10);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'BOW':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = linear(e1[0], e1[4], 15, 10) < linear(e2[0], e2[4], 15, 10);
break;
case 'ASSBOW':
comp[0] = linear(e1[0], e1[1], 5, 30) < linear(e2[0], e2[1], 5, 30);
comp[1] = linear(e1[0], e1[2], 20, 10) < linear(e2[0], e2[2], 20, 10);
comp[2] = linear(e1[0], e1[3], 20, 10) < linear(e2[0], e2[3], 20, 10);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'DAGGER':
comp[0] = linear(e1[0], e1[1], 5, 0) < linear(e2[0], e2[1], 5, 0);
comp[1] = linear(e1[0], e1[2], 5, 0) < linear(e2[0], e2[2], 5, 0);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = linear(e1[0], e1[4], 5, 25) < linear(e2[0], e2[4], 5, 25);
break;
case 'GLOVES':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'BRACELET':
comp[0] = linear(e1[0], e1[1], 5, 1) < linear(e2[0], e2[1], 5, 1);
comp[1] = linear(e1[0], e1[2], 20, 1) < linear(e2[0], e2[2], 20, 1);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'VULTURE':
comp[0] = linear(e1[0], e1[1], 15, 5) < linear(e2[0], e2[1], 15, 5);
comp[1] = linear(e1[0], e1[2], 15, 5) < linear(e2[0], e2[2], 15, 5);
comp[2] = linear(e1[0], e1[3], 15, 5) < linear(e2[0], e2[3], 15, 5);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'CLOAK':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = linear(e1[0], e1[3], 5, 25) < linear(e2[0], e2[3], 5, 25);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'CLOTH':
isPick = false;
break;
case 'LEATHER':
isPick = false;
break;
case 'PLATE':
isPick = false;
break;
case 'THORN':
comp[0] = linear(e1[0], e1[1], 5, 20) < linear(e2[0], e2[1], 5, 20);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = linear(e1[0], e1[4], 15, 10) < linear(e2[0], e2[4], 15, 10);
break;
case 'SCARF':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'TIARA':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = linear(e1[0], e1[2], 3, 1) < linear(e2[0], e2[2], 3, 1);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
case 'RIBBON':
comp[0] = product(e1[0], e1[1]) < product(e2[0], e2[1]);
comp[1] = product(e1[0], e1[2]) < product(e2[0], e2[2]);
comp[2] = product(e1[0], e1[3]) < product(e2[0], e2[3]);
comp[3] = product(e1[0], e1[4]) < product(e2[0], e2[4]);
break;
}
isPick = (
sift[1] == 'false' && comp[0] ||
sift[2] == 'false' && comp[1] ||
sift[3] == 'false' && comp[2] ||
sift[4] == 'false' && comp[3]);
if (isPick) {
break;
}
}
}
if (!isFind) {
isPick = true;
}
}
if (isPick) {
let btn0 = document.createElement('button');
btn0.className = 'btn btn-light';
btn0.style.minWidth = '200px';
btn0.style.padding = '0px';
btn0.style.marginBottom = '5px';
btn0.style.textAlign = 'left';
btn0.style.boxShadow = 'none';
btn0.style.lineHeight = '150%';
btn0.style.borderColor = getComputedStyle(btns[i]).getPropertyValue('background-color');
btn0.setAttribute('data-toggle', 'popover');
btn0.setAttribute('data-trigger', 'hover');
btn0.setAttribute('data-placement', 'left');
btn0.setAttribute('data-html', 'true');
btn0.setAttribute('onclick', btns[i].getAttribute('onclick'));
let popover = document.createElement('div');
popover.innerHTML = `<style>.popover{max-width:420px;}</style>`
for (let eqbtn of equipedbtn) {
if (sortdict[eqToAbbr(btns[i].dataset.originalTitle.split(' ')[2])] == parseInt(eqbtn.getAttribute('data-abbr'))) {
let btn1 = document.createElement('button');
btn1.setAttribute('class', 'btn btn-light');
btn1.style.cssText =
'min-width:180px;padding:10px 5px 0px 5px;text-align:left;box-shadow:none;background-color:none;' +
'line-height:120%;margin-right:3px;margin-bottom:3px';
btn1.innerHTML = eqbtn.dataset.content;
if (btn1.lastChild.nodeType == 3) { //清除背景介绍文本
btn1.lastChild.remove();
}
if (btn1.lastChild.className.indexOf('bg-danger') != -1) {
btn1.lastChild.style.cssText = 'max-width:180px;padding:3px;white-space:pre-line;word-break:break-all;';
}
popover.appendChild(btn1);
}
}
btn0.setAttribute('data-content', popover.innerHTML);
btn0.innerHTML =
`<h3 class="popover-title" style="background-color:${btn0.style.borderColor}">
${btns[i].dataset.originalTitle}</h3><div class="popover-content-show"
style="padding:10px 10px 0px 10px;">${btns[i].dataset.content}</div>`;
insertAfter(btn0, btns[i]);
}
}
g_pickingEquipment = false;
}
$(function() {
$('#beach_copy .btn[data-toggle="popover"]').popover();
});
$('#beach_copy .bg-danger.with-padding').css({
'max-width': '200px',
'padding': '5px',
'white-space': 'pre-line',
'word-break': 'break-all'
});
changeBeachStyle();
}
function changeBeachStyle()
{
$('#beach_copy .popover-content-show').css({
'background-color': beach_BG ? 'black' : 'white'
});
$('#beach_copy .btn-light').css({
'background-color': beach_BG ? 'black' : 'white'
});
$('#beach_copy .popover-title').css({
'color': beach_BG ? 'black' : 'white'
});
$('#beach_copy .pull-right').css({
'color': beach_BG ? 'black' : 'white'
});
$('#beach_copy .bg-danger.with-padding').css({
'color': beach_BG ? 'black' : 'white'
});
let beach_copy = document.getElementById('beach_copy');
if (beach_copy != null) {
beach_copy.style.backgroundColor = beach_BG ? 'black' : 'white';
}
}
//
// by zyxboy
//等待海滩装备加载
let show = setInterval(() => {
if ($('#beachall .btn').length != 0) {
clearInterval(show);
//等待装备读取完成
let pick = setInterval(() => {
if (equipment.length > 0) {
clearInterval(pick);
pickEquipment(equipment);
let beachObserver = new MutationObserver(() => { pickEquipment(equipment); });
beachObserver.observe(document.getElementById('beachall'), { childList: true });
}
}, 500);
}
}, 500);
function copyBeach(beach_copy) {
beach_copy.innerHTML = '';
let nodes = Array.from(document.getElementById('beachall').children).sort(sortBeach);
for (let node of nodes) {
beach_copy.appendChild(node.cloneNode(true));
}
}
function sortBeach(a, b) {
if (a.className != b.className) {
if (a.className == null || !a.className.endsWith('fyg_mp3')) {
return -1;
}
else if (b.className == null || !b.className.endsWith('fyg_mp3')) {
return 1;
}
return (a.className.split(' ')[1] > b.className.split(' ')[1] ? -1 : 1);
}
else if (a == null || !a.className.endsWith('fyg_mp3')) {
return -1;
}
let delta = parseInt(a.innerText.match(/\d+/)[0]) - parseInt(b.innerText.match(/\d+/)[0]);
return (delta != 0 ? -delta : (a.getAttribute('data-original-title') > b.getAttribute('data-original-title') ? -1 : 1));
}
// end by zyxboy
//
} else if (window.location.pathname == '/fyg_pk.php') {
//
// by zyxboy
let autoTaskEnabled = localStorage.getItem(g_autoTaskEnabledStorageKey);
if (autoTaskEnabled == null) {
autoTaskEnabled = 1;
localStorage.setItem(g_autoTaskEnabledStorageKey, autoTaskEnabled);
}
let autoTaskEnabledSpan = document.createElement('span');
autoTaskEnabledSpan.style.float = 'right';
autoTaskEnabledSpan.style.color = '#ffffff';
autoTaskEnabledSpan.style.padding = '5px';
autoTaskEnabledSpan.innerText = '允许执行自定义任务';
let autoTaskEnabledCheckbox = document.createElement('input');
autoTaskEnabledCheckbox.setAttribute('type','checkbox');
autoTaskEnabledCheckbox.style.marginLeft = '5px';
autoTaskEnabledCheckbox.style.marginRight = '10px';
autoTaskEnabledCheckbox.checked = (autoTaskEnabled != 0);
autoTaskEnabledCheckbox.onchange = (() => {
localStorage.setItem(g_autoTaskEnabledStorageKey, autoTaskEnabledCheckbox.checked ? 1 : 0);
window.location.reload();
});
autoTaskEnabledSpan.appendChild(autoTaskEnabledCheckbox);
let p = document.getElementsByClassName('panel panel-primary')[0];
p.insertBefore(autoTaskEnabledSpan, p.children[0]);
if (autoTaskEnabledCheckbox.checked) {
// end by zyxboy
//
let btngroup0 = document.createElement('div');
btngroup0.setAttribute('class', 'action_selector');
btngroup0.innerHTML = `<p></p><div class="btn-group" role="group">
<button type="button" class="btn btn-secondary">0</button>
<button type="button" class="btn btn-secondary">10</button>
<button type="button" class="btn btn-secondary">20</button>
<button type="button" class="btn btn-secondary">30</button>
<button type="button" class="btn btn-secondary">40</button>
<button type="button" class="btn btn-secondary">50</button>
<button type="button" class="btn btn-secondary">60</button>
<button type="button" class="btn btn-secondary">70</button>
<button type="button" class="btn btn-secondary">80</button>
<button type="button" class="btn btn-secondary">90</button>
<button type="button" class="btn btn-secondary">100</button>
</div>`;
let btngroup1 = document.createElement('div');
btngroup1.setAttribute('class', 'action_selector');
btngroup1.innerHTML = `<p></p><div class="btn-group" role="group">
<button type="button" class="btn btn-secondary">0</button>
<button type="button" class="btn btn-secondary">5</button>
<button type="button" class="btn btn-secondary">10</button>
<button type="button" class="btn btn-secondary">15</button>
<button type="button" class="btn btn-secondary">20</button>
<button type="button" class="btn btn-secondary">25</button>
<button type="button" class="btn btn-secondary">30</button>
<button type="button" class="btn btn-secondary">35</button>
<button type="button" class="btn btn-secondary">40</button>
<button type="button" class="btn btn-secondary">45</button>
<button type="button" class="btn btn-secondary">50</button>
<button type="button" class="btn btn-secondary">55</button>
<button type="button" class="btn btn-secondary">60</button>
<button type="button" class="btn btn-secondary">65</button>
<button type="button" class="btn btn-secondary">70</button>
<button type="button" class="btn btn-secondary">75</button>
<button type="button" class="btn btn-secondary">80</button>
<button type="button" class="btn btn-secondary">85</button>
<button type="button" class="btn btn-secondary">90</button>
<button type="button" class="btn btn-secondary">95</button>
<button type="button" class="btn btn-secondary">100</button>
</div>`;
let btngroup2 = document.createElement('div');
btngroup2.setAttribute('class', 'action_selector');
btngroup2.innerHTML = `<p></p><div class="btn-group" role="group">
<button type="button" class="btn btn-secondary">0</button>
<button type="button" class="btn btn-secondary">5</button>
<button type="button" class="btn btn-secondary">10</button>
<button type="button" class="btn btn-secondary">15</button>
<button type="button" class="btn btn-secondary">20</button>
<button type="button" class="btn btn-secondary">25</button>
<button type="button" class="btn btn-secondary">30</button>
<button type="button" class="btn btn-secondary">35</button>
<button type="button" class="btn btn-secondary">40</button>
<button type="button" class="btn btn-secondary">45</button>
<button type="button" class="btn btn-secondary">50</button>
<button type="button" class="btn btn-secondary">55</button>
<button type="button" class="btn btn-secondary">60</button>
<button type="button" class="btn btn-secondary">65</button>
<button type="button" class="btn btn-secondary">70</button>
<button type="button" class="btn btn-secondary">75</button>
<button type="button" class="btn btn-secondary">80</button>
<button type="button" class="btn btn-secondary">85</button>
<button type="button" class="btn btn-secondary">90</button>
<button type="button" class="btn btn-secondary">95</button>
<button type="button" class="btn btn-secondary">100</button>
</div>`;
let observerBody0 = new MutationObserver(() => {
//observerBody0.disconnect();
if (document.getElementsByClassName('btn-secondary').length == 0) {
let addbtn = setInterval(() => {
let col = document.querySelector("#pklist > div > div.col-md-8");
if (col != null) {
clearInterval(addbtn);
let obtns = document.getElementsByClassName('btn-block dropdown-toggle fyg_lh30');
col.insertBefore(btngroup0, obtns[0]);
col.insertBefore(btngroup1, obtns[1]);
col.insertBefore(btngroup2, obtns[2]);
if (document.getElementsByClassName('btn-outline-secondary').length == 0) {
if (localStorage.getItem('dataReward') == null) {
localStorage.setItem('dataReward', '{"sumShell":"0","sumExp":"0"}');
}
let ok = document.createElement('div');
ok.innerHTML = `<p></p><button type="button" class="btn btn-outline-secondary">任务执行</button>`;
col.appendChild(ok);
function gobattle() {
let times = new Array(0, 0, 0);
let sum = 0;
$(".btn-secondary").each(function(i, e) {
if ($(e).attr("style") != null && $(e).css("background-color") == "rgb(135, 206, 250)") {
let a = parseInt(e.innerText);
let b = $(".btn-group .btn-secondary").index(e);
sum += a;
if (b < 11) {
times[0] = a / 10;
} else if (b >= 11 && b < 32) {
times[1] = a / 5;
} else if (b >= 32) {
times[2] = a / 5;
}
}
});
if (sum <= parseInt(document.getElementsByClassName('fyg_colpz03')[0].innerText)) {
let gox_data = getPostData(/gox\(\)\{[\s\S]*\}/m, /data: ".*"/).slice(7, -1);
let dataReward = JSON.parse(localStorage.getItem('dataReward'));
let sum0 = parseInt(dataReward.sumShell);
let sum1 = parseInt(dataReward.sumExp);
//
// by zyxboy
function parseGainResponse(response)
{
let gainText = '';
if (response.startsWith('<p>获得了</p>')) {
let gain;
let sp = '获得';
let regex = /<span class="fyg_f24">x\s*(\d+)\s*([^<]+)<\/span>/g;
while ((gain = regex.exec(response))?.length == 3) {
gainText += `${sp}${gain[2].trim()}:${gain[1]}`;
sp = ', ';
}
let lvlUp = response.match(/角色 \[ [^\s]+ \] 卡片等级提升!/g);
if (lvlUp?.length > 0) {
lvlUp.forEach((e) => {
gainText += `${sp}${e}`;
sp = ', ';
});
}
}
return gainText;
}
// end by zyxboy
//
function func0(time) {
if (time == 0) {
if (times[0] != 0) {
GM_xmlhttpRequest({
method: g_postMethod,
url: g_readUrl,
headers: g_postHeader,
data: 'f=12',
onload: response => {
let ap = response.responseText.match(/class="fyg_colpz03" style="font-size:32px;font-weight:900;">\d+</)[0].match(/>\d+</)[0].slice(1, -1);
document.getElementsByClassName('fyg_colpz03')[0].innerText = ap;
let rankp = response.responseText.match(/class="fyg_colpz02" style="font-size:32px;font-weight:900;">\d+%</)[0].match(/\d+%/)[0];
document.getElementsByClassName('fyg_colpz02')[0].innerText = rankp;
let div_sum = document.createElement('div');
div_sum.innerText = `贝壳总次数:经验总次数=${sum0}:${sum1}=${(sum0 == 0 || sum1 == 0) ? 'undefined' : (sum0 / sum1).toFixed(4)}`;
dataReward.sumShell = sum0;
dataReward.sumExp = sum1;
localStorage.setItem('dataReward', JSON.stringify(dataReward));
document.getElementsByClassName('btn-outline-secondary')[0].parentNode.appendChild(div_sum);
times[0] = 0;
}
});
}
return;
}
GM_xmlhttpRequest({
method: g_postMethod,
url: g_postUrl,
headers: g_postHeader,
data: gox_data,
onload: response => {
//
// by zyxboy
let gainText = parseGainResponse(response.responseText);
if (gainText.length > 0) {
let div_info = document.createElement('div');
div_info.innerText = gainText;
document.getElementsByClassName('btn-outline-secondary')[0].parentNode.appendChild(div_info);
if (gainText.indexOf('贝壳') != -1) {
sum0 += 1;
}
if (gainText.indexOf('经验') != -1) {
sum1 += 1;
}
func0(time - 1);
} else {
let div_info = document.createElement('div');
div_info.innerText = '段位进度不足或无法识别的应答信息';
document.getElementsByClassName('btn-outline-secondary')[0].parentNode.appendChild(div_info);
func0(0);
}
// end by zyxboy
//
}
});
}
function func1(time) {
if (time == 0) {
times[1] = 0;
return;
}
let observerPk = new MutationObserver((mutationsList, observer) => {
let isPk = 0;
for (let mutation of mutationsList) {
if (mutation.type == 'childList') {
isPk = 1;
}
}
if (isPk) {
observerPk.disconnect();
func1(time - 1);
}
});
observerPk.observe(document.querySelector("#pk_text"), { characterData: true, childList: true });
jgjg(1);
}
function func2(time) {
if (time == 0) {
times[2] = 0;
return;
}
let observerPk = new MutationObserver((mutationsList, observer) => {
let isPk = 0;
for (let mutation of mutationsList) {
if (mutation.type == 'childList') {
isPk = 1;
}
}
if (isPk) {
observerPk.disconnect();
func2(time - 1);
}
});
observerPk.observe(document.querySelector("#pk_text"), { characterData: true, childList: true });
jgjg(2);
}
func0(times[0]);
let waitFor0 = setInterval(() => {
if (times[0] == 0) {
clearInterval(waitFor0);
func1(times[1]);
}
}, 1000);
let waitFor1 = setInterval(() => {
if (times[0] == 0 && times[1] == 0) {
clearInterval(waitFor1);
func2(times[2]);
}
}, 1000);
} else {
alert('体力不足');
}
}
document.getElementsByClassName('btn-outline-secondary')[0].addEventListener('click', gobattle, false);
}
function selector_act() {
var btnNum = $(".btn-group .btn-secondary").index(this);
$(".btn-group .btn-secondary")
.eq(btnNum)
.css("background-color", "rgb(135, 206, 250)")
.siblings(".btn-group .btn-secondary")
.css("background-color", "rgb(255, 255, 255)");
}
let btnselector = document.getElementsByClassName('btn-secondary');
for (let i = 0; i < btnselector.length; i++) {
btnselector[i].addEventListener('click', selector_act, false);
}
}
}, 1000);
}
});
observerBody0.observe(document.getElementsByClassName('panel panel-primary')[0], { childList: true, subtree: true, });
}
let keepCheck = document.createElement('form');
keepCheck.innerHTML =
`<div class="form-group form-check">
<label class="form-check-label" for="keepcheck">暂时保持记录</label>
<input type="checkbox" class="form-check-input" id="keepcheck"></div>`;
document.getElementsByClassName('panel panel-primary')[1].insertBefore(keepCheck, document.getElementById('pk_text'));
document.querySelector("#keepcheck").addEventListener('click', () => { localStorage.setItem('keepcheck', document.querySelector("#keepcheck").checked) }, false);
document.querySelector("#keepcheck").checked = (localStorage.getItem('keepcheck') == 'true');
let div0_pk_text_more = document.createElement('div');
div0_pk_text_more.setAttribute('id', 'pk_text_more');
div0_pk_text_more.setAttribute('class', 'panel-body');
document.getElementsByClassName('panel panel-primary')[1].appendChild(div0_pk_text_more);
let pkText = document.querySelector("#pk_text").innerHTML;
let observerBody1 = new MutationObserver(() => {
if (document.querySelector("#keepcheck").checked == true) {
document.querySelector("#pk_text_more").innerHTML = pkText + document.querySelector("#pk_text_more").innerHTML;
pkText = document.querySelector("#pk_text").innerHTML;
}
});
observerBody1.observe(document.querySelector("#pk_text"), { characterData: true, childList: true });
wishExpireTip();
} else if (window.location.pathname == '/fyg_wish.php') {
let timer = setInterval(() => {
let wishPoints = parseInt(document.getElementById('xys_dsn')?.innerText);
if (!isNaN(wishPoints)) {
clearInterval(timer);
function getWishPoints() {
let text = 'WISH';
for (let i = 7; i <= 13; i++) {
text += (' ' + (document.getElementById('xyx_' + ('0' + i).slice(-2))?.innerText ?? '0'));
}
return text;
}
unsafeWindow.copyWishPoints = ((a) => {
let acolor = a.style.color;
let astring = a.innerText;
a.style.color = '#c00000';
calcWishPoints.select();
if (document.execCommand('copy')) {
a.innerText = '许愿点设置已复制到剪贴板';
}
else {
a.innerText = '复制失败,这可能是因为浏览器没有剪贴板访问权限,请进行手工复制';
}
setTimeout((() => {
a.style.color = acolor;
a.innerText = astring;
}), 3000);
});
let div = document.createElement('div');
div.className = 'row';
div.innerHTML =
'<div class="panel panel-info"><div class="panel-heading"> 计算器许愿点设置 (' +
'<a href="#" onclick="copyWishPoints(this);">点击这里复制到剪贴板</a>)</div>' +
'<input type="text" class="panel-body" id="calcWishPoints" readonly="true" style="border:none;outline:none;" value="" />';
let calcWishPoints = div.querySelector("#calcWishPoints");
calcWishPoints.value = getWishPoints();
let xydiv = document.getElementById('xydiv');
xydiv.parentNode.parentNode.insertBefore(div, xydiv.parentNode.nextSibling);
(new MutationObserver(() => {
calcWishPoints.value = getWishPoints();
})).observe(xydiv, { subtree : true , childList : true , characterData : true });
}
}, 500);
}
})();