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