287 lines
16 KiB
TypeScript
287 lines
16 KiB
TypeScript
import WuhuConfig from "../../class/WuhuConfig";
|
|
import WT_HTML from "../../static/html/xmasTown/wt.html";
|
|
import WT_XMAS_TOWN_HTML from "../../static/html/xmasTown/wt_xmas_town.html";
|
|
import WT_MALTESE_SNOW_GLOBE_HTML from "../../static/html/xmasTown/wt_maltese_snow_globe.html";
|
|
import WT_LONG_WAY_FROM_HOME_HTML from "../../static/html/xmasTown/wt_long_way_from_home.html";
|
|
import WT_CHEDBURN_TOWERS_HTML from "../../static/html/xmasTown/wt_chedburn_towers.html";
|
|
import WT_KIDNAPPED_SANTA_HTML from "../../static/html/xmasTown/wt_kidnapped_santa.html";
|
|
import WT_HOLIDAY_TERROR_HTML from "../../static/html/xmasTown/wt_holiday_terror.html";
|
|
import WT_AMONG_US_HTML from "../../static/html/xmasTown/wt_among_us.html";
|
|
import WT_KISS_MY_FESTIVUS_HTML from "../../static/html/xmasTown/wt_kiss_my_festivus.html";
|
|
import WT_STANLEY_HOTEL_HTML from "../../static/html/xmasTown/wt_stanley_hotel.html";
|
|
import WT_DOGGOQUEST_HTML from "../../static/html/xmasTown/wt_doggoQuest.html";
|
|
import WT_POKEMON_CT_HTML from "../../static/html/xmasTown/wt_pokemon_ct.html";
|
|
import WT_WINTER_IN_GATLIN_HTML from "../../static/html/xmasTown/wt_winter_in_gatlin.html";
|
|
import XMAS_TOWN_NOTIFY_HTML from "../../static/html/xmasTown/xmas_town_notify.html";
|
|
|
|
export default function christmasTownHelper() {
|
|
let $root = document.querySelector('#christmastownroot');
|
|
const [xmasTownWT, xmasTownNotify] = WuhuConfig.get(['xmasTownWT', 'xmasTownNotify']);
|
|
// 解密攻略
|
|
if (xmasTownWT) {
|
|
const insert_html = WT_HTML;
|
|
const wt_dict = {
|
|
"None": { title: '', wt: ``, },
|
|
"Christmas Town": {
|
|
title: '圣诞小镇', wt: WT_XMAS_TOWN_HTML,
|
|
},
|
|
"Maltese Snow Globe": {
|
|
title: 'Maltese Snow Globe', wt: WT_MALTESE_SNOW_GLOBE_HTML,
|
|
},
|
|
"Long way from home": {
|
|
title: 'Long way from home', wt: WT_LONG_WAY_FROM_HOME_HTML,
|
|
},
|
|
"Chedburn Towers": {
|
|
title: 'Chedburn Towers', wt: WT_CHEDBURN_TOWERS_HTML,
|
|
},
|
|
"Kidnapped Santa": {
|
|
title: 'Kidnapped Santa', wt: WT_KIDNAPPED_SANTA_HTML,
|
|
},
|
|
"Holiday terror": {
|
|
title: 'Holiday terror', wt: WT_HOLIDAY_TERROR_HTML,
|
|
},
|
|
"Among Us": {
|
|
title: 'Among Us', wt: WT_AMONG_US_HTML,
|
|
},
|
|
"Kiss My Festivus": {
|
|
title: 'Kiss My Festivus', wt: WT_KISS_MY_FESTIVUS_HTML,
|
|
},
|
|
"Stanley Hotel": {
|
|
title: 'Stanley Hotel', wt: WT_STANLEY_HOTEL_HTML,
|
|
},
|
|
"DoggoQuest": {
|
|
title: 'DoggoQuest', wt: WT_DOGGOQUEST_HTML,
|
|
},
|
|
"Pokemon CT": {
|
|
title: 'Pokemon CT', wt: WT_POKEMON_CT_HTML,
|
|
},
|
|
"Winter in Gatlin": {
|
|
title: 'Winter in Gatlin', wt: WT_WINTER_IN_GATLIN_HTML,
|
|
},
|
|
};
|
|
const $city_wrapper = $root.querySelectorAll('div[class^="core-layout__"]');
|
|
$city_wrapper.forEach(el => {
|
|
let $wh_container = $root.querySelector('#wh-xmas-cont');
|
|
if (!$wh_container) {
|
|
$(el).prepend(insert_html);
|
|
$wh_container = $root.querySelector('#wh-xmas-cont');
|
|
// 显示 隐藏
|
|
const jquery$wh_container = $($wh_container);
|
|
const $cont_gray = jquery$wh_container.find('.cont-gray');
|
|
jquery$wh_container.find('button').click(e => {
|
|
if (e.target.innerText === '[隐藏]') {
|
|
$cont_gray.hide();
|
|
e.target.innerText = '[显示]';
|
|
} else {
|
|
$cont_gray.show();
|
|
e.target.innerText = '[隐藏]';
|
|
}
|
|
});
|
|
// 内容
|
|
const $wt_content = jquery$wh_container.find('#wt-content');
|
|
jquery$wh_container.find('select').change(e => {
|
|
const selected = e.target.value;
|
|
$wt_content.html(`<p><b>${ wt_dict[selected].title }</b></p><p>${ wt_dict[selected].wt }</p>`)
|
|
});
|
|
}
|
|
});
|
|
}
|
|
// 宝箱检测
|
|
if (xmasTownNotify) {
|
|
const chestTypeDict = { '1': '金', '2': '银', '3': '铜', };
|
|
const chestTypeColorDict = { '1': 'gold', '2': 'silver', '3': 'sandybrown', };
|
|
const lootTypeDict = {
|
|
'chests': '钥匙箱',
|
|
'gifts': '礼物',
|
|
'combinationChest': '密码箱',
|
|
'keys': '钥匙',
|
|
};
|
|
const keyTypeDict = { 'b': '铜', 's': '银', 'g': '金', };
|
|
let dropHist = localStorage.getItem('wh-loot-store')
|
|
? JSON.parse(localStorage.getItem('wh-loot-store'))
|
|
: {};
|
|
const alertSettings = localStorage.getItem('wh-loot-setting')
|
|
? JSON.parse(localStorage.getItem('wh-loot-setting'))
|
|
: { blink: 'y', sound: 'y', chest: 'y' };
|
|
let $ct_wrap;
|
|
let soundLoopFlag = false;
|
|
const getDOMOb = new MutationObserver(() => {
|
|
$ct_wrap = $root.querySelector('#ct-wrap');
|
|
if ($ct_wrap) {
|
|
getDOMOb.disconnect();
|
|
const insert_html = XMAS_TOWN_NOTIFY_HTML
|
|
.replace('{{}}', alertSettings.blink === 'y' ? 'checked' : '')
|
|
.replace('{{}}', alertSettings.sound === 'y' ? 'checked' : '')
|
|
.replace('{{}}', alertSettings.chest === 'y' ? 'checked' : '');
|
|
$($ct_wrap).before(insert_html);
|
|
const $wh_loot_container = $root.querySelector('#wh-loot-container') as HTMLElement;
|
|
const $btn = $wh_loot_container.querySelector('#wh-loot-btn button') as HTMLButtonElement;
|
|
const $clear_btn = $wh_loot_container.querySelector('#wh-hist-clear button') as HTMLButtonElement;
|
|
const $ex = $wh_loot_container.querySelector('#wh-loot-container-ex');
|
|
const $tbody = $wh_loot_container.querySelector('tbody');
|
|
const $blink = $wh_loot_container.querySelector('#wh-loot-setting-blink') as HTMLInputElement;
|
|
const $sound = $wh_loot_container.querySelector('#wh-loot-setting-sound') as HTMLInputElement;
|
|
const $chest = $wh_loot_container.querySelector('#wh-loot-setting-chest') as HTMLInputElement;
|
|
const $audio = $wh_loot_container.querySelector('audio');
|
|
$btn.onclick = e => {
|
|
let target = e.target as HTMLButtonElement;
|
|
target.innerText = target.innerText === '设置' ? '收起' : '设置';
|
|
$($ex).toggleClass('wh-hide');
|
|
target.blur();
|
|
};
|
|
$clear_btn.onclick = e => {
|
|
let target = e.target as HTMLButtonElement;
|
|
target.blur();
|
|
dropHist = {};
|
|
$tbody.innerHTML = '';
|
|
localStorage.setItem('wh-loot-store', JSON.stringify(dropHist));
|
|
};
|
|
$blink.onchange = e => {
|
|
if ((<HTMLInputElement>e.target).checked) {
|
|
alertSettings.blink = 'y';
|
|
if ($wh_loot_container.querySelector('#wh-loot-item-count').innerText !== '(0)') {
|
|
(<HTMLElement>$wh_loot_container.querySelector('#wh-loot-container-main')).style.animation = 'lootFoundAlert 2s infinite';
|
|
}
|
|
} else {
|
|
alertSettings.blink = 'n';
|
|
(<HTMLElement>$wh_loot_container.querySelector('#wh-loot-container-main')).style.animation = '';
|
|
}
|
|
localStorage.setItem('wh-loot-setting', JSON.stringify(alertSettings));
|
|
};
|
|
$sound.onchange = e => {
|
|
if ((<HTMLInputElement>e.target).checked) {
|
|
alertSettings.sound = 'y';
|
|
if ($wh_loot_container.querySelector('#wh-loot-item-count').innerText !== '(0)') {
|
|
soundLoopFlag = true;
|
|
}
|
|
} else {
|
|
alertSettings.sound = 'n';
|
|
soundLoopFlag = false;
|
|
}
|
|
localStorage.setItem('wh-loot-setting', JSON.stringify(alertSettings));
|
|
};
|
|
$chest.onchange = e => {
|
|
alertSettings.chest = (<HTMLInputElement>e.target).checked ? 'y' : 'n';
|
|
localStorage.setItem('wh-loot-setting', JSON.stringify(alertSettings));
|
|
};
|
|
const soundIntervalID = window.setInterval(() => {
|
|
if (soundLoopFlag) $audio.play().then();
|
|
}, 1200);
|
|
ob.observe($root, { childList: true, subtree: true });
|
|
}
|
|
});
|
|
const ob = new MutationObserver(() => {
|
|
ob.disconnect();
|
|
// 页面刷新重新获取dom
|
|
$root = document.querySelector('#christmastownroot');
|
|
$ct_wrap = $root.querySelector('#ct-wrap');
|
|
if (!$ct_wrap) {
|
|
ob.observe($root, { childList: true, subtree: true });
|
|
return;
|
|
}
|
|
const $ct_title = $ct_wrap.querySelector('.status-title');
|
|
const $pos = $ct_wrap.querySelector('.map-title span[class^="position___"]') || $ct_wrap.querySelector('.status-title span[class^="position___"]');
|
|
if (!$pos) {
|
|
ob.observe($root, { childList: true, subtree: true });
|
|
return;
|
|
}
|
|
const $pos_spl = $pos.innerText.trim().split(',');
|
|
const player_position = {
|
|
x: parseInt($pos_spl[0]),
|
|
y: parseInt($pos_spl[1]),
|
|
};
|
|
// player_position.x = parseInt($pos_spl[0]);
|
|
// player_position.y = parseInt($pos_spl[1]);
|
|
const $wh_loot_container = $root.querySelector('#wh-loot-container');
|
|
if (!$wh_loot_container) {
|
|
console.error('掉落助手未找到DOM容器');
|
|
ob.observe($root, { childList: true, subtree: true });
|
|
return;
|
|
}
|
|
const $blink = $wh_loot_container.querySelector('#wh-loot-setting-blink') as HTMLInputElement;
|
|
const $sound = $wh_loot_container.querySelector('#wh-loot-setting-sound') as HTMLInputElement;
|
|
const $chest = $wh_loot_container.querySelector('#wh-loot-setting-chest') as HTMLInputElement;
|
|
const $tbody = $wh_loot_container.querySelector('tbody');
|
|
const nearby_arr = [];
|
|
const items = $root.querySelectorAll('div.grid-layer div.items-layer div.ct-item');
|
|
// 附近的所有物品
|
|
items.forEach(el => {
|
|
const item_props = { x: 0, y: 0, name: '', type: '', url: '', };
|
|
item_props.x = parseInt((<HTMLElement>el).style.left.replaceAll('px', '')) / 30;
|
|
item_props.y = -parseInt((<HTMLElement>el).style.top.replaceAll('px', '')) / 30;
|
|
item_props.url = el.firstElementChild.src;
|
|
const srcSpl = item_props.url.trim().split('/');
|
|
item_props.name = srcSpl[6];
|
|
item_props.type = srcSpl[8].slice(0, 1);
|
|
nearby_arr.push(item_props);
|
|
});
|
|
const $wh_loot_container_items = $wh_loot_container.querySelector('#wh-loot-container-items');
|
|
const $wh_loot_container_chests = $wh_loot_container.querySelector('#wh-loot-container-chests');
|
|
let item_count = 0, chest_count = 0;
|
|
$wh_loot_container_items.innerHTML = '';
|
|
$wh_loot_container_chests.innerHTML = '';
|
|
nearby_arr.forEach(nearby_item => {
|
|
let path = '=';
|
|
if (nearby_item.x < player_position.x && nearby_item.y < player_position.y) path = '↙';
|
|
else if (nearby_item.x < player_position.x && nearby_item.y === player_position.y) path = '←';
|
|
else if (nearby_item.x < player_position.x && nearby_item.y > player_position.y) path = '↖';
|
|
else if (nearby_item.x === player_position.x && nearby_item.y > player_position.y) path = '↑';
|
|
else if (nearby_item.x > player_position.x && nearby_item.y > player_position.y) path = '↗';
|
|
else if (nearby_item.x > player_position.x && nearby_item.y === player_position.y) path = '→';
|
|
else if (nearby_item.x > player_position.x && nearby_item.y < player_position.y) path = '↘';
|
|
else if (nearby_item.x === player_position.x && nearby_item.y < player_position.y) path = '↓';
|
|
let item_name;
|
|
if (nearby_item.name === 'chests') {
|
|
chest_count++;
|
|
item_name = chestTypeDict[nearby_item.type] + lootTypeDict[nearby_item.name];
|
|
$wh_loot_container_chests.innerHTML += `<span style="background-color: ${ chestTypeColorDict[nearby_item.type] || 'silver' };">${ path }[${ nearby_item.x },${ nearby_item.y }] ${ item_name }<img src="${ nearby_item.url }" /></span>`
|
|
} else {
|
|
item_count++;
|
|
item_name = (nearby_item.name === 'keys' ? keyTypeDict[nearby_item.type] || '' : '') + lootTypeDict[nearby_item.name] || nearby_item.name;
|
|
$wh_loot_container_items.innerHTML += `<span>${ path }[${ nearby_item.x },${ nearby_item.y }] ${ item_name }<img src="${ nearby_item.url }" /></span>`
|
|
}
|
|
// 确认地图坐标存在
|
|
if ($ct_title) {
|
|
const hist_key = `[${ nearby_item.x },${ nearby_item.y }]"${ $ct_title.firstChild.nodeValue.trim() }"${ item_name }`;
|
|
const el = dropHist[hist_key];
|
|
if (el) {
|
|
if (path === '=' && (nearby_item.name === 'keys' || nearby_item.name === 'gifts')) {
|
|
el.isPassed = true;
|
|
}
|
|
} else {
|
|
if (!(nearby_item.name === 'chests' && $chest.checked)) {
|
|
const now = new Date();
|
|
dropHist[hist_key] = {
|
|
pos: `[${ nearby_item.x },${ nearby_item.y }]`,
|
|
map: $ct_title.firstChild.nodeValue.trim(),
|
|
last: `${ now.getFullYear() }-${ now.getMonth() + 1 }-${ now.getDate() } ${ now.getHours() }:${ now.getMinutes() }:${ now.getSeconds() }`,
|
|
name: item_name,
|
|
id: Object.keys(dropHist).length,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
});
|
|
$wh_loot_container.querySelector('#wh-loot-item-count').innerText = `(${ item_count })`;
|
|
if (item_count === 0) {
|
|
$wh_loot_container_items.innerText = '暂无';
|
|
(<HTMLElement>$wh_loot_container.querySelector('#wh-loot-container-main')).style.animation = '';
|
|
soundLoopFlag = false;
|
|
} else {
|
|
if ($blink.checked) (<HTMLElement>$wh_loot_container.querySelector('#wh-loot-container-main')).style.animation = 'lootFoundAlert 2s infinite';
|
|
if ($sound.checked) soundLoopFlag = true;
|
|
}
|
|
$wh_loot_container.querySelector('#wh-loot-chest-count').innerText = `(${ chest_count })`;
|
|
if (chest_count === 0) $wh_loot_container_chests.innerText = '暂无';
|
|
const history = Object.keys(dropHist).map(key => dropHist[key]).sort((a, b) => a.id - b.id);
|
|
let table_html = '';
|
|
history.forEach(e => {
|
|
table_html += `<tr><td>${ e.pos }</td><td>${ e.map }</td><td>${ e.name }</td><td>${ e.last }</td><td>${ e.isPassed ? '已取得' : '不确定' }</td></tr>`;
|
|
});
|
|
$tbody.innerHTML = table_html;
|
|
localStorage.setItem('wh-loot-store', JSON.stringify(dropHist));
|
|
ob.observe($root, { childList: true, subtree: true });
|
|
});
|
|
getDOMOb.observe($root, { childList: true, subtree: true });
|
|
}
|
|
} |