wuhu-torn-helper/src/urlMatch.ts
2022-09-28 19:54:28 +08:00

948 lines
52 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import getWhSettingObj from "./func/utils/getWhSettingObj";
import cityFinder from "./func/module/cityFinder";
import elementReady from "./func/utils/elementReady";
import { missionDict } from "./dictionary/translation";
import getTaskHint from "./func/translate/getTaskHint";
import Device from "./enum/Device";
import WuhuBase from "./class/WuhuBase";
import Utils from "./class/utils/Utils";
import Log from "./class/Log";
import WuhuConfig from "./class/WuhuConfig";
import Alert from "./class/utils/Alert";
import InfoUtils from "./class/utils/InfoUtils";
export default class UrlPattern extends WuhuBase {
constructor() {
super();
}
static resolve() {
let { href, beer } = UrlPattern.glob;
// 捡垃圾助手
if (href.includes('city.php') && getWhSettingObj()['cityFinder']) {
cityFinder();
}
// pt一键购买
if (WuhuConfig.get('ptQuickBuy') && href.includes('pmarket.php')) {
new Alert('一键购买已开启');
// ns脚本
const rmv_cfm = (e) => {
let el = e.firstElementChild;
el.className += ' yes';
let old_href = el.getAttribute('href');
let new_href = old_href.replace(/=buy/, '=buy1').replace(/&points=\d{1,9}$/, '');
el.setAttribute('href', new_href);
};
let points_sales = document.querySelector('.users-point-sell');
for (const index in points_sales.children) {
'LI' === points_sales.children[index].tagName && rmv_cfm(points_sales.children[index])
}
new MutationObserver(e => {
for (const t of e) {
// for (const e of t.addedNodes) {
// 'LI' === e.tagName && rmv_cfm(e)
// }
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && rmv_cfm(e))
}
}).observe(points_sales, { childList: true });
}
// 叠e助手
if (href.includes('gym.php')) {
let cont = null;
const switch_node = document.createElement('div');
switch_node.innerHTML = `<label><input type="checkbox" ${ getWhSettingObj()['SEProtect'] ? 'checked' : '' }/> 叠E保护</label>`;
switch_node.id = 'wh-gym-info-cont';
switch_node.querySelector('input').onchange = e => {
let target = e.target as HTMLInputElement;
cont.classList.toggle('wh-display-none');
WuhuConfig.set('SEProtect', target.checked, true);
};
Utils.elementReady('#gymroot').then(node => {
cont = node;
if (getWhSettingObj()['SEProtect']) node.classList.add('wh-display-none');
node.before(switch_node);
});
}
// 啤酒店
if (href.includes('shops.php?step=bitsnbobs')) {
// 加入啤酒
elementReady('ul.items-list').then(node => {
const add_btn_node = document.createElement('div');
add_btn_node.id = 'wh-gym-info-cont';
add_btn_node.innerHTML = `<button style="color:white;">👉添加啤酒商品</button><p>如果当前商店没有啤酒这个商品可以提前显示以省去刷新步骤,增加抢酒成功率。</p><p id="wh-msg"></p>`;
add_btn_node.querySelector('button').addEventListener('click', e => {
const msg_node = add_btn_node.querySelector('#wh-msg');
if (node.querySelector('span[id="180-name"]')) {
msg_node.innerHTML = '❌ 页面已经有啤酒了';
return;
}
const clear_node = node.querySelector('li.clear');
const beer = document.createElement('li');
beer.classList.add('torn-divider', 'divider-vertical');
beer.style.backgroundColor = '#c8c8c8';
beer.innerHTML = `<div class="acc-title">
<span class="item-desc">
<span tabindex="0" aria-labelledby="180-name 180-price 180-stock" class="item Alcohol" itemid="180" loaded="0">
<img class="torn-item item-plate" data-size="large" src="/images/items/180/large.png" alt="Bottle of Beer" style="opacity: 0;" id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f" data-converted="1" aria-hidden="true">
<span class="item-hover">
<button class="view-h wai-btn" aria-label="Show info: Bottle of Beer" value="100" i-data="i_723_228_51_52"></button>
<button class="buy-h wai-btn" aria-label="Buy: Bottle of Beer" value="100" i-data="i_774_228_51_52"></button>
</span>
<canvas id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f" role="img" aria-label="Bottle of Beer" style="opacity: 1;" class="torn-item item-plate item-converted" item-mode="light" width="100" height="50"></canvas></span>
<span class="desc">
<span id="180-name" class="name t-overflow bold">啤酒</span>
<span id="180-price" class="price t-gray-6" data-sell="$5">$10</span>
<span id="180-stock" class="stock t-gray-6 t-overflow">酒 (<span class="instock">1100</span>存货)</span>
</span>
<span class="buy-act-wrap">
<label for="180" class="wai">Amount
of Bottle of Beer</label>
<input id="180" type="text" value="100" maxlength="3" name="buyAmount[]" autocomplete="new-amount">
<span class="buy-act bold">
<button class="wai-support t-blue h">买</button>
<div class="tt-max-buy-overlay"></div>
</span>
</span>
</span>
<div class="confirm-wrap">
<span class="confirm">
<span>
点击确定购买
</span>
<span>
<span class="count">100</span>
瓶啤酒
$<span class="total">1,000</span>
</span>
<span class="confirm-act m-top5">
<a href="#" class="wai-support yes m-right10 bold t-blue h" data-id="180" i-data="i_819_263_23_16">
确定
</a>
<span class="no bold">
<a href="#" class="wai-support t-blue h" i-data="i_852_263_18_16">
</a>
</span>
</span>
</span>
</div>
<div class="success-wrap">
<span class="success">
<span class="t-red bold">
<span class="ajax-preloader"></span>
</span>
</span>
<button aria-label="Close" class="close-icon p0 wai-btn" value="100" i-data="i_954_228_10_11"></button>
</div>
<div class="msg-wrap">
<span class="t-green bold">
<span class="ajax-preloader"></span>
</span>
</div>
</div>
<div class="view-item-info">
<div class="item-cont">
<div class="item-wrap">
<span class="ajax-preloader m-top10 m-bottom10"></span>
</div>
</div>
</div>`;
if (clear_node) clear_node.before(beer);
else node.append(beer);
(<MyHTMLElement>e.target).remove();
msg_node.innerHTML = '添加成功';
});
document.querySelector('.content-wrapper').prepend(add_btn_node);
});
// 监听啤酒购买
$(document).ajaxComplete((_, xhr, settings) => {
Log.info({ xhr, settings });
let { data } = settings, { responseText } = xhr;
let response = JSON.parse(responseText);
if (data.includes('step=buyShopItem') && data.includes('ID=180') && response['success']) {
new Alert('已检测成功购买啤酒')
beer.skip_today();
}
});
}
// 快速crime TODO 重构、与翻译解藕
if (href.contains(/crimes\.php/) && getWhSettingObj()['quickCrime']) {
if (self !== top) {
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
elementReady('#header-root').then(e => e.style.display = 'none');
elementReady('#sidebarroot').then(e => e.style.display = 'none');
elementReady('#chatRoot').then(e => e.style.display = 'none');
if (!isValidate) document.body.style.overflow = 'hidden';
elementReady('.content-wrapper').then(e => {
e.style.margin = '0px';
e.style.position = 'absolute';
e.style.top = '-35px';
});
elementReady('#go-to-top-btn button').then(e => e.style.display = 'none');
}
const $$ = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe($$, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const trans = () => {
const dom = `<div class="wh-translate"><div class="title-black" style="border-radius: 5px 5px 0 0;"><span>常用犯罪</span></div><div class="cont-gray" style="padding: 6px 0;border-radius: 0 0 5px 5px;">
<!--18-1-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="18">
<input name="crime" type="hidden" value="hackbank">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;" type="submit" value="18-1" />
</form>
<!--15-3-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="15">
<input name="crime" type="hidden" value="napcop">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;" type="submit" value="15-3(慎)" />
</form>
<!--仓库-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="11">
<input name="crime" type="hidden" value="warehouse">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;" type="submit" value="烧仓库" />
</form>
<!--7-2-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="7">
<input name="crime" type="hidden" value="thoroughrobbery">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;" type="submit" value="7-2(仅过渡用)" />
</form>
<!--偷夹克-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="4">
<input name="crime" type="hidden" value="jacket">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;" type="submit" value="偷夹克" />
</form>
<!--卖碟3-1-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="3">
<input name="crime" type="hidden" value="cdrock">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;" type="submit" value="卖碟" />
</form>
<!--捡钱-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="2">
<input name="crime" type="hidden" value="searchtrainstation">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;" type="submit" value="捡钱" />
</form>
</div><hr class="page-head-delimiter m-top10 m-bottom10 r1854"></div>`;
const is_wh_translate = $$.querySelector('.wh-translate') !== null;
const is_captcha = $$.querySelector('div#tab-menu.captcha') !== null;
const $title = $('div.content-title');
const $info = $('.info-msg-cont');
if (!is_wh_translate && !is_captcha) {
if ($title.length > 0) $title.before(dom);
else if ($info.length > 0) $info.before(dom);
}
};
trans();
OB.observe($$, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 任务助手 TODO 重构、与翻译解藕
if (href.contains(/loader\.php\?sid=missions/) && getWhSettingObj()['missionHint']) {
const $$ = $('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe($$.get(0), {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const taskList = {};
const trans = () => {
$('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => {
if ($(e).children().hasClass('mission-complete-icon')) {
taskList[i] = e.innerText.trim();
} else {
taskList[i] = $(e).clone().children().remove().end().text().trim();
}
});
// 助手注入
$('div.max-height-fix.info').each((i, e) => {
if ($(e).find('.wh-translated').length !== 0) return;
$(e).append(`<div class="wh-translated"><h6 style="color:green"><b>任务助手</b></h6><p>${ getTaskHint(taskList[i]) }</p></div>`);
});
// 任务目标
$('ul.tasks-list span.title-wrap').contents().each((i, e) => {
if (e.nodeType === 3) {
if (missionDict[e.nodeValue.trim()]) {
e.nodeValue = missionDict[e.nodeValue.trim()];
}
}
});
};
trans();
OB.observe($$.get(0), {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 圣诞小镇
if (href.contains(/christmas_town\.php/)) {
let $root = document.querySelector('#christmastownroot');
const { xmasTownWT, xmasTownNotify } = getWhSettingObj()
// 解密攻略
if (xmasTownWT) {
const insert_html = `<div id="wh-xmas-cont">
<div class="title-black"><span>水晶球解密地图攻略</span><span><button style="color: white">[隐藏]</button></span></div>
<div class="cont-gray select-wrap dropdown-new dropdown-default">
<select>
<option value="None">未选择</option>
<option value="Christmas Town">Christmas Town</option>
<option value="Maltese Snow Globe">Maltese Snow Globe</option>
<option value="Long way from home">Long way from home</option>
<option value="Chedburn Towers">Chedburn Towers</option>
<option value="Kidnapped Santa">Kidnapped Santa</option>
<option value="Holiday terror">Holiday terror</option>
<option value="Among Us">Among Us</option>
<option value="Kiss My Festivus">Kiss My Festivus</option>
<option value="Stanley Hotel">Stanley Hotel</option>
<option value="DoggoQuest">DoggoQuest</option>
<option value="Pokemon CT">Pokemon CT v2.0</option>
<option value="Winter in Gatlin">Winter in Gatlin</option>
</select>
<div>
<p>来源Torn City公众号图文详情请查看公众号文章</p>
<div id="wt-content"></div>
</div>
</div>
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
</div>
<style>
#wh-xmas-cont .cont-gray{
padding: 0.5em;
}
#wh-xmas-cont p,#wh-xmas-cont select,#wh-xmas-cont li{
margin: 0 0 3px;
}
</style>`;
const wt_dict = {
"None": { title: '', wt: ``, },
"Christmas Town": {
title: '圣诞小镇', wt: `<ul>
<li>旧攻略提到的驯鹿车已被移除,只能手动找一条蓝色的小路[94,3]</li>
<li>向南走,然后上木桥,沿着它向西走到达冰湖</li>
<li>在冰湖[55,7][61,64]附近找Labyrinth传送门进入迷宫</li>
<li>迷宫的出口在中间的方向[395,397]一个冰湖,走进冰湖传送</li>
<li>走到企鹅</li>
</ul>`,
},
"Maltese Snow Globe": {
title: 'Maltese Snow Globe', wt: `<ul>
<li>1.想办法进入前几层的楼梯口</li>
<li>2.出来之后往南走, 在码头找到天鹅船</li>
<li>3.按着数字1-12走过乐高博物馆</li>
<li>4.跟着大路走到天鹅船。</li>
<li>5.走到901,486的银行</li>
<li>6.最左上的楼梯</li>
<li>7.B-D-C-E-F-G-C-A</li>
<li>8.右,右,右,北,北,右,右</li>
<li>9.走到右上角铁路</li>
<li>10.小游戏:</li>
<li>移动1到最右移动2到中间移动1到2上面,移动3到最右,移动1到最左,移动2到3.上面移动1到2上面。</li>
<li>11.往上走出铁丝网往左绕一个大圈走到300,476</li>
<li>12.走到363,406的隧道走到361,400的隧道 ,往南走。</li>
<li>13.走到352,334的迷宫好像有好几条路,我说我的走法,往左下走,走倒最下了往右走走到1个不一样的绿色的时候往上走。</li>
<li>14.走到迷宫中间的小人,后面就只有一条路走了,完成。</li>
</ul>`,
},
"Long way from home": {
title: 'Long way from home', wt: `<ul>
<li>1.随便动一下</li>
<li>2.左边的管道口</li>
<li>3.右走到十字路口,往上,往右,从偏左的那个管道往上。</li>
<li>3.出小门,往右到底,往上到底,往右,进上面房间,右上角的电脑,电脑显示的是下面房间的走法,任意移动退出</li>
<li>4.去下面房间,右边橙色电力符号,进入解密。下,右下,右下,右上,右上,右,右下,右下,下,左下,左下,</li>
<li>左,左,左下,左下,进圈。</li>
<li>5.进入新的房间按钮</li>
<li>6.一直左走,走到有两个怪兽把手的桥那,进上面的房间,左上角的机器,*是重输密码</li>
<li>作者随时改密码,建议看纸条上的提示自己去数</li>
<li>7.桥上怪兽消失, 往左走到底,按钮</li>
<li>8.右走走到雪地走大路按钮开铁门上darkforest的蓝车</li>
<li>9.右走十几步,传送</li>
<li>10.右下走,看到铁丝网,顺着铁丝网右走,有个缺口,进去。</li>
<li>11.右走,直到看见三颗倒下的圣诞树(记住这里),顺着血迹和脚印走,进山洞。</li>
<li>12.顺着山洞走到一滩血,原路出山洞。</li>
<li>13.原路回到三颗倒下的圣诞树,正上方有个红色仓库,进入。</li>
<li>14.上,上,上,右,上,左,上,路就通了,去拿到右上角的锯子,原路出仓库。</li>
<li>15.出来就在车下面,上车,再上车。</li>
<li>16.左边的小橘人,完成</li>
</ul>`,
},
"Chedburn Towers": {
title: 'Chedburn Towers', wt: `<ul>
<li>进入地图后使用附近的FAST的T下方的厕所传送到Chedburn Towers</li>
<li>进入大厅,"之"字形上楼,每层都是如此。</li>
<li>最终会进入问答题区域,通过在相应的数字上穿过来回答问题</li>
<li>答案是3 9 5 4 9 2 6 8</li>
<li>答题后进入Ched的办公室向西走然后一直走到左边的楼梯上</li>
<li>向南走下楼梯,然后向东走,沿着小楼梯到地下室</li>
<li>向东走到牢房区域</li>
<li>先踩下开关,打开牢房门前往右上角的最后一个牢房</li>
<li>开关位于JAIL文字的左上方</li>
<li>沿着挖出来的隧道一直走,岔路口向左走</li>
<li>到金库Chedburn NPC会给你本地图的水晶球</li>
</ul>`,
},
"Kidnapped Santa": {
title: 'Kidnapped Santa', wt: `<ul>
<li>出生在一个类似城镇的地方</li>
<li>沿着这条路向东走,然后向南走</li>
<li>到达道路尽头的一个码头时,向西走一段路,踩在精灵的上面,乘坐渡船[124, -30]</li>
<li>搭船来到了Fantasy Island</li>
<li>小心那个游荡的<span style="color: #32CD32">绿色NPC</span>,不惜一切代价避开他,否则他会把你打回出发点</li>
<li>向西走,然后向北走,再向西绕过岩石。要非常小心,不要踩到水里或掉下悬崖,否则你会死</li>
<li>然后回到南边,在那里你会看到一些门</li>
<li>走进蓝色的门(左二)[111-60]</li>
<li>过了蓝门后继续沿路向南</li>
<li>然后沿路向东,再向南</li>
<li>再向东走,会看到“恐怖之家”,进入这栋楼[137, -84]</li>
<li>向北走,进入洞口[164, -81]</li>
<li>穿过隧道到达另一端的洞穴口[142, -63]<b>避开所有怪物和NPC</b></li>
<li>来到另一个岛上</li>
<li>向南走,然后向东绕过建筑物,可以进入圣诞老人的洞穴[133, -2]</li>
<li>在建筑物内向西走再向北走在圣诞老人家work shop的东北角你会看到一个楼梯走下去[1694]</li>
<li>在这一区域,<b>要避开所有出现破损或有异样的地砖</b>也要避开四处游荡的邪恶的格林奇NPC</li>
<li>沿着地牢里的走廊向东走,然后向南走,避开所有看起来不同的瓷砖</li>
<li>它们上面有一些小裂缝和花纹,如果你是用手机的话,我建议你把亮度调高,以防万一</li>
<li>最终会看到一个发绿光的小开关</li>
<li>走到开关上[165, 18],激活它,然后进入向北打开的大门</li>
<li>走到<span style="color: gold">黄色精灵NPC</span>脸上[16625],可以得到本地图的水晶球</li>
</ul>`,
},
"Holiday terror": {
title: 'Holiday terror', wt: `<ul>
<li>1. 从出生地沿着路向东,然后向北。过桥并沿着穿过城镇的小路继续前行,避开任何明显的陷阱(道路上的洞、打开的井盖等)。</li>
<li>2. 继续向东和向北前进,直到到达 Mansion's Labyrinth豪宅迷宫[121,29]</li>
<li>3. 豪宅入口在[131,41]</li>
<li>4. 进入豪宅后向北走,你会看到一条由骷髅守卫的道路</li>
<li>5. 沿着棕色的小路走,在黑色的<b>区域前</b>停下</li>
<li>6. 按照如下的方式行进</li>
<li> 上3格左2上2右4下1右3上6左2下1左6下2左2上4右5上4</li>
<li>7. 来到一个区域,在这里你必须在两个洞穴中做出选择</li>
<li>第一次选择答案是Christmas Miracle选择左边的洞窟。</li>
<li>第二次选择答案是24/12/2019选择左边的洞窟。</li>
<li>第三次选择答案是Hohoho Coldington选择右边的洞窟。</li>
<li>第四次选择答案是Christmas Miracle Cave选择左边的洞窟。</li>
<li>8. 出现在一个用糖果棒装饰的红色地板的房间里,去地图的右上角一个冰洞的入口[101-74]</li>
<li>9. 进入冰洞。向西走寻找叫Erik the last elf的黄色小NPC</li>
<li>10. 拿到水晶球</li>
</ul>`,
},
"Among Us": {
title: 'Among Us', wt: `<ul>
<li>出生点步行到传送点进入地图 1 [399,12]</li>
<li>到达地图1你出现在食堂往下走绕到红色按钮处[502-1]</li>
<li>答案D B A A D D B B B C A D D D 最终: B (Green)</li>
<li>然后你会被传送到地图2</li>
<li>在地图2中你需要沿着小路向南走然后向东进入通风口前往下一个部分[55624]</li>
<li>穿过通风口后,进入食堂。向南走到红色按钮所在的位置 [571,32]</li>
<li>答题阶段答案如下BBACBDC A</li>
<li>被传送到地图3</li>
<li>先直接向南走一点,再沿着走廊走。进入左边的一个通风口[345170]</li>
<li>会传送到办公室,在那里找到最后一个红色按钮[356173]</li>
<li>答题阶段答案如下CCADABBCD</li>
<li>进入"PEEP SHOW",获得本地图的水晶球</li>
</ul>`,
},
"Kiss My Festivus": {
title: 'Kiss My Festivus', wt: `<ul>
<li>从起点出发沿着小路向北走到出租车处乘坐前往Dark Forest的出租车 [96,16]</li>
<li>沿着公路向东走,继续向东进入雪地</li>
<li>沿着暗淡的蓝色轨迹向东南方向走,穿过树林,直到你到达一个铁栅栏[坐标为114,-89]</li>
<li>铁栅栏进不去。有人会告诉你乘坐他们的雪地车。</li>
<li>向西走到雪地车旁,注意不要踩到任何<b>冬青树</b>(鲜艳黄红色的矮树),否则你将回到起点。</li>
<li>被传送到锯木厂,在伐木工那里获得钥匙。</li>
<li>然后向南走,然后向东走(向东走很长一段路),沿着小路返回铁栅栏处。</li>
<li>来到一个炫酷的45°视角迷宫你要走到地图的东北部抵达另一个洞穴口[156,-74]</li>
<li>先往左下方走到岔路口,然后往右上方走,接下来将只有一条路</li>
<li>到达岛屿沿着小楼梯上去,绕到正下方那艘天鹅船</li>
<li>到一个新的岛屿,向南走几步,踩在[12, -79]的蓝色火花上</li>
<li>被传送到另一个有几辆拖车的岛上</li>
<li>向北走,进入一个新的山洞口</li>
<li>人被挡住了,要在冰层下向西北方向一直走,主要是向上和向左走</li>
<li>沿着这条路一直往上走,然后在开阔的地方往东走,你会看到一座房子[房子的入口在26,58]</li>
<li>进入房子,向北走几步,穿过闪闪发光的入口,你就可以进入房子了</li>
<li>沿着东南方向走你会看到Evil-Duck NPC他将给你本地图的水晶球</li>
</ul>`,
},
"Stanley Hotel": {
title: 'Stanley Hotel', wt: `<ul>
<li>从起点开始,你会看到正北方有一座房子。向北走几步到门前,进入房子。</li>
<li>传送到一个有门的地方。绕过并向上走,激活位于[188,72]的大门开关。</li>
<li>向东北方向前进,沿着血迹穿过森林,直到你到达一个山洞。</li>
<li>依次使用使用防御(踩盾牌标记),然后攻击(剑),然后魔法(闪亮的蓝色气泡)来杀死怪物。</li>
<li>最后你会来到工人Bob的房间他将给你本地图的水晶球。</li>
</ul>`,
},
"DoggoQuest": {
title: 'DoggoQuest', wt: `<ul>
<li>你出现在一个房间里</li>
<li>向东走,然后向南走,沿着小走廊就可以离开这个房间</li>
<li>来到这个地牢的01层</li>
<li>首先向南走,然后绕过墙,攻击你看到的第一个怪物[101,1]</li>
<li>然后向西走到墙边,向北攻击<span style="color: #32CD32">史莱姆</span></li>
<li>继续向北,攻击下一个<span style="color: gold">怪物</span></li>
<li>向北走到拐角处,然后向东走到楼梯处继续前进[坐标为101,1]</li>
<li>来到第二层,直接向东走上楼梯[11-19]</li>
<li>来到了这个地牢的第03层</li>
<li>向东再向南走到墙边,然后向东走,与绿色<span style="color: #32CD32">史莱姆</span>战斗</li>
<li>继续向东走,经过被打败的史莱姆,然后向南和向西绕过墙,向北走一格,向西打败另一个<span style="color: #32CD32">史莱姆</span></li>
<li>向西南方向走下楼梯[53-49]</li>
<li>来到了第 04 层</li>
<li>走到墙边,撞右边两个镣铐之间的墙,然后向北直接走到墙里[15-65]</li>
<li>直接向北走,踏上红色的东西</li>
<li>沿着楼梯向南和东南方向走右边楼梯[39-69]</li>
<li>来到第5层</li>
<li>向北走,然后向西绕过中间的十字架,向南走到下一个楼梯[29-93]</li>
<li>来到第 6 层</li>
<li>杀死那只<span style="color: #32CD32">大绿狗</span></li>
<li>回到刚才的楼梯来到05层[33-114]</li>
<li>在第05层你会看到原来的十字架位置附近出现了新的楼梯口</li>
<li>走上该楼梯[54, -99]</li>
<li>到达了最后的?层</li>
<li>沿着小路向下走然后沿着冰冷的台阶走到Rudolph NPC</li>
<li>在他身边来回走动</li>
<li>踩在他身上的次数足够多时Rudolph会把该图的水晶球交给你</li>
</ul>`,
},
"Pokemon CT": {
title: 'Pokemon CT', wt: `<ul>
<li>宝可梦新增了战斗系统,路过高草丛会几率进入战斗</li>
<li>战斗系统为一个十字形界面,上:技能/精灵球捕捉,下:逃跑,左:回血,右:攻击</li>
<li>战斗守则攻击当你血量为33时回血</li>
<li>打败最终BOSS需要捕捉两只捕捉地点</li>
<li>一:把包裹交给大木博士后,去常磐市的路上</li>
<li>二:进入森林后遇到的毛毛虫</li>
<li>捕捉时需要将其打到残血。</li>
<li>最终BOSS打法</li>
<li>第一个敌方精灵,毛虫进化的蝴蝶,先放技能,使其眩晕,在眩晕期间攻击,一旦醒过来就眩晕,重复。</li>
<li>第一个BOSS死后第二个BOSS会秒杀蝴蝶 此时用第二个精灵。</li>
<li>第二个精灵打法:攻击看见它放absorbing技能就去回血(当然你没血了也要去回血),重复。</li>
<li>【游戏开始】</li>
<li>出生在你房间的二楼</li>
<li>下楼梯离开房间。走出家门。从那里向东北方向进入高草丛将被传送到大木博士Professor Oak的实验室</li>
<li>踩大木博士</li>
<li>踏上桌子,选择你的宝可梦</li>
<li>现在出门去常磐市Veridian City拿一个包裹</li>
<li>离开大木博士的实验室向北走穿过草地前往常磐市Veridian City</li>
<li>进入城市后,前往 Poke Mart [134-3]</li>
<li>回到大木博士的实验室,返回时可以跳下小路西侧的山崖,避开高草丛</li>
<li>把包裹交给大木博士后。回常磐市</li>
<li>在房子和两个精灵之间的小路上继续向北走,穿过城市[79,-21]</li>
<li>过了精灵后一路向北</li>
<li>进入一所房子,经过它才能进入常磐森林</li>
<li>穿过常磐森林才能到达尼比市</li>
<li>森林的入口向东走,直到看到高草,然后向北走,直到下一片高草</li>
<li>绕过树木向东走,然后向北走</li>
<li>现在绕过树木向西走,然后向北走</li>
<li>然后穿过草地向西和向南走</li>
<li>沿着这条小路蜿蜒穿过高高的草丛</li>
<li>沿着小路穿过草地,最终离开森林</li>
<li>离开森林后,沿着草丛旁小路向北走,到达 Pewter City。向北向西绕到大房子处到达道馆</li>
<li>走到大胡桃夹子前,挑战小刚</li>
<li>赢得这场战斗后你会被带到大木博士那里,他会给本地图的水晶球</li>
</ul>`,
},
"Winter in Gatlin": {
title: 'Winter in Gatlin', wt: `<ul>
<li>从出生点出发</li>
<li>往右走到达树林,往右上走跨过铁栅栏,再往右走,经过红车时从右边缝隙穿过往下走</li>
<li>沿公路向下走到第一个岔路向右走到废弃的小屋[14,80]</li>
<li>进入小屋时,你会在一个黑色的小房间里,走到亮起的圆圈处</li>
<li>在下一个房间里,会有一连串的数字,按以下顺序走到数字上</li>
<li>1,4,6,8,7,6,4</li>
<li>在最后一个房间Epic_Heasley NPC 会给你本图的水晶球</li>
</ul>`,
},
};
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 = `<div id="wh-loot-container" class="m-bottom10">
<audio src="https://www.torn.com/js/chat/sounds/Chirp_3.mp3" style="display:none"></audio>
<div class="title-black"><span>附近物品</span></div>
<div id="wh-loot-container-main" class="cont-gray">
<b>物品</b><span id="wh-loot-item-count"></span>
<div id="wh-loot-container-items"></div>
<b>箱子</b><span id="wh-loot-chest-count"></span>
<div id="wh-loot-container-chests"></div>
</div>
<div id="wh-loot-container-ex" class="cont-gray wh-hide">
<div><label><input type="checkbox" id="wh-loot-setting-blink" ${ alertSettings.blink === 'y' ? 'checked' : '' } /> 闪烁提示</label></div>
<div><label><input type="checkbox" id="wh-loot-setting-sound" ${ alertSettings.sound === 'y' ? 'checked' : '' } /> 声音提示 <del>(iOS)</del></label></div>
<div><label><input type="checkbox" id="wh-loot-setting-chest" ${ alertSettings.chest === 'y' ? 'checked' : '' } /> 不记录需要钥匙的宝箱</label></div>
<div id="wh-hist">
<div id="wh-hist-clear">
<p><button>清空数据</button>- 长时间不清空会出现奇怪的问题</p>
</div>
<table><thead><tr><th colspan="5">历史记录</th></tr><tr><th>坐标</th><th>地图</th><th>类型</th><th>发现</th><th>获取</th></tr></thead><tbody></tbody></table>
</div>
</div>
<div id="wh-loot-btn" class="cont-gray"><button>设置</button></div>
</div>
<style>
#wh-loot-container-main{padding: 0.5em;}
#wh-loot-container-main div{overflow-x: auto;overflow-y: hidden;white-space: nowrap;min-height: 4em;}
#wh-loot-container-main div span{display: inline-block;background-color: #2e8b57;color: white;margin: 0 1em 0 0;border-radius: 4px;padding: 0.5em;}
#wh-loot-container-main div span img{height: 1em; width: 1em;}
#wh-loot-container-ex{padding: 0.5em;}
#wh-loot-container-ex.wh-hide{display: none;}
#wh-loot-container-ex #wh-hist{overflow-x: auto;}
#wh-loot-container-ex table {margin-top: 0.5em;}
#wh-loot-container-ex tbody {background-color: antiquewhite;}
#wh-loot-container-ex table, #wh-loot-container-ex th, #wh-loot-container-ex td {
padding: 5px;
border: 1px solid black;
height: auto;
}
#wh-loot-container-ex th:nth-child(1) {min-width: 5em;}
#wh-loot-container-ex th:nth-child(2) {min-width: 8em;}
#wh-loot-container-ex th:nth-child(3) {min-width: 4em;}
#wh-loot-container-ex th:nth-child(4) {min-width: 9em;}
#wh-loot-container-ex th:nth-child(5) {min-width: 3em;}
#wh-loot-container-ex thead {
background-color: #2e8b57;
color: white;
}
@keyframes lootFoundAlert {
0% {background: #f2f2f2}
50% {background: #2e8b57}
100% {background: #f2f2f2}
}
</style>`;
$($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 });
}
}
// rw雷达
if (href.includes('profiles.php?XID=0')) {
const utl = {
set: function (k, v) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
obj[k] = v;
localStorage['wh_rw_raider'] = JSON.stringify(obj);
},
get: function (k) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
return obj[k];
},
setFactionID: function (id) {
this.set('faction', id);
},
setRWFactionID: function (id) {
this.set('rw_faction', id);
},
getFactionID: async function (apikey) {
const response = await fetch('https://api.torn.com/faction/?selections=basic&key=' + apikey);
const res_obj = await response.json();
const faction_id = res_obj['ID'];
if (faction_id) {
this.setFactionID(faction_id);
return faction_id;
} else return -1;
},
getRWFactionID: function (apikey) {
},
};
const rw_raider = async function () {
if (href.includes('#rader')) {
Utils.addStyle('div.content-title,div.info-msg-cont{display:none;}');
const wh_node = document.createElement('div');
wh_node.id = 'wh-rd-cont';
wh_node.innerHTML = `<div class="m-top10">
<h4 id="skip-to-content" class="left">RW 雷达</h4>
<div class="clear"></div>
<hr class="page-head-delimiter">
</div>
<div class="content m-top10">
<a href="/profiles.php?XID=2687093" target="_blank">woohoo</a>
<table>
<thead>
<tr><th>123</th><th>456</th></tr>
</thead>
<tbody>
<tr><td>789</td><td>012</td></tr>
</tbody></table>
</div>`;
// 原页面完全加载
await elementReady('div.msg[role="alert"]');
const t_cont = document.querySelector('div.content-wrapper');
// t
t_cont.append(wh_node);
}
};
addEventListener('hashchange', rw_raider);
rw_raider().then();
}
// 特定代码块 TODO 修复
if (InfoUtils.getInstance().getPlayerInfo().userID === 2687093 && Utils.getDeviceType() === Device.PC) {
InfoUtils.getInstance().getSidebarData().then(data => {
Log.info({ data })
let item = document.getElementById('nav-items');
if (item) {
let copy = item.cloneNode(true);
// TODO 待验证
(<HTMLElement>copy.firstChild).style.backgroundColor = '#ff5722';
// copy.firstChild.style.backgroundColor = '#ff5722';
let a = copy.firstChild.firstChild as HTMLAnchorElement;
a.href = '/item.php?temp=1';
let span = a.lastChild as HTMLElement;
span.innerHTML = '物品';
span.style.color = 'white';
item.after(copy);
}
});
}
}
}