HWM-UI-UX-MOD

try to take over the world!

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

  1. // ==UserScript==
  2. // @name HWM-UI-UX-MOD
  3. // @namespace https://greasyfork.org/ru/scripts/421913-hwm-ui-ux-mod
  4. // @version 0.4
  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}">
  446. <a href="${buttonInfo.href}">
  447. <div class="mm_item_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">
  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">
  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">
  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">
  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">
  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">
  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">
  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">
  503. <div class="menu_button_text">${getTranslation("leader_guild")} 00:00</div>
  504. </div>`
  505. }
  506. return result
  507. }
  508. function getRemainingTime(timeSet, timeCount) {
  509. let hwmDate = getHwmDate()
  510. let timeSetHwm = new Date(timeSet)
  511. return secondsToHumanDate(diffDateInSeconds(timeSetHwm, hwmDate) + timeCount * 60)
  512. }
  513. function diffDateInSeconds(dt1, dt2) {
  514. return Math.round((dt1.getTime() - dt2.getTime()) / 1000);
  515. }
  516. // helpers
  517. function getCookie(name) {
  518. const value = `; ${document.cookie}`;
  519. const parts = value.split(`; ${name}=`);
  520. if (parts.length === 2) return parts.pop().split(';').shift();
  521. }
  522.  
  523. function doGet(url, callback) {
  524. GM_xmlhttpRequest({
  525. method: "GET",
  526. url: url,
  527. overrideMimeType: "text/xml; charset=windows-1251",
  528. onload: function (res) {
  529. callback(new DOMParser().parseFromString(res.responseText, "text/html"))
  530. }
  531. });
  532. }
  533.  
  534. function doPost(url, params, callback) {
  535. GM_xmlhttpRequest({
  536. method: "POST",
  537. url: url,
  538. data: params,
  539. onload: callback,
  540. });
  541. }
  542.  
  543. function removeElement(element) {
  544. element.parentNode.removeChild(element)
  545. }
  546.  
  547. function $(id, where = document) {
  548. return where.querySelector(`#${id}`);
  549. }
  550.  
  551. function get(key, def) {
  552. let result = JSON.parse(localStorage[key] === undefined ? null : localStorage[key]);
  553. return result == null ? def : result;
  554.  
  555. }
  556.  
  557. function set(key, val) {
  558. localStorage[key] = JSON.stringify(val);
  559. }
  560.  
  561. function getScrollHeight() {
  562. return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
  563. }
  564.  
  565. function getClientWidth() {
  566. return document.compatMode === 'CSS1Compat' && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth;
  567. }
  568.  
  569. function findAll(regexPattern, sourceString) {
  570. let output = []
  571. let match
  572. let regexPatternWithGlobal = RegExp(regexPattern, [...new Set("g" + regexPattern.flags)].join(""))
  573. while (match = regexPatternWithGlobal.exec(sourceString)) {
  574. delete match.input
  575. output.push(match)
  576. }
  577. return output
  578. }
  579.  
  580. function sortByKey(array, key) {
  581. return array.sort((a, b) => {
  582. let x = a[key];
  583. let y = b[key];
  584. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  585. });
  586. }
  587.  
  588. function getHwmDate() {
  589. let today = new Date();
  590. let localOffset = -(today.getTimezoneOffset() / 60);
  591. let destinationOffset = +3;
  592.  
  593. let offset = destinationOffset - localOffset;
  594. return new Date(new Date().getTime() + offset * 3600 * 1000)
  595.  
  596. }
  597.  
  598. function hwmDateToHuman(hwmDate) {
  599. let hours = hwmDate.getHours().toString().length === 1
  600. ? "0" + hwmDate.getHours().toString()
  601. : hwmDate.getHours().toString()
  602. let minutes = hwmDate.getMinutes().toString().length === 1
  603. ? "0" + hwmDate.getMinutes().toString()
  604. : hwmDate.getMinutes().toString()
  605. let seconds = hwmDate.getSeconds().toString().length === 1
  606. ? "0" + hwmDate.getSeconds().toString()
  607. : hwmDate.getSeconds().toString()
  608. return hours + ":" + minutes + ":" + seconds
  609. }
  610.  
  611. function secondsToHumanDate(seconds) {
  612. // Hours, minutes and seconds
  613. var hrs = ~~(seconds / 3600);
  614. var mins = ~~((seconds % 3600) / 60);
  615. var secs = ~~seconds % 60;
  616.  
  617. // Output like "1:01" or "4:03:59" or "123:03:59"
  618. var ret = "";
  619. if (hrs > 0) {
  620. ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
  621. }
  622. ret += "" + mins + ":" + (secs < 10 ? "0" : "");
  623. ret += "" + secs;
  624. return ret;
  625. }
  626.  
  627. function getTranslation(textId) {
  628. return allTexts[textId][language]
  629. }
  630.  
  631. function loadSettings() {
  632. settings = get('hwm_header_settings', defaultSettings)
  633. for (const [key, value] of Object.entries(defaultSettings)) {
  634. if (settings[key] === undefined) {
  635. settings[key] = value
  636. }
  637. }
  638. }
  639.  
  640. function loadTimersInfo() {
  641. timersInfo = get('timers_data', {})
  642. }
  643. function getAllTexts() {
  644. return {
  645. 'isTimeWithSeconds': {
  646. "rus": "Показывать время с секундами",
  647. "eng": "Show time with seconds",
  648. },
  649. 'isShowTimers': {
  650. "rus": "Показывать таймеры гильдий",
  651. "eng": "Show guilds' timers",
  652. },
  653. 'isDarkTheme': {
  654. "rus": "Темная тема",
  655. "eng": "Dark theme"
  656. },
  657. 'isTextButtons': {
  658. "rus": "Старые текстовые кнопки",
  659. "eng": "Show old text buttons"
  660. },
  661. 'isHomeButton': {
  662. "rus": "Персонаж",
  663. "eng": "Home"
  664. },
  665. 'isInventoryButton': {
  666. "rus": "Инвентарь",
  667. "eng": "Inventory"
  668. },
  669. 'isMapButton': {
  670. "rus": "Карта",
  671. "eng": "Map"
  672. },
  673. 'isBattleButton': {
  674. "rus": "Битвы",
  675. "eng": "Battles"
  676. },
  677. 'isTavernButton': {
  678. "rus": "Таверна",
  679. "eng": "Tavern"
  680. },
  681. 'isRouletteButton': {
  682. "rus": "Рулетка",
  683. "eng": "Roulette"
  684. },
  685. 'isLeaderboardButton': {
  686. "rus": "Рейтинг",
  687. "eng": "Leaderboards"
  688. },
  689. 'isForumButton': {
  690. "rus": "Форум",
  691. "eng": "Forum"
  692. },
  693. 'isChatButton': {
  694. "rus": "Чат",
  695. "eng": "Chat"
  696. },
  697. 'MenuHome': {
  698. "rus": "Персонаж",
  699. "eng": "Home"
  700. },
  701. 'MenuInventory': {
  702. "rus": "Инвентарь",
  703. "eng": "Inventory"
  704. },
  705. 'MenuMap': {
  706. "rus": "Карта",
  707. "eng": "Map"
  708. },
  709. 'MenuBattles': {
  710. "rus": "Битвы",
  711. "eng": "Battles"
  712. },
  713. 'MenuTavern': {
  714. "rus": "Таверна",
  715. "eng": "Tavern"
  716. },
  717. 'MenuRoulette': {
  718. "rus": "Рулетка",
  719. "eng": "Roulette"
  720. },
  721. 'MenuStat': {
  722. "rus": "Рейтинг",
  723. "eng": "Leaderboards"
  724. },
  725. 'MenuForum': {
  726. "rus": "Форум",
  727. "eng": "Forum"
  728. },
  729. 'MenuChat': {
  730. "rus": "Чат",
  731. "eng": "Chat"
  732. },
  733. 'myself': {
  734. "rus": "Я",
  735. "eng": "Myself"
  736. },
  737. 'inventory': {
  738. "rus": "Инвентарь",
  739. "eng": "Inventory"
  740. },
  741. 'shop': {
  742. "rus": "Магазин",
  743. "eng": "Artifact shop"
  744. },
  745. 'auction': {
  746. "rus": "Рынок",
  747. "eng": "Market"
  748. },
  749. 'choose_army': {
  750. "rus": "Набор армии",
  751. "eng": "Recruiting"
  752. },
  753. 'castle': {
  754. "rus": "Замок",
  755. "eng": "Castle"
  756. },
  757. 'skills': {
  758. "rus": "Навыки",
  759. "eng": "Talents"
  760. },
  761. 'mailbox': {
  762. "rus": "Почта",
  763. "eng": "Mailbox"
  764. },
  765. 'transfer': {
  766. "rus": "Передача ресурсов",
  767. "eng": "Transfer"
  768. },
  769. 'facility1': {
  770. "rus": "Добыча",
  771. "eng": "Mining"
  772. },
  773. 'facility2': {
  774. "rus": "Обработка",
  775. "eng": "Machining"
  776. },
  777. 'facility3': {
  778. "rus": "Производство",
  779. "eng": "Production"
  780. },
  781. 'houses': {
  782. "rus": "Дома",
  783. "eng": "Public services"
  784. },
  785. 'one_to_one': {
  786. "rus": "Дуэли",
  787. "eng": "Duels"
  788. },
  789. 'many_to_many': {
  790. "rus": "Групповые бои",
  791. "eng": "Group battles"
  792. },
  793. 'guild_pvp': {
  794. "rus": "Гильдия тактиков",
  795. "eng": "Commanders' guild"
  796. },
  797. 'guild_task': {
  798. "rus": "Гильдия стражей",
  799. "eng": "Watchers' guild"
  800. },
  801. 'guild_leader': {
  802. "rus": "Гильдия лидеров",
  803. "eng": "Leaders guild"
  804. },
  805. 'clanwars': {
  806. "rus": "Бои за территории",
  807. "eng": "Clan wars"
  808. },
  809. 'tournaments': {
  810. "rus": "Турниры",
  811. "eng": "Tounaments"
  812. },
  813. 'spin_history': {
  814. "rus": "История игр",
  815. "eng": "Spin history"
  816. },
  817. 'lucky_boxes': {
  818. "rus": "Редкие ларцы",
  819. "eng": "Chests of abundance"
  820. },
  821. 'top_heroes': {
  822. "rus": "Рейтинг воинов",
  823. "eng": "Top warriors"
  824. },
  825. 'top_clans': {
  826. "rus": "Рейтинг кланов",
  827. "eng": "Top clans"
  828. },
  829. 'top_hunters': {
  830. "rus": "Рейтинг охотников",
  831. "eng": "Top hunters"
  832. },
  833. 'top_mercenaries': {
  834. "rus": "Рейтинг наемников",
  835. "eng": "Top mercenaries"
  836. },
  837. 'top_shareholders': {
  838. "rus": "Рейтинг акционеров",
  839. "eng": "Top shareholders"
  840. },
  841. 'personal_records': {
  842. "rus": "Мои охоты",
  843. "eng": "My hunt records"
  844. },
  845. 'general_forum': {
  846. "rus": "Общий форум",
  847. "eng": "General forum"
  848. },
  849. 'help_forum': {
  850. "rus": "Помощь по игре",
  851. "eng": "Q&A forum"
  852. },
  853. 'trade_forum': {
  854. "rus": "Торговый форум",
  855. "eng": "Trade forums"
  856. },
  857. 'reference': {
  858. "rus": "Об игре",
  859. "eng": "About the game"
  860. },
  861. 'hwm_newspaper': {
  862. "rus": "Новостная лента",
  863. "eng": "Daily news"
  864. },
  865. 'chat_1': {
  866. "rus": "Комната вопросов",
  867. "eng": "Inquiry"
  868. },
  869. 'chat_2': {
  870. "rus": "Общая комната",
  871. "eng": "Common"
  872. },
  873. 'chat_3': {
  874. "rus": "Торговая палата",
  875. "eng": "Merchant"
  876. },
  877. 'chat_4': {
  878. "rus": "Рулетка",
  879. "eng": "Roulette"
  880. },
  881. 'chat_5': {
  882. "rus": "Карты",
  883. "eng": "Tavern"
  884. },
  885. 'labor_guild': {
  886. "rus": "ГР",
  887. "eng": "LG"
  888. },
  889. 'leader_guild': {
  890. "rus": "ГЛ",
  891. "eng": "LeG"
  892. },
  893. 'hunt_guild': {
  894. "rus": "ГО",
  895. "eng": "HG"
  896. },
  897. 'thief_guild': {
  898. "rus": "ГВ",
  899. "eng": "TG"
  900. },
  901. '': {
  902. "rus": "",
  903. "eng": ""
  904. },
  905.  
  906. }
  907. }
  908.  
  909. function getDefaultSettings() {
  910. return {
  911. "isTimeWithSeconds": true,
  912. "isShowTimers": true,
  913. "isDarkTheme": false,
  914. "isTextButtons": false,
  915. "isHomeButton": true,
  916. "isInventoryButton": false,
  917. "isMapButton": true,
  918. "isBattleButton": true,
  919. "isTavernButton": true,
  920. "isRouletteButton": true,
  921. "isLeaderboardButton": true,
  922. "isForumButton": true,
  923. "isChatButton": true,
  924. }
  925. }
  926.  
  927. function getButtonInfos() {
  928. return {
  929. "isHomeButton": {
  930. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelCharacter.png",
  931. "id": "MenuHome",
  932. "href": "home.php",
  933. "dropDown": [
  934. ["myself", `pl_info.php?id=${getCookie("pl_id")}`],
  935. ["inventory", "inventory.php"],
  936. ["shop", "shop.php"],
  937. ["auction", "auction.php"],
  938. ["choose_army", "army.php"],
  939. ["castle", "castle.php"],
  940. ["skills", "skillwheel.php"],
  941. ["mailbox", "sms.php"],
  942. ["transfer", "transfer.php"],
  943. ]
  944. },
  945. "isInventoryButton": {
  946. "image": "https://dcdn.heroeswm.ru/i/mobile_view/icons/_panelInventory.png",
  947. "id": "MenuInventory",
  948. "href": "inventory.php",
  949. "dropDown": []
  950. },
  951. "isMapButton": {
  952. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelMap.png",
  953. "id": "MenuMap",
  954. "href": "map.php",
  955. "dropDown": [
  956. ["facility1", "map.php?st=mn"],
  957. ["facility2", "map.php?st=fc"],
  958. ["facility3", "map.php?st=sh"],
  959. ["houses", "map.php?st=hs"],
  960. ]
  961. },
  962. "isBattleButton": {
  963. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelBattles.png",
  964. "id": "MenuBattles",
  965. "href": "bselect.php",
  966. "dropDown": [
  967. ["one_to_one", "one_to_one.php"],
  968. ["many_to_many", "group_wars.php"],
  969. ["guild_pvp", "pvp_guild.php"],
  970. ["guild_task", "task_guild.php"],
  971. ["guild_leader", "leader_guild.php"],
  972. ["clanwars", "mapwars.php"],
  973. ["tournaments", "tournaments.php"],
  974. ]
  975. },
  976. "isTavernButton": {
  977. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelTavern.png",
  978. "id": "MenuTavern",
  979. "href": "tavern.php",
  980. "dropDown": []
  981. },
  982. "isRouletteButton": {
  983. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelRoulette.png",
  984. "id": "MenuRoulette",
  985. "href": "roulette.php",
  986. "dropDown": [
  987. ["spin_history", "allroul.php"],
  988. ["lucky_boxes", "gift_box_log.php"],
  989.  
  990. ]
  991. },
  992. "isLeaderboardButton": {
  993. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelRate.png",
  994. "id": "MenuStat",
  995. "href": "plstats.php",
  996. "dropDown": [
  997. ["top_heroes", "plstats.php"],
  998. ["top_clans", "clanstat.php"],
  999. ["top_hunters", "plstats_hunters.php"],
  1000. ["top_mercenaries", "plstats_merc.php"],
  1001. ["top_shareholders", "sholders_stat.php"],
  1002. ["personal_records", `pl_hunter_stat.php?id=${getCookie("pl_id")}`],
  1003.  
  1004. ]
  1005. },
  1006. "isForumButton": {
  1007. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelForum.png",
  1008. "id": "MenuForum",
  1009. "href": "forum.php",
  1010. "dropDown": [
  1011. ["general_forum", "forum_thread.php?id=2"],
  1012. ["help_forum", "forum_thread.php?id=10"],
  1013. ["trade_forum", "forum.php#t1"],
  1014. ["reference", "help.php"],
  1015. ["hwm_newspaper", "https://daily.heroeswm.ru/"],
  1016.  
  1017. ]
  1018. },
  1019. "isChatButton": {
  1020. "image": "https://dcdn.heroeswm.ru/i/new_top/_panelChat.png",
  1021. "id": "MenuChat",
  1022. "href": "frames.php",
  1023. "dropDown": [
  1024. ["chat_1", "frames.php?room=0"],
  1025. ["chat_2", "frames.php?room=1"],
  1026. ["chat_3", "frames.php?room=2"],
  1027. ["chat_4", "frames.php?room=3"],
  1028. ["chat_5", "frames.php?room=4"],
  1029. ]
  1030. },
  1031. }
  1032. }
  1033.  
  1034. function getResourceLinks() {
  1035. return {
  1036. "gold": "roulette.php",
  1037. "wood": "auction.php?cat=res&sort=0&type=1",
  1038. "ore": "auction.php?cat=res&sort=0&type=2",
  1039. "mercury": "auction.php?cat=res&sort=0&type=3",
  1040. "sulfur": "auction.php?cat=res&sort=0&type=4",
  1041. "crystals": "auction.php?cat=res&sort=0&type=5",
  1042. "gems": "auction.php?cat=res&sort=0&type=6",
  1043. "diamonds": "hwm_donate_page_new.php",
  1044. }
  1045. }
  1046.  
  1047. function getStyles() {
  1048. return `
  1049. <style>
  1050. ${settings.isTextButtons ? ".mm_item, .mm_item_inside {height:24px}; .mm_item_inside {display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center;} .menu_button_text{height:100%}" : ""};
  1051. body {
  1052. margin: 0;
  1053. padding: 0;
  1054. }
  1055.  
  1056. #new_header {
  1057. display: flex;
  1058. flex-direction: column;
  1059. align-items: center;
  1060. }
  1061.  
  1062. .top_line {
  1063. width: 100%;
  1064. height: 32px;
  1065. display: flex;
  1066. flex-direction: row;
  1067. flex-wrap: nowrap;
  1068. }
  1069.  
  1070. .top_left_container, .top_right_container {
  1071. height: 100%;
  1072. display: flex;
  1073. flex-direction: row;
  1074. flex-wrap: nowrap;
  1075. flex-grow: 1;
  1076. }
  1077.  
  1078. .top_left_left {
  1079. height: 100%;
  1080. width: 52px;
  1081. background-image: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side2.png");
  1082. background-size: 256px 32px;
  1083. background-repeat: no-repeat;
  1084. }
  1085.  
  1086. .top_left_right {
  1087. min-width: 100px;
  1088. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side1.png") no-repeat top right;
  1089. background-size: 256px 32px;
  1090.  
  1091. }
  1092.  
  1093. /*#logo_container {*/
  1094. /* position: relative;*/
  1095. /*}*/
  1096. /*.logo {*/
  1097. /* max-width: 128px;*/
  1098. /* max-height: 64px;*/
  1099. /*}*/
  1100. #notifications {
  1101. height: 32px;
  1102. float: right;
  1103. display: flex;
  1104. flex-direction: row;
  1105. flex-wrap: nowrap;
  1106. align-items: center;
  1107. margin-right: 10%;
  1108. }
  1109.  
  1110. #heart_container {
  1111. background-image: url("https://dcdn.heroeswm.ru/i/new_top/mm_rp_health.png");
  1112. background-size: contain;
  1113. width: 32px;
  1114. height: 32px;
  1115. margin: auto;
  1116. }
  1117.  
  1118. #heart_container:hover #health_amount {
  1119. display: initial !important;
  1120. position: absolute;
  1121. color: white;
  1122. transform: translate(10%, -100%);
  1123. text-shadow: 1px 0 0 #000, 0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000;
  1124.  
  1125. }
  1126.  
  1127. .sh_HMResIconBlock {
  1128. position: relative;
  1129. left: 15px;
  1130. top: 15px;
  1131. }
  1132.  
  1133. .health_animation {
  1134. position: relative;
  1135. }
  1136.  
  1137. #heart {
  1138. width: 27px;
  1139. height: 27px;
  1140. }
  1141.  
  1142. #mana_container {
  1143. background-image: url("https://dcdn.heroeswm.ru/i/new_top/mm_rp_mana.png");
  1144. background-size: contain;
  1145. width: 32px;
  1146. height: 32px;
  1147. margin: auto;
  1148. display: grid;
  1149. grid-template-columns: 1fr;
  1150. grid-template-rows: 1fr;
  1151. overflow: hidden;
  1152. }
  1153. .mana_animation {
  1154. position: relative;
  1155. grid-column-start: 1;
  1156. grid-row-start: 1;
  1157. z-index: 4;
  1158. }
  1159.  
  1160. .mana {
  1161. grid-column-start: 1;
  1162. grid-row-start: 1;
  1163. z-index: 3;
  1164. }
  1165.  
  1166. #mana_amount {
  1167. grid-column-start: 1;
  1168. grid-row-start: 1;
  1169. z-index: 5;
  1170. margin: auto;
  1171. color: white;
  1172. }
  1173.  
  1174. #mana_container:hover #mana_amount {
  1175. display: initial !important;
  1176. color: white;
  1177. text-shadow: 1px 0 0 #000, 0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000;
  1178. }
  1179.  
  1180. .top_right_right {
  1181. width: 52px;
  1182. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side2.png") no-repeat top right;
  1183. background-size: 256px 32px;
  1184. }
  1185.  
  1186. .top_right_left {
  1187. min-width: 100px;
  1188. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_side1.png") no-repeat top left;
  1189. background-size: 256px 32px;
  1190. }
  1191.  
  1192. .top_wing_middle {
  1193. min-width: 175px;
  1194. width: 100%;
  1195. background: url("https://dcdn.heroeswm.ru/i/new_top/extra_bg_mid.png") repeat-x top left;
  1196. background-size: 32px;
  1197. }
  1198.  
  1199. .time_online_radio_container {
  1200. display: flex;
  1201. flex-direction: row;
  1202. flex-wrap: nowrap;
  1203. align-items: center;
  1204. margin-left: 10%;
  1205. }
  1206. #hwm_time, #hwm_online {
  1207. color: #b12424;
  1208. }
  1209.  
  1210. .top_resource_container {
  1211. background: url("https://dcdn.heroeswm.ru/i/new_top/rp_bg_mid.png");
  1212. background-size: contain;
  1213. }
  1214.  
  1215. .new_header_menu {
  1216. background: url("https://dcdn.heroeswm.ru/i/new_top/mm_dd_tile.jpg");
  1217. min-height: 70px;
  1218. padding: 0;
  1219. width: 100%;
  1220. display: flex;
  1221. flex-direction: row;
  1222. flex-wrap: nowrap;
  1223. justify-content: space-between;
  1224. }
  1225. .common_menu_container {
  1226. margin-top: 5px;
  1227. display: flex;
  1228. flex-direction: row;
  1229. flex-wrap: nowrap;
  1230. justify-content: center;
  1231. align-items: center;
  1232. overflow: hidden;
  1233. }
  1234. .timers_container {
  1235. display: flex;
  1236. flex-direction: row;
  1237. flex-wrap: nowrap;
  1238. justify-content: center;
  1239. align-items: center;
  1240. overflow: hidden;
  1241. }
  1242. .mm_item {
  1243. margin: 0;
  1244. }
  1245. .mm_item + .mm_item {
  1246. margin-left: 5px;
  1247. }
  1248.  
  1249. .left_dragon, .right_dragon {
  1250. }
  1251. .left_dragon {
  1252. transform: scaleX(-1);
  1253. }
  1254. .middle_menus {
  1255. display: flex;
  1256. flex-direction: column;
  1257. justify-content: center;
  1258. }
  1259. .menu_button_text {
  1260. display: flex;
  1261. justify-content: center;
  1262. align-items: center;
  1263. color: #fad49f;
  1264. font-weight: bold;
  1265. }
  1266. </style>
  1267. `
  1268. }
  1269.  
  1270. function getDarkStyles() {
  1271. let mainTextColor = `#d0d0d0`
  1272. return `
  1273. <style>
  1274. body {
  1275. background: #1f2023 !important;
  1276. }
  1277. td, .forum > td {
  1278. color: ${mainTextColor} !important;
  1279. background-image: none !important;
  1280. }
  1281. font {
  1282. color: ${mainTextColor} !important;
  1283. opacity: 0.65;
  1284. }
  1285. a, .forum > a {
  1286. color: ${mainTextColor} !important;
  1287. /*opacity: 0.87;*/
  1288. }
  1289. div {
  1290. color: #121212;
  1291. }
  1292. .txt {
  1293. color: ${mainTextColor};
  1294. /*opacity: 0.87;*/
  1295. }
  1296. .pi {
  1297. color: ${mainTextColor};
  1298. /*opacity: 0.87;*/
  1299. }
  1300. .wblight, .wb2, .wb td{
  1301. background-color: #2d2f34;
  1302. }
  1303. .wbwhite {
  1304. background-color: #383b40;
  1305. }
  1306. table.table3, table.table3 th {
  1307. background-color: #383b40;
  1308. }
  1309. .forum tr:not(.second) > td {
  1310. background-color: #383b40 !important;
  1311. }
  1312. table.forum tr.message_footer td {
  1313. background-color: #27292d !important;
  1314. }
  1315. .forum span, .second {
  1316. background-color: #2d2f34 !important;
  1317. }
  1318. #home_2 {
  1319. color: ${mainTextColor};
  1320. }
  1321. #hwm_for_zoom {
  1322. background-color: #27292d !important;
  1323. }
  1324. #hwm_for_zoom * {
  1325. color: ${mainTextColor};
  1326. }
  1327. .dark_seconds {
  1328. color: #a50909;
  1329. }
  1330. * {
  1331. border-color: #55565d !important;
  1332. }
  1333. table td.tlight {
  1334. background-color: #2d2f34 !important;
  1335. background-image: none;
  1336. }
  1337. table td.twhite {
  1338. background-color: #383b40 !important;
  1339. background-image: none;
  1340. }
  1341. #pa,#pd, #pp, #pk, #pl, #pm, #pi, #ap, #sc {
  1342. color: ${mainTextColor} !important;
  1343. }
  1344. </style>
  1345. `
  1346. }
  1347. })(window);