HWM-UI-UX-MOD

try to take over the world!

当前为 2021-02-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name HWM-UI-UX-MOD
  3. // @namespace https://greasyfork.org/ru/scripts/421913-hwm-ui-ux-mod
  4. // @version 0.6
  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)\/.+/
  8. // @grant unsafeWindow
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_log
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. (function (window, undefined) {
  15. let w;
  16. if (typeof unsafeWindow !== undefined) {
  17. w = unsafeWindow;
  18. } else {
  19. w = window;
  20. }
  21. if (w.self !== w.top) {
  22. return;
  23. }
  24. if (/cgame/.test(location.href)) {
  25. return
  26. }
  27. let allTexts = getAllTexts()
  28. let defaultSettings = getDefaultSettings()
  29.  
  30. let language = /lordswm/.test(location.href) ? "eng" : "rus"
  31. let settings = {}
  32. let headerInfo = {}
  33. let timersInfo = {}
  34.  
  35. loadSettings();
  36. loadTimersInfo();
  37.  
  38. if (settings['isDarkTheme'] && !/war\.php/.test(location.href)) {
  39. applyDarkTheme()
  40. }
  41. document.addEventListener("DOMContentLoaded", () => {
  42. if (!/war\.php/.test(location.href)) {
  43. processPage()
  44. addStyle();
  45. getHeaderInfo()
  46. drawNewHeader()
  47. processSettings();
  48. addMenu();
  49. } else {
  50. processBattle()
  51. }
  52. });
  53.  
  54.  
  55. function addStyle() {
  56. document.body.insertAdjacentHTML("beforeend", getStyles())
  57. }
  58.  
  59. function addMenu() {
  60. $('hwm_header_settings_button').addEventListener('click', handleOnSettingsButtonClick);
  61. }
  62.  
  63.  
  64. // logic
  65. function processSettings() {
  66. if (settings.isTimeWithSeconds) {
  67. showTimeWithSeconds()
  68. }
  69. if (settings.isShowTimers) {
  70. showTimers()
  71. }
  72. }
  73.  
  74. function getHeaderInfo() {
  75. headerInfo['logo'] = getHeaderLogo()
  76. headerInfo['mana_amount'] = getManaAmount()
  77. headerInfo['notifications'] = getHeaderNotifications()
  78. headerInfo['homeColor'] = getHomeButtonColor()
  79. headerInfo['battleColor'] = getBattleButtonColor()
  80. headerInfo['resources'] = getHeaderResources()
  81. headerInfo['online'] = getHwmOnline()
  82. }
  83.  
  84. function getHeaderLogo() {
  85. return document.querySelector("div.sh_logo > img").src
  86. }
  87.  
  88. function getManaAmount() {
  89. return $('mana_amount').textContent
  90. }
  91.  
  92. function getHeaderNotifications() {
  93. return Array.from(document.getElementsByClassName("NotificationIcon"))
  94. }
  95.  
  96. function getHomeButtonColor() {
  97. return document.querySelector("#MenuHome").offsetParent.classList.value.split("_").slice(-1)[0]
  98. }
  99.  
  100. function getBattleButtonColor() {
  101. return document.querySelector("#MenuBattles").offsetParent.classList.value.split("_").slice(-1)[0]
  102. }
  103.  
  104. function getHeaderResources() {
  105. let resources = {}
  106. let resourceDivs = document.querySelectorAll("div.sh_ResourcesItem")
  107. Array.from(resourceDivs).forEach(item => {
  108. let resName = getResNameFromImage(item.firstChild.src)
  109. resources[resName] = item.lastChild.textContent
  110. })
  111. return resources
  112. }
  113.  
  114. function getResNameFromImage(src) {
  115. return src.match(/(\w+)\.png/)[1]
  116. }
  117.  
  118. function getHwmOnline() {
  119. return document.querySelector("div.sh_extra.sh_extra_right > div.mm_extra_separator").nextElementSibling.textContent
  120. }
  121.  
  122. function drawNewHeader() {
  123. removeElement($('hwm_header'))
  124. document.body.insertAdjacentHTML('afterbegin', getNewHeaderTemplate())
  125. let heartData = document.body.textContent.match(/top_line_draw_canvas_heart\((\d{1,3}), (\d{1,3}), (\d{1,3})\);/)
  126. unsafeWindow.top_line_draw_canvas_heart(heartData[1], heartData[2], heartData[3])
  127. unsafeWindow.top_line_add_events_listeners()
  128. }
  129.  
  130. function showTimeWithSeconds() {
  131. let hwmDate = hwmDateToHuman(getHwmDate());
  132. let timePlace = $('hwm_time');
  133. timePlace.innerHTML = hwmDate
  134. setTimeout(showTimeWithSeconds, 1000)
  135. }
  136.  
  137. function showTimers() {
  138. $('timers_container').innerHTML = getTimersTemplate()
  139. setTimeout(showTimers, 1000)
  140. }
  141.  
  142. function applyDarkTheme() {
  143. document.head.insertAdjacentHTML("beforeend", getDarkStyles())
  144.  
  145. }
  146.  
  147. function showEmptyBackground() {
  148. document.body.insertAdjacentHTML('beforeend', getEmptyBackgroundTemplate());
  149. $('empty_background').addEventListener('click', handleOnBackgroundClick);
  150. }
  151.  
  152. function hideEmptyBackground() {
  153. removeElement($('empty_background'))
  154. }
  155.  
  156. function showSettings() {
  157. document.body.insertAdjacentHTML('beforeend', getSettingsTemplate())
  158. fillSettings()
  159. }
  160.  
  161. function fillSettings() {
  162. let settingsField = $('hwm_header_settings');
  163. for (const [key, value] of Object.entries(settings)) {
  164. settingsField.insertAdjacentHTML("beforeend",
  165. `<div id="${key}">
  166. <input id="${key}_checkbox" type="checkbox" ${value ? ' checked' : ''}>
  167. <label for="${key}_checkbox">${getTranslation(key)}</label>
  168. </div>
  169. `)
  170. $(`${key}`).addEventListener('click', () => {
  171. handleSettingsChange(key)
  172. })
  173. }
  174. }
  175.  
  176. function hideSettings() {
  177. removeElement($('hwm_header_settings'))
  178. }
  179.  
  180. function processButtonDropDown(buttonInfo) {
  181. if (buttonInfo.id === "MenuInventory" || buttonInfo.id === "MenuTavern") {
  182. return
  183. }
  184. let target = $(buttonInfo.id+"_expandable")
  185. if (buttonInfo.id === "MenuBattles") {
  186. Array.from(target.getElementsByTagName('a')).slice(8).forEach(item => {
  187. buttonInfo.dropDown.push([item.textContent, item.href, true])
  188. })
  189. }
  190. target.innerHTML = ''
  191. buttonInfo.dropDown.forEach(item => {
  192. if (item.length > 2) {
  193. target.insertAdjacentHTML('beforeend', `<a href="${item[1]}" style="text-decoration:none;"><div class="sh_dd_container_red">${item[0]}</div></a>`)
  194. } else {
  195. target.insertAdjacentHTML('beforeend', `<a href="${item[1]}" style="text-decoration:none;"><div>${getTranslation(item[0])}</div></a>`)
  196. }
  197. })
  198. target.insertAdjacentHTML("beforeend", `<img src="https://dcdn.heroeswm.ru/i/new_top/mm_dd_decorM.png" class="mm_decor2">`)
  199. target.insertAdjacentHTML("beforeend", `<img src="https://dcdn.heroeswm.ru/i/new_top/mm_dd_decorT.png" class="mm_decor3">`)
  200. }
  201.  
  202. function processPage() {
  203. if (/home/.test(location.href)) {
  204. let isPremium = document.body.innerHTML.match(/star.gif/)
  205. timersInfo.isPremium = !!isPremium
  206. }
  207. if (/object_do/.test(location.href)) {
  208. if (document.body.textContent.match(/(successfully|устроены)/)) {
  209. timersInfo.labor_guild_timer_data = getHwmDate()
  210. }
  211. }
  212. let battleId = new URLSearchParams(new URL(document.referrer).search).get("warid")
  213. if (timersInfo.leader_guild_timer_data && !timersInfo.leader_guild_timer_data.timeSet && battleId === timersInfo.leader_guild_timer_data.battleId) {
  214. timersInfo.leader_guild_timer_data.timeSet = getHwmDate()
  215. } else if (timersInfo.thief_guild_timer_data && !timersInfo.thief_guild_timer_data.timeSet && battleId === timersInfo.thief_guild_timer_data.battleId) {
  216. timersInfo.thief_guild_timer_data.timeSet = getHwmDate()
  217. } else if (timersInfo.hunt_guild_timer_data && !timersInfo.hunt_guild_timer_data.timeSet && battleId === timersInfo.hunt_guild_timer_data.battleId) {
  218. timersInfo.hunt_guild_timer_data.timeSet = getHwmDate()
  219. }
  220. set("timers_data", timersInfo)
  221. }
  222.  
  223. function processBattle() {
  224. let battleData = unsafeWindow.run_all.toString()
  225. let battleType = battleData.match(/btype\|(\d{1,10})/)[1]
  226. let battlePlayer = battleData.match(/plid1\|(\d{1,10})/)[1]
  227. let battleId = new URLSearchParams(window.location.search).get("warid")
  228. if (battlePlayer === getCookie("pl_id")) {
  229. if (battleType === "127") {
  230. if ("leader_guild_timer_data" in timersInfo) {
  231. if (timersInfo.leader_guild_timer_data.battleId < battleId) {
  232. timersInfo.leader_guild_timer_data = {"battleId": battleId}
  233. }
  234. } else {
  235. timersInfo.leader_guild_timer_data = {"battleId": battleId}
  236. }
  237. } else if (battleType === "66") {
  238. if ("thief_guild_timer_data" in timersInfo) {
  239. if (timersInfo.thief_guild_timer_data.battleId < battleId) {
  240. timersInfo.thief_guild_timer_data = {"battleId": battleId}
  241. }
  242. } else {
  243. timersInfo.thief_guild_timer_data = {"battleId": battleId}
  244. }
  245. } else if (battleType === "0") {
  246. if ("hunt_guild_timer_data" in timersInfo) {
  247. if (timersInfo.hunt_guild_timer_data.battleId < battleId) {
  248. timersInfo.hunt_guild_timer_data = {"battleId": battleId}
  249. }
  250. } else {
  251. timersInfo.hunt_guild_timer_data = {"battleId": battleId}
  252. }
  253. }
  254. set("timers_data", timersInfo)
  255. }
  256. }
  257.  
  258. // listeners
  259. function handleOnSettingsButtonClick() {
  260. showEmptyBackground();
  261. showSettings();
  262. }
  263.  
  264. function handleOnBackgroundClick() {
  265. hideEmptyBackground();
  266. hideSettings();
  267. }
  268.  
  269. function handleSettingsChange(key) {
  270. settings[key] = $(`${key}_checkbox`).checked
  271. set('hwm_header_settings', settings)
  272. }
  273.  
  274. // templates
  275. function getSettingsButtonTemplate() {
  276. return `
  277. <img
  278. id="hwm_header_settings_button"
  279. src="https://dcdn3.heroeswm.ru/i/combat/btn_settings.png?v=8"
  280. height="18"
  281. alt="Header settings"
  282. style="position: relative; filter: drop-shadow(0.01rem 0.01rem 0 black) drop-shadow(-0.01rem -0.01rem 0 black); transform: rotate(22.5deg)"
  283. title="Header settings"
  284. >`
  285. }
  286.  
  287. function getEmptyBackgroundTemplate() {
  288. return `
  289. <div id="empty_background" style="
  290. position: absolute;
  291. left: 0;
  292. top: 0;
  293. width: 100%;
  294. height: ${getScrollHeight()};
  295. background: #000000;
  296. opacity: 0.5;
  297. z-index: 1100;
  298. "></div>
  299. `
  300. }
  301.  
  302. function getSettingsTemplate() {
  303. return `
  304. <div id="hwm_header_settings" style="
  305. position: absolute;
  306. left: ${(getClientWidth() - 600) / 2}px;
  307. top: ${window.pageYOffset + 155}px;
  308. width: 600px;
  309. background: #F6F3EA;
  310. z-index: 1101;
  311. ">
  312. </div>
  313. `
  314. }
  315.  
  316. function getNewHeaderTemplate() {
  317. return `
  318. <div id="new_header">
  319. <div class="top_line">
  320. <div class="top_left_container">
  321. <!-- <div class="top_left_left">-->
  322. <!-- </div>-->
  323. <div class="top_wing_middle">
  324. <div id="notifications">
  325. ${getNotificationsTemplate()}
  326. </div>
  327. </div>
  328. <div class="top_left_right">
  329. <div id="heart_container">
  330. <div class="sh_HMResIconBlock">
  331. <canvas width="64px" height="64px" id="heart"></canvas>
  332. </div>
  333. <div style="display: none;" id="health_amount">100</div>
  334. </div>
  335. </div>
  336. </div>
  337. <div class="top_resource_container" id="top_resource_container">
  338. <div id="ResourcesPanel" class="sh_ResourcesPanel">
  339. ${getResourcesTemplate()}
  340. </div>
  341. </div>
  342. <div class="top_right_container">
  343. <div class="top_right_left">
  344. <div id="mana_container">
  345. <div class="sh_HMResIconBlock mana"></div>
  346. <div class="mana_animation"></div>
  347. <div style="display: none" id="mana_amount">${headerInfo.mana_amount}</div>
  348. </div>
  349. </div>
  350. <div class="top_wing_middle">
  351. <div class="time_online_radio_container">
  352. <div id="hwm_time"></div>
  353. <div class="mm_extra_separator"></div>
  354. <div id="hwm_online">${headerInfo['online']} online</div>
  355. <div class="mm_extra_separator"></div>
  356. <div class="mm_extra_radio" onclick="hwm_top_line_open_radio(620, 400);return false;"></div>
  357. <div class="mm_extra_separator"></div>
  358. <div id="">${getSettingsButtonTemplate()}</div>
  359. </div>
  360. </div>
  361. <!-- <div class="top_right_right">-->
  362.  
  363. <!-- </div>-->
  364. </div>
  365. </div>
  366. <div class="new_header_menu">
  367. <!-- <img src="https://dcdn.heroeswm.ru/i/new_top/mm_decor1.png" class="mm_decor1">-->
  368. <div class="left_dragon">
  369. <img height="70px" src="https://i.pinimg.com/originals/6c/2e/0b/6c2e0be6ebdad0e7f4bc86bc1f10e451.png">
  370. </div>
  371. <div class="middle_menus">
  372. <div class="timers_container" id="timers_container"></div>
  373. <div class="common_menu_container">
  374. ${getMenuButtonsTemplate()}
  375. </div>
  376. </div>
  377. <div class="right_dragon">
  378. <img height="70px" src="https://i.imgur.com/oqyVp7G.png">
  379. </div>
  380. </div>
  381. </div>
  382. `
  383. }
  384.  
  385. function getNotificationsTemplate() {
  386. return headerInfo['notifications'].reduce((result, current) => {
  387. // #говнокод
  388. if (current.src.includes("pismo")) {
  389. return result + `<a href="sms.php">${current.outerHTML.toString()}</a>`;
  390. } else {
  391. return result + current.outerHTML.toString()
  392. }}, "")
  393. }
  394.  
  395. function getResourcesTemplate() {
  396. let newResources = []
  397. let resourceLinks = getResourceLinks()
  398. for (const [key, value] of Object.entries(headerInfo['resources'])) {
  399. let template = `
  400. <div class="sh_ResourcesItem">
  401. <a href="${resourceLinks[key]}">
  402. <img class="sh_ResourcesItem_icon" src="https://dcdn.heroeswm.ru/i/r/48/${key}.png?v=3.23de65" alt="${key}" title="${key}">
  403. </a>
  404. <span class="select_auto_enabled">${value}</span></div>
  405. `
  406. newResources.push(template)
  407. }
  408. return newResources.join(`<div class="mm_rp_separator"></div>`)
  409. }
  410.  
  411. function getMenuButtonsTemplate() {
  412. let buttonsToShow = getAvailableButtons()
  413. return buttonsToShow.reduce((result, current) => result + getMenuButtonHTML(current), "")
  414. }
  415.  
  416. function getAvailableButtons() {
  417. let buttons = []
  418. for (const [key, value] of Object.entries(getButtonInfos())) {
  419. if (settings[key]) {
  420. buttons.push(value)
  421. }
  422. }
  423. return buttons
  424. }
  425.  
  426. function getMenuButtonHTML(buttonInfo) {
  427. processButtonDropDown(buttonInfo)
  428. let buttonInside = ``
  429. if (settings['isTextButtons']) {
  430. buttonInside = `<div class="menu_button_text">${getTranslation(buttonInfo.id)}</div>`
  431. } else {
  432. buttonInside = `<img class="mm_item_icon" src="${buttonInfo.image}">`
  433. }
  434. let buttonColor = ``
  435. if (headerInfo['homeColor'] === 'red') {
  436. buttonColor = 'red'
  437. } else if (headerInfo['battleColor'] === 'orange' && buttonInfo.id === "MenuBattles") {
  438. buttonColor = 'orange'
  439. } else if (headerInfo['battleColor'] === 'red' && buttonInfo.id === "MenuBattles") {
  440. buttonColor = 'red'
  441. } else {
  442. buttonColor = 'blue'
  443. }
  444. return `
  445. <div class="mm_item mm_item_${buttonColor} ${settings.isTextButtons ? "small_text_button": ""}">
  446. <a href="${buttonInfo.href}">
  447. <div class="mm_item_inside ${settings.isTextButtons ? "small_text_inside": ""}" id="${buttonInfo.id}" hwm_label="">
  448. ${buttonInside}
  449. </div>
  450. </a>
  451. </div>
  452. `
  453. }
  454.  
  455. function getTimersTemplate() {
  456. let isPremium = timersInfo.isPremium ? timersInfo.isPremium : false
  457. let result = ''
  458. if (timersInfo.labor_guild_timer_data) {
  459. let timeCount = isPremium ? 60 : 60
  460. result += `
  461. <div class="mm_item mm_item_blue small_text_button">
  462. <div class="menu_button_text">${getTranslation("labor_guild")} ${getRemainingTime(timersInfo.labor_guild_timer_data, timeCount)}</div>
  463. </div>`
  464. } else {
  465. result += `
  466. <div class="mm_item mm_item_blue small_text_button">
  467. <div class="menu_button_text">${getTranslation("labor_guild")} 00:00</div>
  468. </div>`
  469. }
  470. if (timersInfo.hunt_guild_timer_data && timersInfo.hunt_guild_timer_data.timeSet) {
  471. let timeCount = isPremium ? 28 : 40
  472. result += `
  473. <div class="mm_item mm_item_blue small_text_button">
  474. <div class="menu_button_text">${getTranslation("hunt_guild")} ${getRemainingTime(timersInfo.hunt_guild_timer_data.timeSet, timeCount)}</div>
  475. </div>`
  476. } else {
  477. result += `
  478. <div class="mm_item mm_item_blue small_text_button">
  479. <div class="menu_button_text">${getTranslation("hunt_guild")} 00:00</div>
  480. </div>`
  481. }
  482. if (timersInfo.thief_guild_timer_data && timersInfo.thief_guild_timer_data.timeSet) {
  483. let timeCount = isPremium ? 42 : 60
  484. result += `
  485. <div class="mm_item mm_item_blue small_text_button">
  486. <div class="menu_button_text">${getTranslation("thief_guild")} ${getRemainingTime(timersInfo.thief_guild_timer_data.timeSet, timeCount)}</div>
  487. </div>`
  488. } else {
  489. result += `
  490. <div class="mm_item mm_item_blue small_text_button">
  491. <div class="menu_button_text">${getTranslation("thief_guild")} 00:00</div>
  492. </div>`
  493. }
  494. if (timersInfo.leader_guild_timer_data && timersInfo.leader_guild_timer_data.timeSet) {
  495. let timeCount = isPremium ? 180 : 180
  496. result += `
  497. <div class="mm_item mm_item_blue small_text_button">
  498. <div class="menu_button_text">${getTranslation("leader_guild")} ${getRemainingTime(timersInfo.leader_guild_timer_data.timeSet, timeCount)}</div>
  499. </div>`
  500. } else {
  501. result += `
  502. <div class="mm_item mm_item_blue small_text_button">
  503. <div class="menu_button_text">${getTranslation("leader_guild")} 00:00</div>
  504. </div>`
  505. }
  506. return result
  507. }
  508.  
  509. function getRemainingTime(timeSet, timeCount) {
  510. let hwmDate = getHwmDate()
  511. let timeSetHwm = new Date(timeSet)
  512. return secondsToHumanDate(diffDateInSeconds(timeSetHwm, hwmDate) + timeCount * 60)
  513. }
  514.  
  515. function diffDateInSeconds(dt1, dt2) {
  516. return Math.round((dt1.getTime() - dt2.getTime()) / 1000);
  517. }
  518. // helpers
  519. function getCookie(name) {
  520. const value = `; ${document.cookie}`;
  521. const parts = value.split(`; ${name}=`);
  522. if (parts.length === 2) return parts.pop().split(';').shift();
  523. }
  524.  
  525. function doGet(url, callback) {
  526. GM_xmlhttpRequest({
  527. method: "GET",
  528. url: url,
  529. overrideMimeType: "text/xml; charset=windows-1251",
  530. onload: function (res) {
  531. callback(new DOMParser().parseFromString(res.responseText, "text/html"))
  532. }
  533. });
  534. }
  535.  
  536. function doPost(url, params, callback) {
  537. GM_xmlhttpRequest({
  538. method: "POST",
  539. url: url,
  540. data: params,
  541. onload: callback,
  542. });
  543. }
  544.  
  545. function removeElement(element) {
  546. element.parentNode.removeChild(element)
  547. }
  548.  
  549. function $(id, where = document) {
  550. return where.querySelector(`#${id}`);
  551. }
  552.  
  553. function get(key, def) {
  554. let result = JSON.parse(localStorage[key] === undefined ? null : localStorage[key]);
  555. return result == null ? def : result;
  556.  
  557. }
  558.  
  559. function set(key, val) {
  560. localStorage[key] = JSON.stringify(val);
  561. }
  562.  
  563. function getScrollHeight() {
  564. return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
  565. }
  566.  
  567. function getClientWidth() {
  568. return document.compatMode === 'CSS1Compat' && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth;
  569. }
  570.  
  571. function findAll(regexPattern, sourceString) {
  572. let output = []
  573. let match
  574. let regexPatternWithGlobal = RegExp(regexPattern, [...new Set("g" + regexPattern.flags)].join(""))
  575. while (match = regexPatternWithGlobal.exec(sourceString)) {
  576. delete match.input
  577. output.push(match)
  578. }
  579. return output
  580. }
  581.  
  582. function sortByKey(array, key) {
  583. return array.sort((a, b) => {
  584. let x = a[key];
  585. let y = b[key];
  586. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  587. });
  588. }
  589.  
  590. function getHwmDate() {
  591. let today = new Date();
  592. let localOffset = -(today.getTimezoneOffset() / 60);
  593. let destinationOffset = +3;
  594.  
  595. let offset = destinationOffset - localOffset;
  596. return new Date(new Date().getTime() + offset * 3600 * 1000)
  597.  
  598. }
  599.  
  600. function hwmDateToHuman(hwmDate) {
  601. let hours = hwmDate.getHours().toString().length === 1
  602. ? "0" + hwmDate.getHours().toString()
  603. : hwmDate.getHours().toString()
  604. let minutes = hwmDate.getMinutes().toString().length === 1
  605. ? "0" + hwmDate.getMinutes().toString()
  606. : hwmDate.getMinutes().toString()
  607. let seconds = hwmDate.getSeconds().toString().length === 1
  608. ? "0" + hwmDate.getSeconds().toString()
  609. : hwmDate.getSeconds().toString()
  610. return hours + ":" + minutes + ":" + seconds
  611. }
  612.  
  613. function secondsToHumanDate(seconds) {
  614. if (seconds < 0) {
  615. return "00:00"
  616. }
  617. // Hours, minutes and seconds
  618. var hrs = ~~(seconds / 3600);
  619. var mins = ~~((seconds % 3600) / 60);
  620. var secs = ~~seconds % 60;
  621.  
  622. // Output like "1:01" or "4:03:59" or "123:03:59"
  623. var ret = "";
  624. if (hrs > 0) {
  625. ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
  626. }
  627. ret += "" + mins + ":" + (secs < 10 ? "0" : "");
  628. ret += "" + secs;
  629. return ret;
  630. }
  631.  
  632. function getTranslation(textId) {
  633. return allTexts[textId][language]
  634. }
  635.  
  636. function loadSettings() {
  637. settings = get('hwm_header_settings', defaultSettings)
  638. for (const [key, value] of Object.entries(defaultSettings)) {
  639. if (settings[key] === undefined) {
  640. settings[key] = value
  641. }
  642. }
  643. }
  644.  
  645. function loadTimersInfo() {
  646. timersInfo = get('timers_data', {})
  647. }
  648.  
  649. function getAllTexts() {
  650. return {
  651. 'isTimeWithSeconds': {
  652. "rus": "Показывать время с секундами",
  653. "eng": "Show time with seconds",
  654. },
  655. 'isShowTimers': {
  656. "rus": "Показывать таймеры гильдий",
  657. "eng": "Show guilds' timers",
  658. },
  659. 'isDarkTheme': {
  660. "rus": "Темная тема",
  661. "eng": "Dark theme"
  662. },
  663. 'isTextButtons': {
  664. "rus": "Старые текстовые кнопки",
  665. "eng": "Show old text buttons"
  666. },
  667. 'isHomeButton': {
  668. "rus": "Персонаж",
  669. "eng": "Home"
  670. },
  671. 'isInventoryButton': {
  672. "rus": "Инвентарь",
  673. "eng": "Inventory"
  674. },
  675. 'isMapButton': {
  676. "rus": "Карта",
  677. "eng": "Map"
  678. },
  679. 'isBattleButton': {
  680. "rus": "Битвы",
  681. "eng": "Battles"
  682. },
  683. 'isTavernButton': {
  684. "rus": "Таверна",
  685. "eng": "Tavern"
  686. },
  687. 'isRouletteButton': {
  688. "rus": "Рулетка",
  689. "eng": "Roulette"
  690. },
  691. 'isLeaderboardButton': {
  692. "rus": "Рейтинг",
  693. "eng": "Leaderboards"
  694. },
  695. 'isForumButton': {
  696. "rus": "Форум",
  697. "eng": "Forum"
  698. },
  699. 'isChatButton': {
  700. "rus": "Чат",
  701. "eng": "Chat"
  702. },
  703. 'MenuHome': {
  704. "rus": "Персонаж",
  705. "eng": "Home"
  706. },
  707. 'MenuInventory': {
  708. "rus": "Инвентарь",
  709. "eng": "Inventory"
  710. },
  711. 'MenuMap': {
  712. "rus": "Карта",
  713. "eng": "Map"
  714. },
  715. 'MenuBattles': {
  716. "rus": "Битвы",
  717. "eng": "Battles"
  718. },
  719. 'MenuTavern': {
  720. "rus": "Таверна",
  721. "eng": "Tavern"
  722. },
  723. 'MenuRoulette': {
  724. "rus": "Рулетка",
  725. "eng": "Roulette"
  726. },
  727. 'MenuStat': {
  728. "rus": "Рейтинг",
  729. "eng": "Leaderboards"
  730. },
  731. 'MenuForum': {
  732. "rus": "Форум",
  733. "eng": "Forum"
  734. },
  735. 'MenuChat': {
  736. "rus": "Чат",
  737. "eng": "Chat"
  738. },
  739. 'myself': {
  740. "rus": "Я",
  741. "eng": "Myself"
  742. },
  743. 'inventory': {
  744. "rus": "Инвентарь",
  745. "eng": "Inventory"
  746. },
  747. 'shop': {
  748. "rus": "Магазин",
  749. "eng": "Artifact shop"
  750. },
  751. 'auction': {
  752. "rus": "Рынок",
  753. "eng": "Market"
  754. },
  755. 'choose_army': {
  756. "rus": "Набор армии",
  757. "eng": "Recruiting"
  758. },
  759. 'castle': {
  760. "rus": "Замок",
  761. "eng": "Castle"
  762. },
  763. 'skills': {
  764. "rus": "Навыки",
  765. "eng": "Talents"
  766. },
  767. 'mailbox': {
  768. "rus": "Почта",
  769. "eng": "Mailbox"
  770. },
  771. 'transfer': {
  772. "rus": "Передача ресурсов",
  773. "eng": "Transfer"
  774. },
  775. 'facility1': {
  776. "rus": "Добыча",
  777. "eng": "Mining"
  778. },
  779. 'facility2': {
  780. "rus": "Обработка",
  781. "eng": "Machining"
  782. },
  783. 'facility3': {
  784. "rus": "Производство",
  785. "eng": "Production"
  786. },
  787. 'houses': {
  788. "rus": "Дома",
  789. "eng": "Public services"
  790. },
  791. 'one_to_one': {
  792. "rus": "Дуэли",
  793. "eng": "Duels"
  794. },
  795. 'many_to_many': {
  796. "rus": "Групповые бои",
  797. "eng": "Group battles"
  798. },
  799. 'guild_pvp': {
  800. "rus": "Гильдия тактиков",
  801. "eng": "Commanders' guild"
  802. },
  803. 'guild_task': {
  804. "rus": "Гильдия стражей",
  805. "eng": "Watchers' guild"
  806. },
  807. 'guild_leader': {
  808. "rus": "Гильдия лидеров",
  809. "eng": "Leaders guild"
  810. },
  811. 'clanwars': {
  812. "rus": "Бои за территории",
  813. "eng": "Clan wars"
  814. },
  815. 'tournaments': {
  816. "rus": "Турниры",
  817. "eng": "Tounaments"
  818. },
  819. 'spin_history': {
  820. "rus": "История игр",
  821. "eng": "Spin history"
  822. },
  823. 'lucky_boxes': {
  824. "rus": "Редкие ларцы",
  825. "eng": "Chests of abundance"
  826. },
  827. 'top_heroes': {
  828. "rus": "Рейтинг воинов",
  829. "eng": "Top warriors"
  830. },
  831. 'top_clans': {
  832. "rus": "Рейтинг кланов",
  833. "eng": "Top clans"
  834. },
  835. 'top_hunters': {
  836. "rus": "Рейтинг охотников",
  837. "eng": "Top hunters"
  838. },
  839. 'top_mercenaries': {
  840. "rus": "Рейтинг наемников",
  841. "eng": "Top mercenaries"
  842. },
  843. 'top_shareholders': {
  844. "rus": "Рейтинг акционеров",
  845. "eng": "Top shareholders"
  846. },
  847. 'personal_records': {
  848. "rus": "Мои охоты",
  849. "eng": "My hunt records"
  850. },
  851. 'general_forum': {
  852. "rus": "Общий форум",
  853. "eng": "General forum"
  854. },
  855. 'help_forum': {
  856. "rus": "Помощь по игре",
  857. "eng": "Q&A forum"
  858. },
  859. 'trade_forum': {
  860. "rus": "Торговый форум",
  861. "eng": "Trade forums"
  862. },
  863. 'reference': {
  864. "rus": "Об игре",
  865. "eng": "About the game"
  866. },
  867. 'hwm_newspaper': {
  868. "rus": "Новостная лента",
  869. "eng": "Daily news"
  870. },
  871. 'chat_1': {
  872. "rus": "Комната вопросов",
  873. "eng": "Inquiry"
  874. },
  875. 'chat_2': {
  876. "rus": "Общая комната",
  877. "eng": "Common"
  878. },
  879. 'chat_3': {
  880. "rus": "Торговая палата",
  881. "eng": "Merchant"
  882. },
  883. 'chat_4': {
  884. "rus": "Рулетка",
  885. "eng": "Roulette"
  886. },
  887. 'chat_5': {
  888. "rus": "Карты",
  889. "eng": "Tavern"
  890. },
  891. 'labor_guild': {
  892. "rus": "ГР",
  893. "eng": "LG"
  894. },
  895. 'leader_guild': {
  896. "rus": "ГЛ",
  897. "eng": "LeG"
  898. },
  899. 'hunt_guild': {
  900. "rus": "ГО",
  901. "eng": "HG"
  902. },
  903. 'thief_guild': {
  904. "rus": "ГВ",
  905. "eng": "TG"
  906. },
  907. '': {
  908. "rus": "",
  909. "eng": ""
  910. },
  911.  
  912. }
  913. }
  914.  
  915. function getDefaultSettings() {
  916. return {
  917. "isTimeWithSeconds": true,
  918. "isShowTimers": true,
  919. "isDarkTheme": false,
  920. "isTextButtons": false,
  921. "isHomeButton": true,
  922. "isInventoryButton": false,
  923. "isMapButton": true,
  924. "isBattleButton": true,
  925. "isTavernButton": true,
  926. "isRouletteButton": true,
  927. "isLeaderboardButton": true,
  928. "isForumButton": true,
  929. "isChatButton": true,
  930. }
  931. }
  932.  
  933. function getButtonInfos() {
  934. return {
  935. "isHomeButton": {
  936. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelCharacter.png",
  937. "id": "MenuHome",
  938. "href": "home.php",
  939. "dropDown": [
  940. ["myself", `pl_info.php?id=${getCookie("pl_id")}`],
  941. ["inventory", "inventory.php"],
  942. ["shop", "shop.php"],
  943. ["auction", "auction.php"],
  944. ["choose_army", "army.php"],
  945. ["castle", "castle.php"],
  946. ["skills", "skillwheel.php"],
  947. ["mailbox", "sms.php"],
  948. ["transfer", "transfer.php"],
  949. ]
  950. },
  951. "isInventoryButton": {
  952. "image": "https://dcdn.heroeswm.ru/i/mobile_view/icons/_panelInventory.png",
  953. "id": "MenuInventory",
  954. "href": "inventory.php",
  955. "dropDown": []
  956. },
  957. "isMapButton": {
  958. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelMap.png",
  959. "id": "MenuMap",
  960. "href": "map.php",
  961. "dropDown": [
  962. ["facility1", "map.php?st=mn"],
  963. ["facility2", "map.php?st=fc"],
  964. ["facility3", "map.php?st=sh"],
  965. ["houses", "map.php?st=hs"],
  966. ]
  967. },
  968. "isBattleButton": {
  969. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelBattles.png",
  970. "id": "MenuBattles",
  971. "href": "bselect.php",
  972. "dropDown": [
  973. ["one_to_one", "one_to_one.php"],
  974. ["many_to_many", "group_wars.php"],
  975. ["guild_pvp", "pvp_guild.php"],
  976. ["guild_task", "task_guild.php"],
  977. ["guild_leader", "leader_guild.php"],
  978. ["clanwars", "mapwars.php"],
  979. ["tournaments", "tournaments.php"],
  980. ]
  981. },
  982. "isTavernButton": {
  983. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelTavern.png",
  984. "id": "MenuTavern",
  985. "href": "tavern.php",
  986. "dropDown": []
  987. },
  988. "isRouletteButton": {
  989. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelRoulette.png",
  990. "id": "MenuRoulette",
  991. "href": "roulette.php",
  992. "dropDown": [
  993. ["spin_history", "allroul.php"],
  994. ["lucky_boxes", "gift_box_log.php"],
  995.  
  996. ]
  997. },
  998. "isLeaderboardButton": {
  999. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelRate.png",
  1000. "id": "MenuStat",
  1001. "href": "plstats.php",
  1002. "dropDown": [
  1003. ["top_heroes", "plstats.php"],
  1004. ["top_clans", "clanstat.php"],
  1005. ["top_hunters", "plstats_hunters.php"],
  1006. ["top_mercenaries", "plstats_merc.php"],
  1007. ["top_shareholders", "sholders_stat.php"],
  1008. ["personal_records", `pl_hunter_stat.php?id=${getCookie("pl_id")}`],
  1009.  
  1010. ]
  1011. },
  1012. "isForumButton": {
  1013. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelForum.png",
  1014. "id": "MenuForum",
  1015. "href": "forum.php",
  1016. "dropDown": [
  1017. ["general_forum", "forum_thread.php?id=2"],
  1018. ["help_forum", "forum_thread.php?id=10"],
  1019. ["trade_forum", "forum.php#t1"],
  1020. ["reference", "help.php"],
  1021. ["hwm_newspaper", "https://daily.heroeswm.ru/"],
  1022.  
  1023. ]
  1024. },
  1025. "isChatButton": {
  1026. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelChat.png",
  1027. "id": "MenuChat",
  1028. "href": "frames.php",
  1029. "dropDown": [
  1030. ["chat_1", "frames.php?room=0"],
  1031. ["chat_2", "frames.php?room=1"],
  1032. ["chat_3", "frames.php?room=2"],
  1033. ["chat_4", "frames.php?room=3"],
  1034. ["chat_5", "frames.php?room=4"],
  1035. ]
  1036. },
  1037. }
  1038. }
  1039.  
  1040. function getResourceLinks() {
  1041. return {
  1042. "gold": "roulette.php",
  1043. "wood": "auction.php?cat=res&sort=0&type=1",
  1044. "ore": "auction.php?cat=res&sort=0&type=2",
  1045. "mercury": "auction.php?cat=res&sort=0&type=3",
  1046. "sulfur": "auction.php?cat=res&sort=0&type=4",
  1047. "crystals": "auction.php?cat=res&sort=0&type=5",
  1048. "gems": "auction.php?cat=res&sort=0&type=6",
  1049. "diamonds": "hwm_donate_page_new.php",
  1050. }
  1051. }
  1052.  
  1053. function getStyles() {
  1054. return `
  1055. <style>
  1056. body {
  1057. margin: 0;
  1058. padding: 0;
  1059. }
  1060.  
  1061. #new_header {
  1062. display: flex;
  1063. flex-direction: column;
  1064. align-items: center;
  1065. }
  1066.  
  1067. .top_line {
  1068. width: 100%;
  1069. height: 32px;
  1070. display: flex;
  1071. flex-direction: row;
  1072. flex-wrap: nowrap;
  1073. }
  1074.  
  1075. .top_left_container, .top_right_container {
  1076. height: 100%;
  1077. display: flex;
  1078. flex-direction: row;
  1079. flex-wrap: nowrap;
  1080. flex-grow: 1;
  1081. }
  1082.  
  1083. .top_left_left {
  1084. height: 100%;
  1085. width: 52px;
  1086. background-image: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side2.png");
  1087. background-size: 256px 32px;
  1088. background-repeat: no-repeat;
  1089. }
  1090.  
  1091. .top_left_right {
  1092. min-width: 100px;
  1093. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side1.png") no-repeat top right;
  1094. background-size: 256px 32px;
  1095.  
  1096. }
  1097.  
  1098. /*#logo_container {*/
  1099. /* position: relative;*/
  1100. /*}*/
  1101. /*.logo {*/
  1102. /* max-width: 128px;*/
  1103. /* max-height: 64px;*/
  1104. /*}*/
  1105. #notifications {
  1106. height: 32px;
  1107. float: right;
  1108. display: flex;
  1109. flex-direction: row;
  1110. flex-wrap: nowrap;
  1111. align-items: center;
  1112. margin-right: 10%;
  1113. }
  1114.  
  1115. #heart_container {
  1116. background-image: url("https://dcdn.heroeswm.ru/i/new_top/mm_rp_health.png");
  1117. background-size: contain;
  1118. width: 32px;
  1119. height: 32px;
  1120. margin: auto;
  1121. }
  1122.  
  1123. #heart_container:hover #health_amount {
  1124. display: initial !important;
  1125. position: absolute;
  1126. color: white;
  1127. transform: translate(10%, -100%);
  1128. text-shadow: 1px 0 0 #000, 0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000;
  1129.  
  1130. }
  1131.  
  1132. .sh_HMResIconBlock {
  1133. position: relative;
  1134. left: 15px;
  1135. top: 15px;
  1136. }
  1137.  
  1138. .health_animation {
  1139. position: relative;
  1140. }
  1141.  
  1142. #heart {
  1143. width: 27px;
  1144. height: 27px;
  1145. }
  1146.  
  1147. #mana_container {
  1148. background-image: url("https://dcdn.heroeswm.ru/i/new_top/mm_rp_mana.png");
  1149. background-size: contain;
  1150. width: 32px;
  1151. height: 32px;
  1152. margin: auto;
  1153. display: grid;
  1154. grid-template-columns: 1fr;
  1155. grid-template-rows: 1fr;
  1156. overflow: hidden;
  1157. }
  1158. .mana_animation {
  1159. position: relative;
  1160. grid-column-start: 1;
  1161. grid-row-start: 1;
  1162. z-index: 4;
  1163. }
  1164.  
  1165. .mana {
  1166. grid-column-start: 1;
  1167. grid-row-start: 1;
  1168. z-index: 3;
  1169. }
  1170.  
  1171. #mana_amount {
  1172. grid-column-start: 1;
  1173. grid-row-start: 1;
  1174. z-index: 5;
  1175. margin: auto;
  1176. color: white;
  1177. }
  1178.  
  1179. #mana_container:hover #mana_amount {
  1180. display: initial !important;
  1181. color: white;
  1182. text-shadow: 1px 0 0 #000, 0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000;
  1183. }
  1184.  
  1185. .top_right_right {
  1186. width: 52px;
  1187. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side2.png") no-repeat top right;
  1188. background-size: 256px 32px;
  1189. }
  1190.  
  1191. .top_right_left {
  1192. min-width: 100px;
  1193. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side1.png") no-repeat top left;
  1194. background-size: 256px 32px;
  1195. }
  1196.  
  1197. .top_wing_middle {
  1198. min-width: 175px;
  1199. width: 100%;
  1200. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_mid.png") repeat-x top left;
  1201. background-size: 32px;
  1202. }
  1203.  
  1204. .time_online_radio_container {
  1205. display: flex;
  1206. flex-direction: row;
  1207. flex-wrap: nowrap;
  1208. align-items: center;
  1209. margin-left: 10%;
  1210. }
  1211. #hwm_time, #hwm_online {
  1212. color: #ccb89f;
  1213. }
  1214.  
  1215. .top_resource_container {
  1216. background: url("https://dcdn.heroeswm.ru/i/new_top/rp_bg_mid.png");
  1217. background-size: contain;
  1218. }
  1219.  
  1220. .new_header_menu {
  1221. background: url("https://dcdn.heroeswm.ru/i/new_top/mm_dd_tile.jpg");
  1222. min-height: 70px;
  1223. padding: 0;
  1224. width: 100%;
  1225. display: flex;
  1226. flex-direction: row;
  1227. flex-wrap: nowrap;
  1228. justify-content: space-between;
  1229. }
  1230. .common_menu_container {
  1231. margin-top: 5px;
  1232. display: flex;
  1233. flex-direction: row;
  1234. flex-wrap: nowrap;
  1235. justify-content: center;
  1236. align-items: center;
  1237. overflow: hidden;
  1238. }
  1239. .timers_container {
  1240. display: flex;
  1241. flex-direction: row;
  1242. flex-wrap: nowrap;
  1243. justify-content: center;
  1244. align-items: center;
  1245. overflow: hidden;
  1246. }
  1247. .mm_item {
  1248. margin: 0;
  1249. }
  1250. .mm_item + .mm_item {
  1251. margin-left: 5px;
  1252. }
  1253.  
  1254. .left_dragon, .right_dragon {
  1255. }
  1256. .left_dragon {
  1257. transform: scaleX(-1);
  1258. }
  1259. .middle_menus {
  1260. display: flex;
  1261. flex-direction: column;
  1262. justify-content: center;
  1263. margin-bottom: 8px;
  1264. margin-top: 8px;
  1265. }
  1266. .menu_button_text {
  1267. height:100%;
  1268. display: flex;
  1269. justify-content: center;
  1270. align-items: center;
  1271. color: #fad49f;
  1272. font-weight: bold;
  1273. }
  1274. .small_text_button {
  1275. height:24px;
  1276. }
  1277. .small_text_inside {
  1278. height:24px;
  1279. }
  1280. </style>
  1281. `
  1282. }
  1283.  
  1284. function getDarkStyles() {
  1285. let mainTextColor = `#d0d0d0`
  1286. return `
  1287. <style>
  1288. body {
  1289. background: #1f2023 !important;
  1290. }
  1291. td, .forum > td {
  1292. color: ${mainTextColor} !important;
  1293. background-image: none !important;
  1294. }
  1295. font {
  1296. color: ${mainTextColor} !important;
  1297. opacity: 0.65;
  1298. }
  1299. a, .forum > a {
  1300. color: ${mainTextColor} !important;
  1301. /*opacity: 0.87;*/
  1302. }
  1303. div {
  1304. color: #121212;
  1305. }
  1306. .txt {
  1307. color: ${mainTextColor};
  1308. /*opacity: 0.87;*/
  1309. }
  1310. .pi {
  1311. color: ${mainTextColor};
  1312. /*opacity: 0.87;*/
  1313. }
  1314. .wblight, .wb2, .wb td{
  1315. background-color: #2d2f34;
  1316. }
  1317. .wbwhite {
  1318. background-color: #383b40;
  1319. }
  1320. table.table3, table.table3 th {
  1321. background-color: #383b40;
  1322. }
  1323. .forum tr:not(.second) > td {
  1324. background-color: #383b40 !important;
  1325. }
  1326. table.forum tr.message_footer td {
  1327. background-color: #27292d !important;
  1328. }
  1329. .forum span, .second {
  1330. background-color: #2d2f34 !important;
  1331. }
  1332. #home_2 {
  1333. color: ${mainTextColor};
  1334. }
  1335. #hwm_for_zoom {
  1336. background-color: #27292d !important;
  1337. }
  1338. #hwm_for_zoom * {
  1339. color: ${mainTextColor};
  1340. }
  1341. .dark_seconds {
  1342. color: #a50909;
  1343. }
  1344. * {
  1345. border-color: #55565d !important;
  1346. }
  1347. table td.tlight {
  1348. background-color: #2d2f34 !important;
  1349. background-image: none;
  1350. }
  1351. table td.twhite {
  1352. background-color: #383b40 !important;
  1353. background-image: none;
  1354. }
  1355. #pa,#pd, #pp, #pk, #pl, #pm, #pi, #ap, #sc {
  1356. color: ${mainTextColor} !important;
  1357. }
  1358. </style>
  1359. `
  1360. }
  1361. })(window);