HWM Pointer

try to take over the world!

当前为 2021-03-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name HWM Pointer
  3. // @namespace https://greasyfork.org/ru/scripts/424028-hwm-pointer
  4. // @version 0.2
  5. // @description try to take over the world!
  6. // @author achepta
  7. // @include /^https{0,1}:\/\/((www|qrator)(\.heroeswm\.ru|\.lordswm\.com)|178\.248\.235\.15)\/war\.php.+/
  8. // @grant unsafeWindow
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_log
  11. // @run-at document-end
  12. // ==/UserScript==
  13.  
  14. (function (window, undefined) {
  15. //TODO add message processing queue
  16. let w;
  17. if (typeof unsafeWindow !== undefined) {
  18. w = unsafeWindow;
  19. } else {
  20. w = window;
  21. }
  22. if (w.self !== w.top) {
  23. return;
  24. }
  25. let allPlayers = getPlayers()
  26. let coordsData = ""
  27. let isPressed = false
  28. let allMessages = getAllMessages()
  29.  
  30. let isSettingsOpened = false;
  31. let defaultSettings = getDefaultSettings()
  32. let settings = {}
  33. loadSettings()
  34.  
  35. setInterval(checkChatForCoords, 300)
  36.  
  37. function checkChatForCoords() {
  38. let newMessages = getAllMessages();
  39. console.log(newMessages.length, allMessages.length)
  40. if (newMessages.length > allMessages.length) {
  41. allMessages = newMessages
  42. checkMessageForCoords(allMessages.slice(-1)[0])
  43. }
  44. }
  45.  
  46. function checkMessageForCoords(msg) {
  47. console.log(msg)
  48.  
  49. if (msg.includes("!")) {
  50. let coords = findAll(/\|(\d{1,2}):(\d{1,2})/, msg)
  51. if (coords.length > 0) {
  52. setChatCoordsListener(coords)
  53. highlightCoords(coords)
  54. }
  55. }
  56. }
  57.  
  58. function setChatCoordsListener(coords) {
  59. let msgWithCoords = Array.from(getChat().getElementsByTagName("b")).slice(-1)[0]
  60. msgWithCoords.id = "coords" + allMessages.length
  61. $(`coords${allMessages.length}`).addEventListener('mouseover', () => showCoordsMouse(coords))
  62. $(`coords${allMessages.length}`).addEventListener('mouseout', () => hideCoordsMouse(coords))
  63. }
  64.  
  65. function showCoordsMouse(coords) {
  66. coords.forEach(coordinate => {
  67. showCoords(coordinate)
  68. })
  69. }
  70.  
  71. function hideCoordsMouse(coords) {
  72. coords.forEach(coordinate => {
  73. hideCoords(coordinate)
  74. })
  75. }
  76.  
  77. function highlightCoords(coords) {
  78. coords.forEach(coordinate => {
  79. showCoords(coordinate)
  80. setTimeout(() => {
  81. hideCoords(coordinate)
  82. }, settings.duration)
  83. })
  84. }
  85.  
  86. function showCoords(coordinate) {
  87. shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].stroke(settings.color);
  88. shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].fill(settings.color);
  89. set_visible(shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn], 1);
  90. }
  91.  
  92. function hideCoords(coordinate) {
  93. shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].stroke('red');
  94. shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn].fill(null);
  95. set_visible(shado[(coordinate[1] - 0) + (coordinate[2] - 0) * defxn], 0);
  96. }
  97.  
  98. window.addEventListener("keydown", e => {
  99. if ((document.querySelector("#chattext") !== document.activeElement) && (document.querySelector("#chattext_classic") !== document.activeElement)) {
  100. if (!isSettingsOpened && e.shiftKey && ["f", "F", "а", "А"].includes(e.key)) {
  101. isSettingsOpened = true;
  102. openSettings()
  103. e.preventDefault()
  104. return
  105. }
  106. if (!isSettingsOpened && ["f", "F", "а", "А"].includes(e.key)) {
  107. if (!isPressed) {
  108. coordsData = "";
  109. coordsData += "|" + xr_last + ":" + yr_last
  110. isPressed = true
  111. }
  112. }
  113. }
  114. })
  115.  
  116. window.addEventListener("keyup", e => {
  117. if ((document.querySelector("#chattext") !== document.activeElement) && (document.querySelector("#chattext_classic") !== document.activeElement)) {
  118. if (!isSettingsOpened && ["f", "F", "а", "А"].includes(e.key)) {
  119. let newCoords = "|" + xr_last + ":" + yr_last
  120. if (newCoords !== coordsData) {
  121. coordsData += " " + newCoords
  122. }
  123. isPressed = false
  124. createAndSendMessage();
  125. }
  126. }
  127. })
  128.  
  129. function openSettings() {
  130. showEmptyBackground();
  131. document.body.insertAdjacentHTML('beforeend', getSettingsTemplate())
  132. fillSettings()
  133. }
  134.  
  135. function showEmptyBackground() {
  136. document.body.insertAdjacentHTML('beforeend', getEmptyBackgroundTemplate());
  137. $('empty_background').addEventListener('click', handleOnBackgroundClick);
  138. }
  139.  
  140. function hideEmptyBackground() {
  141. removeElement($('empty_background'))
  142. }
  143.  
  144. function fillSettings() {
  145. $('coords-color').addEventListener('input', () => {
  146. handleChangeColor()
  147. })
  148. $('coords-duration-btn').addEventListener('click', () => {
  149. handleChangeDuration()
  150. })
  151. $('coords-duration').addEventListener('keyup', e => {
  152. if (e.key === 'Enter' || e.keyCode === 13) {
  153. handleChangeDuration()
  154. }
  155. })
  156. }
  157.  
  158. function handleChangeDuration() {
  159. let inputValue = $('coords-duration').value - 0
  160. if (!isNaN(inputValue) && inputValue !== 0) {
  161. settings.duration = inputValue
  162. handleSettingsChange()
  163. }
  164. }
  165.  
  166. function handleChangeColor() {
  167. settings.color = $('coords-color').value
  168. handleSettingsChange()
  169. }
  170.  
  171. function handleSettingsChange() {
  172. set('hwm_pointer_settings', settings)
  173. }
  174.  
  175. function hideSettings() {
  176. removeElement($('hwm_pointer_settings'))
  177. }
  178.  
  179. function handleOnBackgroundClick() {
  180. isSettingsOpened = false;
  181. hideEmptyBackground();
  182. hideSettings();
  183. }
  184.  
  185. function getEmptyBackgroundTemplate() {
  186. return `
  187. <div id="empty_background" style="
  188. position: fixed;
  189. left: 0;
  190. top: 0;
  191. width: 100%;
  192. height: 100%;
  193. background: #000000;
  194. opacity: 0.5;
  195. z-index: 11000001;
  196. "></div>
  197. `
  198. }
  199.  
  200. function getSettingsTemplate() {
  201. return `
  202. <div id="hwm_pointer_settings" style="
  203. position: fixed;
  204. left: ${(getClientWidth() - 300) / 2}px;
  205. top: ${window.pageYOffset + 155}px;
  206. width: 300px;
  207. background: #F6F3EA;
  208. z-index: 11000002;
  209. padding: 20px;">
  210. <label for="coords-color">Select your favorite color:</label>
  211. <input type="color" id="coords-color" name="coords-color" value="${settings.color}">
  212. <br>
  213. <span>Duration in ms <input id="coords-duration" type="text" style="width: 40px" value="${settings.duration}">
  214. <button id="coords-duration-btn">OK</button></span>
  215. </div>
  216. `
  217. }
  218.  
  219.  
  220. function createAndSendMessage() {
  221. if (allPlayers.includes(player.toString())) {
  222. coordsData = "!" + coordsData
  223. }
  224. sentCoords(coordsData)
  225. }
  226.  
  227. function getPlayers() {
  228. let battleData = unsafeWindow.run_all.toString()
  229. let battlePlayers = findAll(/plid\d\|(\d{1,10})/, battleData)
  230. return battlePlayers.map(player => player[1])
  231. }
  232.  
  233. function getAllMessages() {
  234. return getChat().innerHTML.split("<br>").slice(0, -1)
  235. }
  236.  
  237. function getChat() {
  238. if (isVisible(document.querySelector("#chat_inside"))) {
  239. return document.querySelector("#chat_inside")
  240. } else {
  241. return document.querySelector("#chat_classic_inside")
  242. }
  243. }
  244.  
  245. function isVisible(element) {
  246. return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
  247. }
  248.  
  249. function sentCoords(msg) {
  250. chatloader.loading = true;
  251. let formData = new FormData();
  252. formData.append("warid", warid)
  253. formData.append("chat", 1)
  254. let pl_id = player;
  255. if (player2 > 0) {
  256. pl_id = player2;
  257. }
  258.  
  259. formData.append("pl_id", pl_id)
  260. formData.append("mess", encodeURIComponent(getunicode(msg)))
  261. formData.append("lastturn", lastturn)
  262. formData.append("lastmess", lastmess)
  263. formData.append("lastmess2", lastmess2)
  264.  
  265. if (crclink != 0) {
  266. formData.append("show_for_all", crclink)
  267. }
  268. const str = [...formData.entries()]
  269. .map(x => `${x[0]}=${x[1]}`)
  270. .join('&')
  271.  
  272. chatloader_load(str);
  273. window.scrollTo(0, 0);
  274. }
  275.  
  276. function findAll(regexPattern, sourceString) {
  277. let output = []
  278. let match
  279. let regexPatternWithGlobal = RegExp(regexPattern, [...new Set("g" + regexPattern.flags)].join(""))
  280. while (match = regexPatternWithGlobal.exec(sourceString)) {
  281. delete match.input
  282. output.push(match)
  283. }
  284. return output
  285. }
  286.  
  287. function removeElement(element) {
  288. element.parentNode.removeChild(element)
  289. }
  290.  
  291. function $(id, where = document) {
  292. return where.querySelector(`#${id}`);
  293. }
  294.  
  295. function get(key, def) {
  296. let result = JSON.parse(localStorage[key] === undefined ? null : localStorage[key]);
  297. return result == null ? def : result;
  298.  
  299. }
  300.  
  301. function set(key, val) {
  302. localStorage[key] = JSON.stringify(val);
  303. }
  304.  
  305. function getClientWidth() {
  306. return document.compatMode === 'CSS1Compat' && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth;
  307. }
  308.  
  309. function getDefaultSettings() {
  310. return {
  311. "color": "#FF0000",
  312. "duration": 2000
  313. }
  314. }
  315.  
  316. function loadSettings() {
  317. settings = get('hwm_pointer_settings', defaultSettings)
  318. for (const [key, value] of Object.entries(defaultSettings)) {
  319. if (settings[key] === undefined) {
  320. settings[key] = value
  321. }
  322. }
  323. }
  324. })(window);