hwmNightMode

Ночная тема

  1. // ==UserScript==
  2. // @name hwmNightMode
  3. // @author Мифист, Tamozhnya1
  4. // @namespace Tamozhnya1
  5. // @description Ночная тема
  6. // @version 11.5
  7. // @include https://*heroeswm.ru/*
  8. // @include https://*lordswm.com/*
  9. // @exclude */chat*
  10. // @exclude */war*
  11. // @exclude */cgame*
  12. // @exclude /\/quest_(?!journal)/
  13. // @exclude /\.(ru|com)\/$/
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_deleteValue
  17. // @noframes
  18. // @license MIT
  19. // ==/UserScript==
  20.  
  21. const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
  22. const PlayerId = playerIdMatch ? playerIdMatch[1] : "";
  23. const lang = document.documentElement.lang || (location.hostname == "www.lordswm.com" ? "en" : "ru");
  24. const isEn = lang == "en";
  25. const win = window.wrappedJSObject || unsafeWindow;
  26. const isHeartOnPage = (document.querySelector("canvas#heart") || document.querySelector("div#heart_js_mobile")) ? true : false;
  27. const isMooving = location.pathname == '/map.php' && !document.getElementById("map_right_block");
  28. const isNewInterface = document.querySelector("div#hwm_header") ? true : false;
  29. const isMobileInterface = document.querySelector("div#btnMenuGlobal") ? true : false;
  30. const isMobileDevice = mobileCheck(); // Там нет мышки
  31. const isNewPersonPage = document.querySelector("div#hwm_no_zoom") ? true : false;
  32.  
  33. fetch.get = (url) => fetch({ url });
  34. fetch.post = (url, data) => fetch({ url, method: 'POST', body: data });
  35.  
  36. if(!PlayerId) {
  37. return;
  38. }
  39. const nightStyle = parseNode(`<style>
  40. :root {
  41. overflow-y: auto;
  42. }
  43. :root,
  44. :root > body {
  45. color: #ccc;
  46. background-color: #222;
  47. border-color: #888;
  48. }
  49. :root > body * {
  50. border-color: #888;
  51. }
  52. :root .wbwhite,
  53. :root .wblight2 {
  54. background-color: #1d1d1d;
  55. }
  56. :root .wblight {
  57. background-color: #2d2d2d;
  58. }
  59. :root a,
  60. :root td,
  61. :root .txt {
  62. color: #ccc;
  63. }
  64. button,
  65. input[type="button"],
  66. input[type="submit"] {
  67. cursor: pointer;
  68. }
  69. :root input,
  70. :root button {
  71. border-color: initial;
  72. }
  73. :root button:hover,
  74. :root input[type="button"]:hover:root input[type="submit"]:hover {
  75. background-color: #fff;
  76. }
  77. :root :disabled {
  78. color: #666 !important;
  79. background-color: #bbb !important;
  80. cursor: default;
  81. }
  82. :root b,
  83. :root h1,
  84. :root h2,
  85. :root h3,
  86. :root h4,
  87. :root h5,
  88. :root h6,
  89. :root strong {
  90. color: #d0bda6;
  91. }
  92. :root font[color] * {
  93. color: inherit;
  94. }
  95. :root a[href],
  96. :root a[href] > *,
  97. :root b > a[href] {
  98. color: #c9b087;
  99. }
  100. :root a[href]:hover,
  101. :root a[href]:hover *,
  102. :root a[href]:hover + font[color] {
  103. color: #da472d !important;
  104. }
  105. :root font[color="black"],
  106. :root font[color="000000"] {
  107. color: #999;
  108. }
  109. :root font[color="gray"],
  110. :root font[color="#7D7D7D"] {
  111. color: #999;
  112. }
  113. :root font[color="red"],
  114. :root font[color="#CC1100"],
  115. :root font[color="ff0000"] {
  116. color: #d03535;
  117. }
  118. :root font[color="green"],
  119. :root font[color="00ff00"] {
  120. color: #4f9a68;
  121. }
  122. :root font[color="blue"] {
  123. color: #3171a3;
  124. }
  125. :root font[color="purple"] {
  126. color: #ab3cab;
  127. }
  128. font[style$="color:#696156"] {
  129. color: #c9b087 !important;
  130. }
  131. #main_top_table table[width="970"] {
  132. background-color: inherit !important;
  133. }
  134. #main_top_table img,
  135. #main_top_table td[style*="/right_big.jpg"],
  136. #main_top_table td[style*="/line/lbkg.jpg"],
  137. #main_top_table td[style*="/bkgbot.jpg"],
  138. #main_top_table td[style*="/bkgtop.jpg"] {
  139. -webkit-filter: invert(1) grayscale(1) contrast(1.05);
  140. filter: invert(1) grayscale(1) contrast(1.05);
  141. }
  142. #main_top_table td[style*="/t_bot_bkg.jpg"],
  143. #main_top_table td[style*="/t_top_bkg.jpg"],
  144. #main_top_table td[width="9"] {
  145. -webkit-filter: sepia(1) grayscale(0.5);
  146. filter: sepia(1) grayscale(0.5);
  147. }
  148. #main_top_table img.rs,
  149. #main_top_table img[src$="/res_line_botc.jpg"],
  150. #main_top_table img[src$="/res_line_topc.jpg"],
  151. #main_top_table table[width="580"] img {
  152. -webkit-filter: none;
  153. filter: none;
  154. }
  155. #main_top_table td[style$="/top/bkg2.jpg);"] {
  156. background-image: none !important;
  157. background-color: #333 !important;
  158. }
  159. #main_top_table td[height="17"] {
  160. color: #222;
  161. }
  162. #main_top_table td[height="26"][width="88"]:nth-child(3) {
  163. border-right: 2px solid tan;
  164. }
  165. #main_top_table td[height="26"][width="88"]:nth-child(5) {
  166. border-left: 2px solid tan;
  167. }
  168. #breadcrumbs a {
  169. color: #ccc !important;
  170. }
  171. #breadcrumbs a[style$="#ff0000;"] > b {
  172. color: #ea9f2f;
  173. }
  174. #breadcrumbs a:hover,
  175. #breadcrumbs a:hover blink {
  176. color: #c9b087 !important;
  177. }
  178. #breadcrumbs li.subnav:hover b {
  179. color: #dadada !important;
  180. }
  181. #breadcrumbs hr {
  182. border: none;
  183. height: 1px;
  184. background-color: #999;
  185. }
  186. #breadcrumbs blink {
  187. color: #c9b087;
  188. }
  189. .cre_mon_parent [valign="middle"] {
  190. color: #eee;
  191. background: #333 !important;
  192. outline: 1px solid gray;
  193. }
  194. #add_now_count {
  195. color: #c9b087;
  196. }
  197. tr[bgcolor],
  198. td[bgcolor] {
  199. background-color: inherit;
  200. }
  201. tr[bgcolor="#ffffff"],
  202. td[bgcolor="#ffffff"] {
  203. background-color: #222;
  204. }
  205. tr[bgcolor="#eeeeee"],
  206. td[bgcolor="#eeeeee"] {
  207. background-color: #272727;
  208. }
  209. tr[bgcolor="#dddddd"] {
  210. background-color: #404040;
  211. }
  212. td.wb[bgcolor="#cbc9fb"] {
  213. background-color: #263c46;
  214. }
  215. img[name="imgcode"] {
  216. -webkit-filter: invert(0.8);
  217. filter: invert(0.8);
  218. }
  219. img[src$="male.gif"] {
  220. -webkit-filter: invert(0.86);
  221. filter: invert(0.86);
  222. }
  223. img[src$="/horse_gif.gif"],
  224. img[src$="/star0t.gif"],
  225. img[src$="/star1t.gif"],
  226. img[src$="/star12t.gif"],
  227. img[src$="/speed_hunt.png"],
  228. img[src$="/galka.jpg"],
  229. img[src$="/zvezda.png"],
  230. img[src$="/zvezda_empty.png"],
  231. img[src$="/blood_rage.jpg"],
  232. img[src*="/magic/l"],
  233. img[src*="/pvp_"] {
  234. -webkit-filter: invert(0.9) sepia(1);
  235. filter: invert(0.9) sepia(1);
  236. }
  237. [data-page="clan_info"] img[src$="line.gif"],
  238. img[src*="/map/nl"] {
  239. border-radius: 50%;
  240. }
  241. :root .sweet-overlay {
  242. background-color: rgba(27, 27, 27, 0.6);
  243. }
  244. :root .sweet-alert {
  245. background-color: #444;
  246. border: 2px solid #777;
  247. -webkit-user-select: none;
  248. user-select: none;
  249. }
  250. :root .sweet-alert:not(.showSweetAlert) {
  251. opacity: 0 !important;
  252. }
  253. :root .sweet-alert,
  254. :root .sweet-alert * {
  255. transition: none;
  256. animation: none;
  257. }
  258. :root .sweet-alert p {
  259. color: #aaa;
  260. }
  261. :root .sweet-alert button {
  262. background-color: #607d8b !important;
  263. box-shadow: none !important;
  264. }
  265. :root .sweet-alert button.confirm {
  266. background-color: #795548 !important;
  267. }
  268. :root .sweet-alert button:hover {
  269. -webkit-filter: brightness(120%);
  270. filter: brightness(120%);
  271. }
  272. #lbOverlay,
  273. #lbCenter,
  274. #lbBottomContainer {
  275. z-index: 100;
  276. } /* ------------------------------------------- */ /* auction */
  277. [data-page="auction"] td[bgcolor="#9ADEED"] {
  278. background-color: #58423a;
  279. }
  280. [data-page="auction"] td[bgcolor="#A09CEA"] {
  281. background-color: #395f61;
  282. } /* forum */
  283. .forum.c_darker * {
  284. border-color: #888;
  285. }
  286. .forum.c_darker tr {
  287. background-color: #222;
  288. }
  289. .forum.c_darker tr > td[bgcolor="#F5F3EA"],
  290. .forum.c_darker tr.second {
  291. background-color: #333;
  292. }
  293. .forum.c_darker th {
  294. background-color: #555;
  295. }
  296. .forum.c_darker td {
  297. color: #ccc !important;
  298. background-image: none;
  299. outline: 1px solid #444;
  300. outline-offset: -2px;
  301. }
  302. .forum.c_darker td[style$="image: none"] {
  303. outline: none;
  304. }
  305. .forum.c_darker tr > td[colspan] {
  306. background-color: #6d6d6d;
  307. }
  308. .forum.c_darker tr.message_footer td {
  309. color: #888 !important;
  310. background-color: #333;
  311. border: none;
  312. }
  313. .forum.c_darker td a[href] {
  314. color: #c9b087;
  315. }
  316. .forum.c_darker a[href^="forum_thread"] > img {
  317. -webkit-filter: invert(0.9) sepia(0.6);
  318. filter: invert(0.9) sepia(0.6);
  319. }
  320. .forum.c_darker span[style*="background-color: #C1CDCE"] {
  321. background-color: #444 !important;
  322. }
  323. .forum.c_darker font[style*="color:#696156"] {
  324. color: #aaa !important;
  325. }
  326. .forum.c_darker .fsm,
  327. .forum.c_darker .forumt {
  328. color: inherit;
  329. }
  330. #nm_txta {
  331. background-color: #ddd;
  332. }
  333. [data-page="forum_thread"] .forum tr:hover {
  334. background-color: #5d4942 !important;
  335. }
  336. [data-page="forum_thread"] .forum a[href]:hover {
  337. color: #f8be66 !important;
  338. } /* roulette */
  339. [data-page*="roul"] td.wblight {
  340. background-color: #555;
  341. }
  342. [data-page*="roul"] td.wb2 {
  343. background-color: #795548;
  344. } /* tavern */
  345. td[style*="/taverna_bkg.jpg"],
  346. td[style*="/taverna_bkg.jpg"] td[class] {
  347. background-image: none !important;
  348. border-color: #666;
  349. }
  350. td[style*="/taverna_bkg.jpg"] td.tlight {
  351. background-color: #333;
  352. }
  353. td[style*="/taverna_bkg.jpg"] td.twhite {
  354. background-color: #464646;
  355. } /* events */
  356. .Global [class^="TextBlockContent"] {
  357. background: url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/corner4_lt.png") no-repeat top left, url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/corner4_rt.png") no-repeat top right,
  358. url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/corner4_lb.png") no-repeat bottom left, url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/corner4_rb.png") no-repeat bottom right,
  359. url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/winChatDesktop_border_t.png") top left repeat-x, url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/winChatDesktop_border_b.png") bottom left repeat-x,
  360. url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/winChatDesktop_border_l.png") top left repeat-y, url("https://dcdn3.heroeswm.ru/i/naym_event_rogues/winChatDesktop_border_r.png") top right repeat-y;
  361. background-size: 2.2%, 2.2%, 2.2%, 2.2%, auto, auto, auto, auto, auto;
  362. background-color: rgba(35, 35, 35, 0.95);
  363. }
  364. .Global .cre_mon_image1[style],
  365. .Global td[width="60"] {
  366. background-color: #333 !important;
  367. } /* naym_event_set */
  368. [data-page="naym_event_set"] td.wbwhite[width="100%"][align="center"] td[width="60"] {
  369. background-color: inherit !important;
  370. } /* map */
  371. #jsmap {
  372. outline: 2px solid #444;
  373. }
  374. .no_touch_selection > div:first-child {
  375. background-image: linear-gradient(to right, transparent, #1d1d1d, #1d1d1d) !important;
  376. }
  377. .ohota_block,
  378. #map_right_block .wbwhite[style^="border"] {
  379. border-color: inherit !important;
  380. }
  381. [data-page="map"] .ntooltiptext {
  382. color: #333;
  383. background-color: rgba(255, 255, 255, 0.85);
  384. border-color: #222 !important;
  385. box-shadow: 0 0 10px #555;
  386. } /* object-info */
  387. :root .getjob_block {
  388. color: inherit;
  389. background-color: #333;
  390. }
  391. :root .getjob_capcha {
  392. filter: invert(0.9);
  393. }
  394. :root #code {
  395. background: #222;
  396. color: inherit;
  397. box-shadow: 0 0 3px;
  398. } /* army_info */
  399. .army_info {
  400. background-color: #333;
  401. background-image: none;
  402. background-image: linear-gradient(#555, #111);
  403. }
  404. .scroll_content_half {
  405. color: inherit;
  406. }
  407. .scroll_content_half div {
  408. color: #d6b47d;
  409. }
  410. .army_info_skills {
  411. text-align: left;
  412. }
  413. .army_info_skills > div {
  414. color: #ccc;
  415. }
  416. .army_info_skills [id^="skill_name"] {
  417. color: #bbb;
  418. transition: none !important;
  419. }
  420. .army_info_skills [id^="skill_name"]:hover {
  421. color: #c9b087;
  422. }
  423. #easyTooltip {
  424. width: auto;
  425. min-width: auto;
  426. max-width: 320px;
  427. font-size: 0.95em;
  428. padding: 0.9em;
  429. color: #ddd;
  430. border-color: #bbb;
  431. background-color: #1c1c1c;
  432. background-image: none;
  433. text-align: justify;
  434. opacity: 1 !important;
  435. } /* leader_army */
  436. #army_info_div .bookmark {
  437. background-color: #736e6c;
  438. border-color: inherit;
  439. }
  440. #army_info_div .bookmark:hover {
  441. background-color: #a7a7a7;
  442. }
  443. #army_info_div .selected_bookmark {
  444. background-color: #3a3a3a;
  445. }
  446. #bookmark-1 > span,
  447. #army_info_div .info_header_leadershipAmount {
  448. color: inherit;
  449. }
  450. #army_info_div .amount {
  451. color: #d6b47d;
  452. }
  453. #upper_block .content_separator {
  454. background: #555;
  455. } /* skillwheel */
  456. #skills_table .area_wheelInfoPanels {
  457. background-image: none;
  458. background: url("https://dcdn3.heroeswm.ru/i/combat/corner4_lt.png") no-repeat top left, url("https://dcdn3.heroeswm.ru/i/combat/corner4_rt.png") no-repeat top right,
  459. url("https://dcdn3.heroeswm.ru/i/combat/corner4_lb.png") no-repeat bottom left, url("https://dcdn3.heroeswm.ru/i/combat/corner4_rb.png") no-repeat bottom right,
  460. url("https://dcdn3.heroeswm.ru/i/combat/winChatDesktop_border_t.png") top left repeat-x, url("https://dcdn3.heroeswm.ru/i/combat/winChatDesktop_border_b.png") bottom left repeat-x,
  461. url("https://dcdn3.heroeswm.ru/i/combat/winChatDesktop_border_l.png") top left repeat-y, url("https://dcdn3.heroeswm.ru/i/combat/winChatDesktop_border_r.png") top right repeat-y;
  462. background-size: 20px, 20px, 20px, 20px, auto, auto, auto, auto, auto;
  463. background-color: #353535;
  464. outline: 1px solid gray;
  465. }
  466. #skills_table .info_head3Wheel {
  467. color: #cca568;
  468. }
  469. #skills_table .wheel_abilitiesList {
  470. color: #e0c497;
  471. }
  472. #skills_table .info_head3_2Wheel {
  473. color: #888;
  474. }
  475. #skill_cur_cost {
  476. color: inherit;
  477. }
  478. #win_Loader {
  479. -webkit-filter: invert(0.9) sepia(0.7);
  480. filter: invert(0.9) sepia(0.7);
  481. } /* arts_for_monsters */
  482. [data-page="arts_for_monsters"] i {
  483. color: #caa472;
  484. } /* sms */
  485. img[src$="sms_flag.gif"] {
  486. -webkit-filter: invert(0.9) sepia(1) grayscale(1);
  487. filter: invert(0.9) sepia(1) grayscale(1);
  488. }
  489. [data-page="sms"] td.wbwhite b {
  490. color: inherit !important;
  491. }
  492. [data-page^="sms_"] td.wbcapt {
  493. color: #ccc;
  494. background-color: #444;
  495. }
  496. [data-page^="sms"] a[href] > font[color="#5ACE5A"] > b {
  497. color: #5ace5a !important;
  498. }
  499. [data-page="sms"] a[href="sms.php?filter=new"],
  500. [data-page="sms_clans"] td[align] > a[href^="/sms_"] {
  501. text-decoration: none;
  502. }
  503. [data-page="sms"] [name="data"] {
  504. color: #ccc;
  505. background-color: #1d1d1d;
  506. } /* sms_clans */
  507. [data-page="sms_clans"] td.wbcapt > b {
  508. color: inherit !important;
  509. } /* tour_hist */
  510. [data-page$="_hist"] [style^="BACKGROUND"] {
  511. background-color: #333 !important;
  512. }
  513. [data-page$="_hist"] [style^="BACKGROUND-COLOR: #d3d1c6"],
  514. [data-page$="_hist"] [style^="BACKGROUND-COLOR: #F5F3EA"] {
  515. background-color: #444 !important;
  516. }
  517. img[src$="/mtp1.jpg"],
  518. img[src$="/mtp2.jpg"],
  519. img[src$="/mtp3.jpg"] {
  520. -webkit-filter: invert(0.9) sepia(0.5);
  521. filter: invert(0.9) sepia(0.5);
  522. } /* donate */
  523. [data-page^="hwm_donate"] div[style*="color: #000000"] {
  524. color: inherit !important;
  525. }
  526. [data-page^="hwm_donate"] .pay-sys {
  527. background-color: #353535;
  528. } /* home */
  529. [data-page="home"] table[width="90%"] b {
  530. color: #d0bda6;
  531. }
  532. [data-page="home"] table[width="90%"] font[color="black"] {
  533. color: #bbb;
  534. } /* script: hwm_time_restore */
  535. #main_top_table [src$="/dragon__left.jpg"] + div {
  536. z-index: 2;
  537. }
  538. #main_top_table .hwm_tb * {
  539. color: tan;
  540. }
  541. #main_top_table .hwm_tb span {
  542. color: #59a7ad !important;
  543. }
  544. #main_top_table .hwm_tb span[style$="rgb(255, 0, 0);"] {
  545. color: #ff9800 !important;
  546. }
  547. #main_top_table .hwm_tb img {
  548. -webkit-filter: none;
  549. filter: none;
  550. }
  551. #main_top_table .hwm_tb td[width="5"] > img {
  552. visibility: visible;
  553. }
  554. #main_top_table .hwm_tb a:hover {
  555. color: #ccc !important;
  556. }
  557. #bgCenter {
  558. background-color: #333 !important;
  559. } /* script: SetsMaster */
  560. #main_top_table div[id^="menuSetsTab"] {
  561. color: tan !important;
  562. border-color: tan;
  563. }
  564. #main_top_table div[id^="menuSetsTab"] * {
  565. color: inherit !important;
  566. }
  567. #main_top_table div[id^="menuSetsTab"] li:hover {
  568. color: #ccc !important;
  569. }
  570. #main_top_table div[id^="menuSetsTab"] b[style$="rgb(0, 255, 0);"] {
  571. color: #76c5cc !important;
  572. }
  573. [data-page="army"] center:nth-of-type(2) table {
  574. background-color: #555;
  575. border: 1px solid;
  576. border-collapse: initial !important;
  577. } /* ========================= */ /* inventory */
  578. [data-page="inventory"] .art_durability_hidden {
  579. display: block !important;
  580. opacity: 1 !important;
  581. }
  582. [data-page="inventory"] .hwm_hint_css {
  583. color: #222;
  584. background: #eee;
  585. border: 2px solid #888 !important;
  586. z-index: 100;
  587. }
  588. :root .container_block {
  589. color: #eee;
  590. background-color: #333;
  591. box-shadow: inset 0 0 0 1px #c2b4a3;
  592. }
  593. :root .filter_tab {
  594. background-color: #fff;
  595. -webkit-filter: invert(0.9) grayscale(0.6);
  596. filter: invert(0.9) grayscale(0.6);
  597. }
  598. :root .filter_tab_active {
  599. background-color: #ddd;
  600. }
  601. :root .inv_scroll_content {
  602. color: #eee;
  603. background-color: #222;
  604. border: 1px solid;
  605. }
  606. :root .inv_scroll_content_expand_sign {
  607. -webkit-filter: invert(0.9);
  608. filter: invert(0.9);
  609. }
  610. :root .inv_note_kukla {
  611. background-color: transparent;
  612. box-shadow: none;
  613. }
  614. :root #inv_expandedBlock {
  615. margin-top: 0.4em;
  616. }
  617. :root .btn_standard:not(.btn_disabled) {
  618. color: #222;
  619. background-color: #ddd;
  620. text-shadow: none;
  621. }
  622. :root .btn_on_edit {
  623. background-color: #fff !important;
  624. }
  625. :root #inv_menu {
  626. padding: 0.4em;
  627. background-color: rgba(225, 225, 225, 0.9);
  628. z-index: 10;
  629. }
  630. :root #inv_menu,
  631. :root .inv_item_info font {
  632. color: #222;
  633. }
  634. :root .inv_item_select_img[cat] {
  635. -webkit-filter: invert(0.8) grayscale(0.6);
  636. filter: invert(0.8) grayscale(0.6);
  637. }
  638. :root #inv_menu a,
  639. :root #inv_menu a > * {
  640. color: #ae5650;
  641. }
  642. :root .inventory_item_div_wide {
  643. background-color: #444;
  644. }
  645. .inventory_item_in_rent ~ div .cre_mon_image2 {
  646. background-color: rgba(113, 196, 223, 0.3);
  647. }
  648. .inventory_item_broken ~ div .cre_mon_image2 {
  649. background-color: rgb(255, 17, 0, 0.3);
  650. }
  651. .s_art {
  652. background-color: #88887e;
  653. }
  654. .global_container_block {
  655. background-color: #666663;
  656. }
  657. .map_obj_table_div_gray {
  658. background-color: #201c1c !important;
  659. }
  660. .global_container_block_header {
  661. background-color: #201f1e;
  662. }
  663. .map_obj_head {
  664. background-color: #5b5954 !important;
  665. }
  666. .global_table_div table tbody tr:nth-of-type(2n+1) {
  667. background-color: #201c1c;
  668. }
  669. .global_table_div table tbody tr:nth-of-type(2n) {
  670. background-color: #201c1c;
  671. }
  672. .hwm_recruit_ramka {
  673. background-color: #6f6e6a !important;
  674. }
  675. </style>`);
  676. const coloredHeaderStyle = parseNode(`<style>
  677. #main_top_table b,
  678. #main_top_table table.hwm_tb * {
  679. color: #ffd875;
  680. }
  681. #main_top_table div[id^="menuSetsTab"] {
  682. color: #ffd875 !important;
  683. }
  684. #main_top_table td[width="88"] {
  685. border-width: 0 !important;
  686. }
  687. #main_top_table td[height="17"] {
  688. color: #ccc;
  689. }
  690. #main_top_table img,
  691. #main_top_table td {
  692. -webkit-filter: none !important;
  693. filter: none !important;
  694. }
  695. #main_top_table img[src$="_topll_80.jpg"],
  696. #main_top_table img[src$="_topr2_80.jpg"] {
  697. content: url("https://i.ibb.co/frf905t/res-line-topll-80.png");
  698. }
  699. #main_top_table img[src$="_top0.jpg"],
  700. #main_top_table img[src$="_toprr.jpg"] {
  701. content: url("https://i.ibb.co/T8pgh0r/res-line-top0.png");
  702. }
  703. #main_top_table img[src$="logot.jpg"] {
  704. content: url("https://i.ibb.co/nsWmc8k/logot.png");
  705. }
  706. #main_top_table td[style$="/right_big.jpg);"] {
  707. background-image: url("https://i.ibb.co/9hK2xrd/right-big.png") !important;
  708. }
  709. #main_top_table td[style*="/lbkg.jpg"] {
  710. background-image: url("https://i.ibb.co/b5q3Dwj/lbkg.png") !important;
  711. }
  712. #main_top_table img[src*="dragon"] {
  713. content: url("https://i.ibb.co/wgLHkFj/dragon-left.png");
  714. }
  715. #main_top_table img[src$="/left_big0_56.jpg"] {
  716. content: url("https://i.ibb.co/y69yYWQ/left-big0-56.png");
  717. }
  718. #main_top_table img[src$="/left_big2_92.jpg"] {
  719. content: url("https://i.ibb.co/xm7g9sD/left-big2-92.png");
  720. }
  721. #main_top_table img[src$="dec_88.jpg"] {
  722. content: url("https://i.ibb.co/gVJb89v/ldec-88.png");
  723. }
  724. #main_top_table img[src$="part.jpg"] {
  725. content: url("https://i.ibb.co/p4zM1ym/lpart.png");
  726. }
  727. #main_top_table img[src$="32_39.jpg"] {
  728. content: url("https://i.ibb.co/sgTGdSb/h-top-32-39.png");
  729. }
  730. #main_top_table img[src$="32_10.jpg"] {
  731. content: url("https://i.ibb.co/GdGQsWm/h-top-32-10.png");
  732. }
  733. #main_top_table img[src*="_bot"][src$="_80.jpg"] {
  734. content: url("https://i.ibb.co/mFwH3rS/res-line-botl-80.jpg");
  735. }
  736. #main_top_table img[src$="t_end.jpg"] {
  737. content: url("https://i.ibb.co/n650yBY/t-end.png");
  738. }
  739. #main_top_table img[src$="_bot0.jpg"],
  740. #main_top_table img[src$="_botrr.jpg"] {
  741. content: url("https://i.ibb.co/Dfdj0gZ/res-line-bot0.png");
  742. }
  743. #main_top_table td[style$="/bkgtop.jpg);"] {
  744. position: relative;
  745. background-image: url("https://i.ibb.co/rc0qfLf/res-line-topc.png") !important;
  746. }
  747. #main_top_table td[style$="/bkgtop.jpg);"]:before {
  748. content: "";
  749. width: 100%;
  750. height: 2px;
  751. position: absolute;
  752. background-color: #222;
  753. }
  754. #main_top_table img[src$="topr2_80.jpg"],
  755. #main_top_table img[src$="botr_80.jpg"],
  756. #main_top_table img[src$="rdec_88.jpg"],
  757. #main_top_table img[src$="rpart.jpg"],
  758. #main_top_table img[src$="line_32_39.jpg"],
  759. #main_top_table img[src$="right_36.jpg"] {
  760. -o-transform: scaleX(-1);
  761. -moz-transform: scaleX(-1);
  762. -webkit-transform: scaleX(-1);
  763. transform: scaleX(-1);
  764. }
  765. </style>`);
  766.  
  767. main();
  768. function main() {
  769. addStyle(":root {overflow-y: auto;} :root > body {overflow-y: visible;}");
  770. addStyle(`#night_mode_switcher {width: 22px; height: 22px; position: fixed; right: 10px; bottom: 10px; margin: 0; padding: 0; color: transparent; outline: none; border: 1px solid #888; border-radius: 50%; background: url("https://i.ibb.co/dJCMwGN/switcher.png") center /contain;background-color: #333;cursor: pointer;z-index: 9999;opacity: .9;transition: transform .3s;}#night_mode_switcher:hover {opacity: 1;}[data-page="frames"] #night_mode_switcher {display: none;}`);
  771. document.documentElement.setAttribute('data-page', location.pathname.slice(1).replace(/\.(php|html)$/, ''));
  772.  
  773. const switcher = addElement("button", { id: "night_mode_switcher" }, document.body);
  774. switcher.hidden = getPlayerBool("nightModeSwitcherHidden");
  775. switcher.addEventListener("click", function() { setPlayerValue("nightMode", !getPlayerBool("nightMode")); applyNightMode(); });
  776.  
  777. applyNightMode();
  778. drawSettings();
  779. }
  780. function applyNightMode() {
  781. const nightMode = getPlayerBool("nightMode");
  782. document.getElementById("night_mode_switcher").title = isEn ? (nightMode ? "Disable night mode" : "Enable night mode") : (nightMode ? "Выключить ночную тему" : "Включить ночную тему");
  783. if(nightMode) {
  784. document.head.appendChild(nightStyle);
  785. if(getPlayerBool("coloredHeader")) {
  786. document.head.appendChild(coloredHeaderStyle);
  787. }
  788. } else {
  789. nightStyle.remove();
  790. if(getPlayerBool("coloredHeader")) {
  791. coloredHeaderStyle.remove();
  792. }
  793. }
  794. }
  795. function drawSettings() {
  796. if(location.pathname == '/pers_settings.php') {
  797. const search = document.querySelector('td.wbwhite[colspan="2"]').parentNode;
  798. search.insertAdjacentHTML("beforebegin", `
  799. <tr>
  800. <td class=wblight colspan=2>
  801. &nbsp;<b>${isEn ? "Night mode settings" : "Ночная тема: настройки"}</b>
  802. </td>
  803. </tr>
  804. <tr hidden="hidden">
  805. <td class=wbwhite style="width: 35%;">
  806. &nbsp;${isEn ? "Colored cap" : "Цветная шапка"}
  807. </td>
  808. <td class=wbwhite align=left>
  809. &nbsp;<input id=coloredHeaderCheckbox type=checkbox />
  810. </td>
  811. </tr>
  812. <tr>
  813. <td class=wbwhite style="width: 35%;">
  814. &nbsp;${isEn ? 'Hide switcher' : 'Скрывать кнопку-переключатель'}
  815. </td>
  816. <td class=wbwhite align=left>
  817. &nbsp;<input id=btnHiddenCheckbox type=checkbox />
  818. </td>
  819. </tr>`);
  820. document.getElementById("coloredHeaderCheckbox").checked = getPlayerBool("coloredHeader");
  821. document.getElementById("coloredHeaderCheckbox").addEventListener("change", function() { setPlayerValue("coloredHeader", this.checked); this.checked ? document.head.appendChild(coloredHeaderStyle) : coloredHeaderStyle.remove(); });
  822. document.getElementById("btnHiddenCheckbox").checked = getPlayerBool("nightModeSwitcherHidden");
  823. document.getElementById("btnHiddenCheckbox").addEventListener("change", function() { setPlayerValue("nightModeSwitcherHidden", this.checked); switcher.hidden = this.checked; });
  824. }
  825. }
  826. function parseNode(html) {
  827. const div = addElement('div', { innerHTML: html });
  828. return div.firstChild.cloneNode(true);
  829. }
  830. // Array and object
  831. function groupBy(list, keyFieldOrSelector) { return list.reduce(function(t, item) { const keyValue = typeof keyFieldOrSelector === 'function' ? keyFieldOrSelector(item) : item[keyFieldOrSelector]; (t[keyValue] = t[keyValue] || []).push(item); return t; }, {}); };
  832. function getKeyByValue(object, value) { return Object.keys(object).find(key => object[key] === value); }
  833. function findKey(obj, selector) { return Object.keys(obj).find(selector); }
  834. function pushNew(array, newValue) { if(array.indexOf(newValue) == -1) { array.push(newValue); } }
  835. function sortBy(field, reverse, evaluator) {
  836. const key = evaluator ? function(x) { return evaluator(x[field]); } : function(x) { return x[field]; };
  837. return function(a, b) { return a = key(a), b = key(b), (reverse ? -1 : 1) * ((a > b) - (b > a)); }
  838. }
  839. // HttpRequests
  840. function getRequest(url, overrideMimeType = "text/html; charset=windows-1251") {
  841. return new Promise((resolve, reject) => {
  842. GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
  843. onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); },
  844. onerror: function(error) { reject(error); }
  845. });
  846. });
  847. }
  848. function getRequestText(url, overrideMimeType = "text/html; charset=windows-1251") {
  849. return new Promise((resolve, reject) => {
  850. GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
  851. onload: function(response) { resolve(response.responseText); },
  852. onerror: function(error) { reject(error); }
  853. });
  854. });
  855. }
  856. function postRequest(url, data) {
  857. return new Promise((resolve, reject) => {
  858. GM.xmlHttpRequest({ method: "POST", url: url, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: data,
  859. onload: function(response) { resolve(response); },
  860. onerror: function(error) { reject(error); }
  861. });
  862. });
  863. }
  864. function fetch({ url, method = 'GET', type = 'document', body = null }) {
  865. return new Promise((resolve, reject) => {
  866. const xhr = new XMLHttpRequest();
  867. xhr.open(method, url);
  868. xhr.responseType = type;
  869.  
  870. xhr.onload = () => {
  871. if (xhr.status === 200) return resolve(xhr.response);
  872. throwError(`Error with status ${xhr.status}`);
  873. };
  874.  
  875. xhr.onerror = () => throwError(`HTTP error with status ${xhr.status}`);
  876.  
  877. xhr.send(body);
  878.  
  879. function throwError(msg) {
  880. const err = new Error(msg);
  881. err.status = xhr.status;
  882. reject(err);
  883. }
  884. });
  885. }
  886. // Storage
  887. function getValue(key, defaultValue) { return GM_getValue(key, defaultValue); };
  888. function setValue(key, value) { GM_setValue(key, value); };
  889. function deleteValue(key) { return GM_deleteValue(key); };
  890. function getPlayerValue(key, defaultValue) { return getValue(`${key}${PlayerId}`, defaultValue); };
  891. function setPlayerValue(key, value) { setValue(`${key}${PlayerId}`, value); };
  892. function deletePlayerValue(key) { return deleteValue(`${key}${PlayerId}`); };
  893. function getPlayerBool(valueName, defaultValue = false) { return getBool(valueName + PlayerId, defaultValue); }
  894. function getBool(valueName, defaultValue = false) {
  895. const value = getValue(valueName);
  896. //console.log(`valueName: ${valueName}, value: ${value}, ${typeof(value)}`)
  897. if(value != undefined) {
  898. if(typeof(value) == "string") {
  899. return value == "true";
  900. }
  901. if(typeof(value) == "boolean") {
  902. return value;
  903. }
  904. }
  905. return defaultValue;
  906. }
  907. function setOrDeleteNumberValue(key, value) {
  908. if(!value || value == "" || isNaN(Number(value))) {
  909. deleteValue(key);
  910. } else {
  911. setValue(key, value);
  912. }
  913. }
  914. function setOrDeleteNumberPlayerValue(key, value) { setOrDeleteNumberValue(key + PlayerId, value); }
  915. function getStorageKeys(filter) { return listValues().filter(filter); }
  916. // Html DOM
  917. function addElement(type, data = {}, parent = undefined, insertPosition = "beforeend") {
  918. const el = document.createElement(type);
  919. for(const key in data) {
  920. if(key == "innerText" || key == "innerHTML") {
  921. el[key] = data[key];
  922. } else {
  923. el.setAttribute(key, data[key]);
  924. }
  925. }
  926. if(parent) {
  927. if(parent.insertAdjacentElement) {
  928. parent.insertAdjacentElement(insertPosition, el);
  929. } else if(parent.parentNode) {
  930. switch(insertPosition) {
  931. case "beforebegin":
  932. parent.parentNode.insertBefore(el, parent);
  933. break;
  934. case "afterend":
  935. parent.parentNode.insertBefore(el, parent.nextSibling);
  936. break;
  937. }
  938. }
  939. }
  940. return el;
  941. }
  942. function addStyle(css) { addElement("style", { type: "text/css", innerHTML: css }, document.head); }
  943. function getParent(element, parentType, number = 1) {
  944. if(!element) {
  945. return;
  946. }
  947. let result = element;
  948. let foundNumber = 0;
  949. while(result = result.parentNode) {
  950. if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
  951. foundNumber++;
  952. if(foundNumber == number) {
  953. return result;
  954. }
  955. }
  956. }
  957. }
  958. function getNearestAncestorSibling(node) {
  959. let parentNode = node;
  960. while((parentNode = parentNode.parentNode)) {
  961. if(parentNode.nextSibling) {
  962. return parentNode.nextSibling;
  963. }
  964. }
  965. }
  966. function getNearestAncestorElementSibling(node) {
  967. let parentNode = node;
  968. while((parentNode = parentNode.parentNode)) {
  969. if(parentNode.nextElementSibling) {
  970. return parentNode.nextElementSibling;
  971. }
  972. }
  973. }
  974. function nextSequential(node) { return node.firstChild || node.nextSibling || getNearestAncestorSibling(node); }
  975. function nextSequentialElement(element) { return element.firstElementChild || element.nextElementSibling || getNearestAncestorElementSibling(element); }
  976. function getSequentialsUntil(firstElement, lastElementTagName) {
  977. let currentElement = firstElement;
  978. const resultElements = [currentElement];
  979. while((currentElement = nextSequential(currentElement)) && currentElement.nodeName.toLowerCase() != lastElementTagName.toLowerCase()) {
  980. resultElements.push(currentElement);
  981. }
  982. if(currentElement) {
  983. resultElements.push(currentElement);
  984. }
  985. return resultElements;
  986. }
  987. function findChildrenTextContainsValue(selector, value) { return Array.from(document.querySelectorAll(selector)).reduce((t, x) => { const match = Array.from(x.childNodes).filter(y => y.nodeName == "#text" && y.textContent.includes(value)); return [...t, ...match]; }, []); }
  988. // Popup panel
  989. function createPupupPanel(panelName, panelTitle, fieldsMap, panelToggleHandler) {
  990. const backgroundPopupPanel = addElement("div", { id: panelName, style: "position: fixed; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); z-index: 200;" }, document.body);
  991. backgroundPopupPanel.addEventListener("click", function(e) { if(e.target == this) { hidePupupPanel(panelName, panelToggleHandler); }});
  992. const topStyle = isMobileDevice ? "" : "top: 50%; transform: translateY(-50%);";
  993. const contentDiv = addElement("div", { style: `${topStyle} padding: 5px; display: flex; flex-wrap: wrap; position: relative; margin: auto; padding: 0; width: fit-content; background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); border: 1mm ridge rgb(211, 220, 50);` }, backgroundPopupPanel);
  994. if(panelTitle) {
  995. addElement("b", { innerHTML: panelTitle, style: "text-align: center; margin: auto; width: 90%; display: block;" }, contentDiv);
  996. }
  997. const divClose = addElement("span", { id: panelName + "close", title: isEn ? "Close" : "Закрыть", innerHTML: "&times;", style: "cursor: pointer; font-size: 20px; font-weight: bold;" }, contentDiv);
  998. divClose.addEventListener("click", function() { hidePupupPanel(panelName, panelToggleHandler); });
  999.  
  1000. addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
  1001.  
  1002. if(fieldsMap) {
  1003. let contentTable = addElement("table", { style: "flex-basis: 100%; width: min-content;"}, contentDiv);
  1004. for(const rowData of fieldsMap) {
  1005. if(rowData.length == 0) { // Спомощью передачи пустой стороки-массива, указываем, что надо начать новую таблицу после брейка
  1006. addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
  1007. contentTable = addElement("table", undefined, contentDiv);
  1008. continue;
  1009. }
  1010. const row = addElement("tr", undefined, contentTable);
  1011. for(const cellData of rowData) {
  1012. const cell = addElement("td", undefined, row);
  1013. if(cellData) {
  1014. if(typeof(cellData) == "string") {
  1015. cell.innerText = cellData;
  1016. } else {
  1017. cell.appendChild(cellData);
  1018. }
  1019. }
  1020. }
  1021. }
  1022. }
  1023. if(panelToggleHandler) {
  1024. panelToggleHandler(true);
  1025. }
  1026. return contentDiv;
  1027. }
  1028. function showPupupPanel(panelName, panelToggleHandler) {
  1029. const backgroundPopupPanel = document.getElementById(panelName);
  1030. if(backgroundPopupPanel) {
  1031. backgroundPopupPanel.style.display = '';
  1032. if(panelToggleHandler) {
  1033. panelToggleHandler(true);
  1034. }
  1035. return true;
  1036. }
  1037. return false;
  1038. }
  1039. function hidePupupPanel(panelName, panelToggleHandler) {
  1040. const backgroundPopupPanel = document.getElementById(panelName);
  1041. backgroundPopupPanel.style.display = 'none';
  1042. if(panelToggleHandler) {
  1043. panelToggleHandler(false);
  1044. }
  1045. }
  1046. // Script autor and url
  1047. function getScriptLastAuthor() {
  1048. let authors = GM_info.script.author;
  1049. if(!authors) {
  1050. const authorsMatch = GM_info.scriptMetaStr.match(/@author(.+)\n/);
  1051. authors = authorsMatch ? authorsMatch[1] : "";
  1052. }
  1053. const authorsArr = authors.split(",").map(x => x.trim()).filter(x => x);
  1054. return authorsArr[authorsArr.length - 1];
  1055. }
  1056. function getDownloadUrl() {
  1057. let result = GM_info.script.downloadURL;
  1058. if(!result) {
  1059. const downloadURLMatch = GM_info.scriptMetaStr.match(/@downloadURL(.+)\n/);
  1060. result = downloadURLMatch ? downloadURLMatch[1] : "";
  1061. result = result.trim();
  1062. }
  1063. return result;
  1064. }
  1065. function getScriptReferenceHtml() { return `<a href="${getDownloadUrl()}" title="${isEn ? "Check for update" : "Проверить обновление скрипта"}" target=_blanc>${GM_info.script.name} ${GM_info.script.version}</a>`; }
  1066. function getSendErrorMailReferenceHtml() { return `<a href="sms-create.php?mailto=${getScriptLastAuthor()}&subject=${isEn ? "Error in" : "Ошибка в"} ${GM_info.script.name} ${GM_info.script.version} (${GM_info.scriptHandler} ${GM_info.version})" target=_blanc>${isEn ? "Bug report" : "Сообщить об ошибке"}</a>`; }
  1067. // Server time
  1068. function getServerTime() { return Date.now() - parseInt(getValue("ClientServerTimeDifference", 0)); }
  1069. function getGameDate() { return new Date(getServerTime() + 10800000); } // Игра в интерфейсе всегда показывает московское время // Это та дата, которая в toUTCString покажет время по москве
  1070. function toServerTime(clientTime) { return clientTime - parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
  1071. function toClientTime(serverTime) { return serverTime + parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
  1072. function truncToFiveMinutes(time) { return Math.floor(time / 300000) * 300000; }
  1073. function today() { const now = new Date(getServerTime()); now.setHours(0, 0, 0, 0); return now; }
  1074. function tomorrow() { const today1 = today(); today1.setDate(today1.getDate() + 1); return today1; }
  1075. async function requestServerTime() {
  1076. if(parseInt(getValue("LastClientServerTimeDifferenceRequestDate", 0)) + 6 * 60 * 60 * 1000 < Date.now()) {
  1077. setValue("LastClientServerTimeDifferenceRequestDate", Date.now());
  1078. const responseText = await getRequestText("/time.php");
  1079. const responseParcing = /now (\d+)/.exec(responseText); //responseText: now 1681711364 17-04-23 09:02
  1080. if(responseParcing) {
  1081. setValue("ClientServerTimeDifference", Date.now() - parseInt(responseParcing[1]) * 1000);
  1082. }
  1083. } else {
  1084. setTimeout(requestServerTime, 60 * 60 * 1000);
  1085. }
  1086. }
  1087. // dateString - игровое время, взятое со страниц игры. Оно всегда московское // Как результат возвращаем серверную дату
  1088. function parseDate(dateString, isFuture = false, isPast = false) {
  1089. //console.log(dateString)
  1090. if(!dateString) {
  1091. return;
  1092. }
  1093. const dateStrings = dateString.split(" ");
  1094.  
  1095. let hours = 0;
  1096. let minutes = 0;
  1097. let seconds = 0;
  1098. const gameDate = getGameDate();
  1099. let year = gameDate.getUTCFullYear();
  1100. let month = gameDate.getUTCMonth();
  1101. let day = gameDate.getUTCDate();
  1102. const timePart = dateStrings.find(x => x.includes(":"));
  1103. if(timePart) {
  1104. var time = timePart.split(":");
  1105. hours = parseInt(time[0]);
  1106. minutes = parseInt(time[1]);
  1107. if(time.length > 2) {
  1108. seconds = parseInt(time[2]);
  1109. }
  1110. if(dateStrings.length == 1) {
  1111. let result = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
  1112. if(isPast && result > gameDate) {
  1113. result.setUTCDate(result.getUTCDate() - 1);
  1114. }
  1115. if(isFuture && result < gameDate) {
  1116. result.setUTCDate(result.getUTCDate() + 1);
  1117. }
  1118. //console.log(`result: ${result}, gameDate: ${gameDate}`)
  1119. result.setUTCHours(result.getUTCHours() - 3);
  1120. return result;
  1121. }
  1122. }
  1123.  
  1124. const datePart = dateStrings.find(x => x.includes("-"));
  1125. if(datePart) {
  1126. const date = datePart.split("-");
  1127. month = parseInt(date[isEn ? (date.length == 3 ? 1 : 0) : 1]) - 1;
  1128. day = parseInt(date[isEn ? (date.length == 3 ? 2 : 1) : 0]);
  1129. if(date.length == 3) {
  1130. const yearText = isEn ? date[0] : date[2];
  1131. year = parseInt(yearText);
  1132. if(yearText.length < 4) {
  1133. year += Math.floor(gameDate.getUTCFullYear() / 1000) * 1000;
  1134. }
  1135. } else {
  1136. if(isFuture && month == 0 && gameDate.getUTCMonth() == 11) {
  1137. year += 1;
  1138. }
  1139. }
  1140. }
  1141. if(dateStrings.length > 2) {
  1142. const letterDateExec = /(\d{2}):(\d{2}) (\d{2}) (.{3,4})/.exec(dateString);
  1143. if(letterDateExec) {
  1144. //console.log(letterDateExec)
  1145. day = parseInt(letterDateExec[3]);
  1146. //const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
  1147. const monthShortNames = ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сент', 'окт', 'ноя', 'дек'];
  1148. month = monthShortNames.findIndex(x => x.toLowerCase() == letterDateExec[4].toLowerCase());
  1149. if(isPast && Date.UTC(year, month, day, hours, minutes, seconds) > gameDate.getTime()) {
  1150. year -= 1;
  1151. }
  1152. }
  1153. }
  1154. //console.log(`year: ${year}, month: ${month}, day: ${day}, time[0]: ${time[0]}, time[1]: ${time[1]}, ${new Date(year, month, day, parseInt(time[0]), parseInt(time[1]))}`);
  1155. let result = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
  1156. result.setUTCHours(result.getUTCHours() - 3);
  1157. return result;
  1158. }
  1159. // Misc
  1160. async function initUserName() {
  1161. if(location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) {
  1162. //console.log(document.querySelector("h1").innerText)
  1163. setPlayerValue("UserName", document.querySelector("h1").innerText);
  1164. }
  1165. if(location.pathname == "/home.php") {
  1166. //console.log(document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText)
  1167. setPlayerValue("UserName", document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText);
  1168. }
  1169. if(!getPlayerValue("UserName")) {
  1170. const doc = await getRequest(`/pl_info.php?id=${PlayerId}`);
  1171. setPlayerValue("UserName", doc.querySelector("h1").innerText);
  1172. }
  1173. }
  1174. function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
  1175. function showBigData(data) { console.log(data); /*addElement("TEXTAREA", { innerText: data }, document.body);*/ }
  1176. function round0(value) { return Math.round(value * 10) / 10; }
  1177. function round00(value) { return Math.round(value * 100) / 100; }
  1178. function mobileCheck() {
  1179. let check = false;
  1180. (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  1181. return check;
  1182. };
  1183. // MutationObserver
  1184. function observe(targets, handler, config = { childList: true, subtree: true }) {
  1185. targets = Array.isArray(targets) ? targets : [targets];
  1186. targets = targets.map(x => { if(typeof x === 'function') { return x(document); } return x; }); // Можем передавать не элементы, а их селекторы
  1187. const ob = new MutationObserver(async function(mut, observer) {
  1188. //console.log(`Mutation start`);
  1189. observer.disconnect();
  1190. if(handler.constructor.name === 'AsyncFunction') {
  1191. await handler();
  1192. } else {
  1193. handler();
  1194. }
  1195. for(const target of targets) {
  1196. if(target) {
  1197. observer.observe(target, config);
  1198. }
  1199. }
  1200. });
  1201. for(const target of targets) {
  1202. if(target) {
  1203. ob.observe(target, config);
  1204. }
  1205. }
  1206. }
  1207. // UpdatePanels
  1208. // Если используется url, то это должна быть та же локация с другими параметрами
  1209. async function refreshUpdatePanels(panelSelectors, postProcessor, url = location.href) {
  1210. panelSelectors = Array.isArray(panelSelectors) ? panelSelectors : [panelSelectors];
  1211. let freshDocument;
  1212. for(const panelSelector of panelSelectors) {
  1213. const updatePanel = panelSelector(document);
  1214. //console.log(panelSelector.toString())
  1215. //console.log(updatePanel)
  1216. if(updatePanel) {
  1217. freshDocument = freshDocument || await getRequest(url);
  1218. const freshUpdatePanel = panelSelector(freshDocument);
  1219. if(!freshUpdatePanel) {
  1220. console.log(updatePanel)
  1221. continue;
  1222. }
  1223. if(postProcessor) {
  1224. postProcessor(freshUpdatePanel);
  1225. }
  1226. updatePanel.innerHTML = freshUpdatePanel.innerHTML;
  1227. Array.from(updatePanel.querySelectorAll("script")).forEach(x => {
  1228. x.insertAdjacentElement("afterend", addElement("script", { innerHTML: x.innerHTML })); // Передобавляем скрипты, как элементы, что они сработали
  1229. x.remove();
  1230. });
  1231. }
  1232. }
  1233. if(typeof win.hwm_hints_init === 'function') win.hwm_hints_init();
  1234. return freshDocument;
  1235. }