HWM Pointer

try to take over the world!

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