275 lines
12 KiB
TypeScript
275 lines
12 KiB
TypeScript
import Device from "../../enum/Device";
|
||
import WuhuBase from "../../class/WuhuBase";
|
||
import WuhuConfig from "../../class/WuhuConfig";
|
||
import CommonUtils from "../../class/utils/CommonUtils";
|
||
import Log from "../../class/Log";
|
||
import Alert from "../../class/utils/Alert";
|
||
import MathUtils from "../../class/utils/MathUtils";
|
||
import ActionButtonUtils from "../../class/utils/ActionButtonUtils";
|
||
|
||
export default async function attackHelper(): Promise<null> {
|
||
let { href, device } = WuhuBase.glob;
|
||
// 攻击页面
|
||
if (href.contains(/loader\.php\?sid=attack/)) {
|
||
let stop_reload = false;
|
||
const quickAttIndex = WuhuConfig.get('quickAttIndex');
|
||
const quickFinishAtt = WuhuConfig.get('quickFinishAtt');
|
||
const attReload = WuhuConfig.get('attReload');
|
||
|
||
// 光速刷新按钮
|
||
ActionButtonUtils.getInstance().add('光速刷新', doAttackReload);
|
||
|
||
// 自刷新
|
||
let audio_played_flag;
|
||
// @ts-ignore
|
||
if (attReload !== 6 && stop_reload !== true) {
|
||
const selector_device_map = {
|
||
'pc': '#defender div[class^="modal___"]',
|
||
'mobile': '#attacker div[class^="modal___"]',
|
||
'tablet': '',
|
||
};
|
||
const selector = selector_device_map[device];
|
||
CommonUtils.elementReady(selector).then(elem => {
|
||
if (!elem.querySelector('button')) {
|
||
if (WuhuConfig.get('attReload') === 0 && stop_reload !== true) {
|
||
doAttackReload();
|
||
} else {
|
||
let reload_flag;
|
||
const timeout = WuhuConfig.get('attReload') * 1000 + MathUtils.getInstance().getRandomInt(-500, 500);
|
||
Log.info(`[WH] ${ timeout / 1000 }s 后自动刷新`);
|
||
window.setInterval(() => {
|
||
if (reload_flag === undefined) {
|
||
reload_flag = true;
|
||
} else if (stop_reload !== true) {
|
||
// window.location.reload();
|
||
doAttackReload();
|
||
}
|
||
}, timeout);
|
||
}
|
||
} else if (audio_played_flag === undefined) {
|
||
audio_played_flag = true;
|
||
let play_time = 0;
|
||
const audio_play_id = window.setInterval(() => {
|
||
const $audio = document.createElement('audio');
|
||
$audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
|
||
$audio.play().then();
|
||
play_time++;
|
||
if (play_time === 3) clearInterval(audio_play_id);
|
||
}, 600);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 光速拔刀
|
||
if (quickAttIndex !== 6) {
|
||
const btn = await CommonUtils.elementReady('div[class^="modal___"] button');
|
||
Log.info(btn);
|
||
if (!btn.innerText.toLowerCase().includes('fight')) return;
|
||
// 判断是否存在脚踢
|
||
const hasKick = !!document.querySelector('#weapon_boots');
|
||
// modal层
|
||
const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
|
||
Log.info(`当前设备类型是${ device }`);
|
||
// 区分设备
|
||
switch (device) {
|
||
case Device.PC: {
|
||
Log.info(`开始调整按钮位置`);
|
||
// 隐藏modal层
|
||
modal.style.display = 'none';
|
||
// 根据选择的武器调整css
|
||
let css_top = '0';
|
||
switch (WuhuConfig.get('quickAttIndex')) {
|
||
case 1: { // weapon_second
|
||
css_top = '97px';
|
||
break;
|
||
}
|
||
case 2: { // weapon_melee
|
||
css_top = '194px';
|
||
break;
|
||
}
|
||
case 3: { // weapon_temp
|
||
css_top = '291px';
|
||
break;
|
||
}
|
||
case 4: // weapon_fists
|
||
case 5: { // weapon_boots
|
||
css_top = '375px';
|
||
break;
|
||
}
|
||
}
|
||
const css_rule = `
|
||
.wh-move-btn #defender div[class^="modal___"]{display: block;width: 0 !important;top: ${ css_top };left: -169px !important;}
|
||
.wh-move-btn #defender div[class^="dialog___"]{border:0;width:159px;height:96px;}
|
||
.wh-move-btn #defender div[class^="colored___"]{display:block;padding:0;}
|
||
.wh-move-btn #defender div[class^="title___"]{height:0;}
|
||
.wh-move-btn #defender button{width: 100%;margin:17px 0;height: 60px;}
|
||
`;
|
||
CommonUtils.addStyle(css_rule);
|
||
document.body.classList.add('wh-move-btn');
|
||
// 绑定点击事件 联动【光速跑路】
|
||
btn.onclick = () => {
|
||
if (quickFinishAtt !== 3) {
|
||
btn.remove();
|
||
// 停止自动刷新
|
||
stop_reload = true;
|
||
} else {
|
||
document.body.classList.remove('wh-move-btn');
|
||
}
|
||
};
|
||
break;
|
||
}
|
||
case Device.MOBILE: {
|
||
Log.info(`开始调整按钮位置`);
|
||
// 加入css
|
||
let css_top = '0';
|
||
let slot_height = '76px';
|
||
// 判断有没有脚踢
|
||
if (hasKick) {
|
||
// 根据选择的武器调整
|
||
switch (WuhuConfig.get('quickAttIndex')) {
|
||
case 1: { // weapon_second
|
||
css_top = '76px';
|
||
break;
|
||
}
|
||
case 2: { // weapon_melee
|
||
css_top = '152px';
|
||
break;
|
||
}
|
||
case 3: { // weapon_temp
|
||
css_top = '228px';
|
||
break;
|
||
}
|
||
case 4: { // weapon_fists
|
||
css_top = '304px';
|
||
break;
|
||
}
|
||
case 5: { // weapon_boots
|
||
css_top = '380px';
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
const slot = document.querySelector('#weapon_main') as HTMLElement;
|
||
const height = slot.offsetHeight + 1;
|
||
// TODO 待验证
|
||
slot_height = height + 'px';
|
||
// 根据选择的武器调整
|
||
switch (WuhuConfig.get('quickAttIndex')) {
|
||
case 1: { // weapon_second
|
||
css_top = `${ height }px`;
|
||
break;
|
||
}
|
||
case 2: { // weapon_melee
|
||
css_top = `${ height * 2 }px`;
|
||
break;
|
||
}
|
||
case 3: { // weapon_temp
|
||
css_top = `${ height * 3 }px`;
|
||
break;
|
||
}
|
||
case 4: { // weapon_fists
|
||
css_top = `${ height * 4 }px`;
|
||
break;
|
||
}
|
||
case 5: { // weapon_boots
|
||
css_top = `${ height * 5 }px`;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
const css_rule = `
|
||
.wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;}
|
||
.wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };}
|
||
.wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;}
|
||
.wh-move-btn #attacker div[class^="title___"]{height:0;}
|
||
.wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;}
|
||
`;
|
||
CommonUtils.addStyle(css_rule);
|
||
document.body.classList.toggle('wh-move-btn');
|
||
btn.onclick = () => {
|
||
if (WuhuConfig.get('quickFinishAtt') !== 3) {
|
||
btn.remove();
|
||
// 停止自动刷新
|
||
stop_reload = true;
|
||
} else {
|
||
document.body.classList.toggle('wh-move-btn');
|
||
}
|
||
};
|
||
break;
|
||
}
|
||
case Device.TABLET: {
|
||
break;
|
||
}
|
||
}
|
||
// 自动开打
|
||
if (WuhuConfig.get('autoStartFinish') === true) {
|
||
if (btn.innerText.includes('(')) {
|
||
let interval_id = window.setInterval(() => {
|
||
if (!btn) {
|
||
clearInterval(interval_id);
|
||
return;
|
||
}
|
||
try {
|
||
btn.click();
|
||
} catch {
|
||
}
|
||
}, 100);
|
||
} else {
|
||
btn.click();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 光速跑路
|
||
if (quickFinishAtt !== 3) {
|
||
const user_btn_select = ['leave', 'mug', 'hosp'][WuhuConfig.get('quickFinishAtt')];
|
||
const wrap = document.querySelector('#react-root');
|
||
Log.info('光速跑路选项选中:', user_btn_select);
|
||
new MutationObserver(() => {
|
||
const btn_arr = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
|
||
if (btn_arr.length > 1) btn_arr.forEach(btn => {
|
||
btn = btn as HTMLButtonElement;
|
||
const flag = btn.innerText.toLowerCase().includes(user_btn_select);
|
||
Log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
|
||
if (!flag) btn.style.display = 'none';
|
||
// 自动结束
|
||
else if (WuhuConfig.get('autoStartFinish') === true) {
|
||
try {
|
||
btn.click();
|
||
} catch {
|
||
}
|
||
}
|
||
});
|
||
}).observe(wrap, { subtree: true, attributes: true, childList: true });
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 错误的攻击页面
|
||
if (WuhuConfig.get('attRelocate') && href.includes('loader2.php')) {
|
||
const spl = window.location.href.trim().split('=');
|
||
const uid = spl[spl.length - 1];
|
||
if (!/^\d+$/.test(uid)) return;
|
||
window.location.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${ uid }`;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 战斗页面快速刷新
|
||
function doAttackReload() {
|
||
if (!window.ReactDOM) {
|
||
new Alert('光速刷新失败:未找到React对象');
|
||
return;
|
||
}
|
||
let react_root = document.querySelector('#react-root');
|
||
if (!react_root.querySelector('#attacker')) return;
|
||
let script = document.querySelector('script[src*="/builds/attack/"]');
|
||
let url = script.src;
|
||
if (!url.contains('app.js')) return;
|
||
window.ReactDOM.unmountComponentAtNode(react_root);
|
||
script.remove();
|
||
let node = document.createElement('script');
|
||
node.src = url;
|
||
node.type = 'text/javascript';
|
||
document.head.appendChild(node);
|
||
} |