HWM Pointer

try to take over the world!

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         HWM Pointer
// @namespace    https://greasyfork.org/ru/scripts/424028-hwm-pointer
// @version      0.4
// @description  try to take over the world!
// @author       achepta
// @include     /^https{0,1}:\/\/((www|qrator|my)(\.heroeswm\.ru|\.lordswm\.com)|178\.248\.235\.15)\/war\.php.+/
// @grant       unsafeWindow
// @grant    GM_xmlhttpRequest
// @grant    GM_log
// @run-at document-end
// ==/UserScript==

(function (window, undefined) {
	//TODO add message processing queue
	let w;
	if (typeof unsafeWindow !== undefined) {
		w = unsafeWindow;
	} else {
		w = window;
	}
	if (w.self !== w.top) {
		return;
	}
	let allPlayers = getPlayers()
	let coordsData = ""
	let isPressed = false
	let allMessages = getAllMessages()

	let isSettingsOpened = false;
	let defaultSettings = getDefaultSettings()
	let settings = {}
	loadSettings()

	setInterval(checkChatForCoords, 300)

	function checkChatForCoords() {
		let newMessages = getAllMessages();
		if (newMessages.length > allMessages.length) {
			allMessages = newMessages
			checkMessageForCoords(allMessages.slice(-1)[0])
		}
	}

	function checkMessageForCoords(msg) {
		if (msg.includes("!")) {
			let coords = findAll(/\|(\d{1,2}):(\d{1,2})/, msg)
			if (coords.length > 0) {
				setChatCoordsListener(coords)
				highlightCoords(coords)
			}
		}
	}

	function setChatCoordsListener(coords) {
		let msgWithCoords = Array.from(getChat().getElementsByTagName("b")).slice(-1)[0]
		msgWithCoords.id = "coords" + allMessages.length
		$(`coords${allMessages.length}`).addEventListener('mouseover', () => showCoordsMouse(coords))
		$(`coords${allMessages.length}`).addEventListener('mouseout', () => hideCoordsMouse(coords))
	}

	function showCoordsMouse(coords) {
		coords.forEach(coordinate => {
			showCoords(coordinate)
		})
	}

	function hideCoordsMouse(coords) {
		coords.forEach(coordinate => {
			hideCoords(coordinate)
		})
	}

	function highlightCoords(coords) {
		coords.forEach(coordinate => {
			showCoords(coordinate)
			setTimeout(() => {
				hideCoords(coordinate)
			}, settings.duration)
		})
	}

	function showCoords(coordinate) {
		shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].stroke(settings.color);
		shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].fill(settings.color);
		set_visible(shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn], 1);
	}

	function hideCoords(coordinate) {
		shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].stroke('red');
		shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].fill(null);
		set_visible(shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn], 0);
	}

	window.addEventListener("keydown", e => {
		if ((document.querySelector("#chattext") !== document.activeElement) && (document.querySelector("#chattext_classic") !== document.activeElement)) {
			if (!isSettingsOpened && e.shiftKey && ["f", "F", "а", "А"].includes(e.key)) {
				isSettingsOpened = true;
				openSettings()
				e.preventDefault()
				return
			}
			if (!isSettingsOpened && ["f", "F", "а", "А"].includes(e.key)) {
				if (!isPressed) {
					coordsData = "";
					coordsData += "|" + xr_last + ":" + yr_last
					isPressed = true
				}
			}
		}
	})

	window.addEventListener("keyup", e => {
		if ((document.querySelector("#chattext") !== document.activeElement) && (document.querySelector("#chattext_classic") !== document.activeElement)) {
			if (!isSettingsOpened && ["f", "F", "а", "А"].includes(e.key)) {
				let newCoords = "|" + xr_last + ":" + yr_last
				if (newCoords !== coordsData) {
					coordsData += " " + newCoords
				}
				isPressed = false
				createAndSendMessage();
			}
		}
	})

	function openSettings() {
		showEmptyBackground();
		document.body.insertAdjacentHTML('beforeend', getSettingsTemplate())
		fillSettings()
	}

	function showEmptyBackground() {
		document.body.insertAdjacentHTML('beforeend', getEmptyBackgroundTemplate());
		$('empty_background').addEventListener('click', handleOnBackgroundClick);
	}

	function hideEmptyBackground() {
		removeElement($('empty_background'))
	}

	function fillSettings() {
		$('coords-color').addEventListener('input', () => {
			handleChangeColor()
		})
		$('coords-duration-btn').addEventListener('click', () => {
			handleChangeDuration()
		})
		$('coords-duration').addEventListener('keyup', e => {
			if (e.key === 'Enter' || e.keyCode === 13) {
				handleChangeDuration()
			}
		})
	}

	function handleChangeDuration() {
		let inputValue = $('coords-duration').value - 0
		if (!isNaN(inputValue) && inputValue !== 0) {
			settings.duration = inputValue
			handleSettingsChange()
		}
	}

	function handleChangeColor() {
		settings.color = $('coords-color').value
		handleSettingsChange()
	}

	function handleSettingsChange() {
		set('hwm_pointer_settings', settings)
	}

	function hideSettings() {
		removeElement($('hwm_pointer_settings'))
	}

	function handleOnBackgroundClick() {
		isSettingsOpened = false;
		hideEmptyBackground();
		hideSettings();
	}

	function getEmptyBackgroundTemplate() {
		return `
        <div id="empty_background" style="
            position: fixed; 
            left: 0; 
            top: 0;
            width: 100%;
            height: 100%;
            background: #000000;
            opacity: 0.5;
            z-index: 11000001;
        "></div>
        `
	}

	function getSettingsTemplate() {
		return `
        <div id="hwm_pointer_settings" style="
            position: fixed;
            left: ${(getClientWidth() - 300) / 2}px;
            top: ${window.pageYOffset + 155}px;
            width: 300px;
            background: #F6F3EA;
            z-index: 11000002;
            padding: 20px;">
            <label for="coords-color">Select your favorite color:</label>
  			<input type="color" id="coords-color" name="coords-color" value="${settings.color}">
  			<br>
  			<span>Duration in ms <input id="coords-duration" type="text" style="width: 40px" value="${settings.duration}">
  			<button id="coords-duration-btn">OK</button></span>
        </div>
        `
	}


	function createAndSendMessage() {
		if (allPlayers.includes(player.toString())) {
			coordsData = "!" + coordsData
		}
		sentCoords(coordsData)
	}

	function getPlayers() {
		let battleData = unsafeWindow.run_all.toString()
		let battlePlayers = findAll(/plid\d\|(\d{1,10})/, battleData)
		return battlePlayers.map(player => player[1])
	}

	function getAllMessages() {
		return getChat().innerHTML.split("<br>").slice(0, -1)
	}

	function getChat() {
		if (isVisible(document.querySelector("#chat_inside"))) {
			return document.querySelector("#chat_inside")
		} else {
			return document.querySelector("#chat_classic_inside")
		}
	}

	function isVisible(element) {
		return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
	}

	function sentCoords(msg) {
		chatloader.loading = true;
		let formData = new FormData();
		formData.append("warid", warid)
		formData.append("chat", 1)
		let pl_id = player;
		if (player2 > 0) {
			pl_id = player2;
		}

		formData.append("pl_id", pl_id)
		formData.append("mess", encodeURIComponent(getunicode(msg)))
		formData.append("lastturn", lastturn)
		formData.append("lastmess", lastmess)
		formData.append("lastmess2", lastmess2)

		if (crclink != 0) {
			formData.append("show_for_all", crclink)
		}
		const str = [...formData.entries()]
			.map(x => `${x[0]}=${x[1]}`)
			.join('&')

		chatloader_load(str);
		window.scrollTo(0, 0);
	}

	function findAll(regexPattern, sourceString) {
		let output = []
		let match
		let regexPatternWithGlobal = RegExp(regexPattern, [...new Set("g" + regexPattern.flags)].join(""))
		while (match = regexPatternWithGlobal.exec(sourceString)) {
			delete match.input
			output.push(match)
		}
		return output
	}

	function removeElement(element) {
		element.parentNode.removeChild(element)
	}

	function $(id, where = document) {
		return where.querySelector(`#${id}`);
	}

	function get(key, def) {
		let result = JSON.parse(localStorage[key] === undefined ? null : localStorage[key]);
		return result == null ? def : result;

	}

	function set(key, val) {
		localStorage[key] = JSON.stringify(val);
	}

	function getClientWidth() {
		return document.compatMode === 'CSS1Compat' && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth;
	}

	function getDefaultSettings() {
		return {
			"color": "#FF0000",
			"duration": 2000
		}
	}

	function loadSettings() {
		settings = get('hwm_pointer_settings', defaultSettings)
		for (const [key, value] of Object.entries(defaultSettings)) {
			if (settings[key] === undefined) {
				settings[key] = value
			}
		}
	}
})(window);