hwmTroopsDeploymentHelper

Помощник в расстановке войск

当前为 2024-02-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name hwmTroopsDeploymentHelper
  3. // @namespace Tamozhnya1
  4. // @author Tamozhnya1
  5. // @description Помощник в расстановке войск
  6. // @version 1.3
  7. // @include *heroeswm.ru/war.php*
  8. // @include *lordswm.com/war.php*
  9. // @grant GM_deleteValue
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM.xmlHttpRequest
  13. // @grant GM.notification
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
  18. if(!playerIdMatch) {
  19. return;
  20. }
  21. const PlayerId = playerIdMatch[1];
  22. const battleTypes = { _NABEG: 2, _GN_OTRYAD: 5, _GN_MONSTER: 7, _GN_NABEGI: 8, _GN_ZASHITA: 10, _GN_ARMY: 12, _MAL_TOUR: 14, _THIEF_WAR: 16, _SURVIVAL: 20, _NEWGROUP: 21, _ELEMENTALS: 22, _GNOMES: 23, _NEWKZS: 24, NEWKZS: 24, _NEWKZS_T: 25, NEWKZS_T: 25, _NEWTHIEF: 26, _NEWCARAVAN: 27, _NEWGNCARAVAN: 29, _SURVIVALGN: 28, _TUNNEL: 30, _SEA: 32, _HELL: 33, _CASTLEWALLS: 35, _UNIWAR: 36, _DIFFTUR: 37, _UNIWARCARAVAN: 38, _PVPGUILDTEST: 39, _PVPGUILD: 40, _BALANCED_EVENT: 41, _NECR_EVENT: 42, _NECR_EVENT2: 43, _HELLOWEEN: 44, _SURVIVAL_GNOM: 45, _DEMON_EVENT: 46, _DEMON_EVENT2: 47, _DEMON_EVENT3: 48, _DEMON_EVENT4: 49, _PVEDUEL: 50, _DEMONVALENTIN: 51, _QUICKTOUR: 52, _BARBTE_ATTACK: 53, _BARBTE_DEEP: 54, _BARBTE_BOSS: 55, _TRANSEVENT: 56, _STEPEVENT: 57, _STEPEVENT2: 58, _KZS_PVE: 59, _2TUR: 60, _RANGER: 61, _PRAET: 62, _RANGER_TEST: 63, _SUN_EVENT1: 64, _SUN_EVENT2: 65, _NEWCARAVAN2: 66, _23ATTACK: 67, _2TU_FAST: 68, _SV_ATTACK: 69, _KILLER_BOT: 70, _SV_DUEL: 71, _SV_WAR: 72, _FAST_TEST: 73, _TRUE_EVENT: 74, _TIKVA_BOT: 75, _TIKVA_ATTACK: 76, _ELKA_DEFENSE: 77, _PPE_EVENT: 78, _ALTNECR_EVENT: 79,
  23. _CLAN_SUR_DEF: 80, _CLAN_SUR_ATT: 81, _QUESTWAR: 82, _BARBNEW_DEEP: 83, _BARBNEW_BOSS: 84, _ELKA_RESCUE: 85, _REGWAR1: 86, _REGWAR2: 87, _CLAN_SUR_CAPT: 88, _CLAN_SUR_DEF_PVP: 89, _TRUE_TOUR: 90, _NOOB_DUEL: 91, _ALTMAG_EVENT: 92, _ALTELF_EVENT: 93, _NEWPORTAL_EVENT: 94, _UNIGUILD: 95, _PIRATE_EVENT: 96, _TOUR_EVENT: 97, _PAST_EVENT: 98, _GOLD_EVENT: 99,
  24. _FAST_TEST2: 100, _OHOTA_EVENT: 101, _BUNT_EVENT: 102, _ZASADA_EVENT: 103, _CLAN_NEW_PVP: 104, _SURV_DEEP: 105, _SURV_DEEP_BOSS: 106, _2AND3_EVENT: 107, _CASTLE_EVENT: 108, _CARAVAN_EVENT: 109, _CAMPAIGN_WAR: 110, _NY2016: 111, _ALTTE_EVENT: 112, _PVP_EVENT: 113, _ALTTE2_EVENT: 114, _PIRATE_NEW_EVENT: 115, _PVP_KR_EVENT: 116, _CATCH_EVENT: 117, _PVP_DIAGONAL_EVENT: 118, _VILLAGE_EVENT: 119, _TRAVEL_EVENT: 120, _CASTLE_BATTLE2X2: 121, _PVP_BOT: 122, _PIRATE_SELF_EVENT: 123, _2ZASADA_EVENT: 124, _NEWCARAVAN3: 125, _ONEDAY_EVENT: 126, _CRE_EVENT: 127, _GL_EVENT: 128, _1ZASADA_EVENT: 129, _NYGL2018_EVENT: 130, _EGYPT_EVENT: 131, _GL_DWARF_EVENT: 132, _NAIM_MAP_EVENT: 133, _2BOT_TUR: 134, _CRE_SPEC: 135, _CRE_INSERT: 136, _CRE_TOUR: 137, _GNOM_EVENT: 138, _MAPHERO_EVENT: 138, _NEWCRE_EVENT: 139, _NEWOHOTA_EVENT: 140, _2SURVIVAL: 141, _ADVENTURE_EVENT: 142, _AMBUSHHERO_EVENT: 143, _FRACTION_EVENT: 144, _PVP_KZS: 145, _REAPING_MAP_EVENT: 147 };
  25.  
  26.  
  27. const lang = document.documentElement.lang || (location.hostname == "www.lordswm.com" ? "en" : "ru");
  28. const isEn = lang == "en";
  29. const windowObject = window.wrappedJSObject || unsafeWindow;
  30. // Типы боёв с постоянным числом партнеров
  31. const staticAmounts = {
  32. [battleTypes._CLAN_SUR_DEF]: 2,
  33. [battleTypes._2BOT_TUR]: 2
  34. };
  35.  
  36. var loadId;
  37. var startId;
  38.  
  39. main();
  40. function main() {
  41. loadId = setInterval(waitForBattleLoad, 200);
  42. }
  43. function waitForBattleLoad() {
  44. if(windowObject.stage[windowObject.war_scr].setted_atb) {
  45. clearInterval(loadId);
  46. console.log(`btype: ${windowObject.btype}`);
  47. const playersPositions = getPlayersPositions();
  48. if(windowObject.warlog == 0) {
  49. createMirrorDeploymentButton();
  50. startId = setInterval(waitForBattleStart, 200);
  51. document.getElementById("confirm_ins_img").addEventListener("click", removeMirrorDeploymentButton, true);
  52. }
  53. }
  54. }
  55. function waitForBattleStart() {
  56. if (windowObject.lastturn > -1) {
  57. clearInterval(startId);
  58. removeMirrorDeploymentButton();
  59. }
  60. }
  61. function removeMirrorDeploymentButton() {
  62. const mirrorDeploymentButton = document.getElementById("mirrorDeploymentButton");
  63. if(mirrorDeploymentButton) {
  64. mirrorDeploymentButton.remove();
  65. }
  66. }
  67. // TODO Подобрать картинку
  68. function createMirrorDeploymentButton() {
  69. document.getElementById('right_button').insertAdjacentHTML("beforeend", `
  70. <div id="mirrorDeploymentButton" class="toolbars_img">
  71. <img src="https://dcdn.heroeswm.ru/i/combat/btn_autoalignment.png?v=6" alt="${isEn ? "Deployment mirror vertical" : "Отразить расстановку по вертикали"}" title="${isEn ? "Deployment mirror vertical" : "Отразить расстановку по вертикали"}" style="filter: sepia(100%) hue-rotate(190deg) saturate(900%);">
  72. </div>`);
  73. document.getElementById("mirrorDeploymentButton").addEventListener("click", mirrorDeployment);
  74. }
  75. function mirrorDeployment() {
  76. const pole = windowObject.stage[windowObject.war_scr]; //stage[war_scr].obj
  77. const poleObj = windowObject.stage[windowObject.war_scr].obj; //console.log(poleObj);
  78. const playerStekIds = Array.from(windowObject.stekid).filter((x, i) => i >= 1 && i <= windowObject.stackcount);
  79. const playerUnits = Object.keys(poleObj).filter(k => !poleObj[k].hero && playerStekIds.includes(poleObj[k].id)).map(k => poleObj[k]);
  80. const minY = playerUnits.reduce((t, x) => Math.min(t, x.y), playerUnits[0].y); // console.log(playerUnits.map(x => x.y))
  81. const friendsCount = getVerticalSegmentsAmount();
  82. const onePlayerFieldWidth = windowObject.defyn / friendsCount; // Ширина пространства для расстановки игрока
  83. let deploymentFieldWidthBegin;
  84. let deploymentFieldWidthEnd;
  85. for(let i = 0; i < friendsCount; i++) {
  86. const leftEdge = 1 + i * onePlayerFieldWidth;
  87. const rightEdge = (i + 1) * onePlayerFieldWidth;
  88. if(leftEdge <= minY && minY <= rightEdge) {
  89. deploymentFieldWidthBegin = leftEdge;
  90. deploymentFieldWidthEnd = rightEdge;
  91. }
  92. }
  93. console.log(`minY: ${minY}, defxn: ${windowObject.defxn}, defyn: ${windowObject.defyn}, deploymentFieldWidthBegin: ${deploymentFieldWidthBegin}, deploymentFieldWidthEnd: ${deploymentFieldWidthEnd}`);
  94. const deployment = playerUnits.map(x => [x.id, x.nownumber, x.x, deploymentFieldWidthBegin + deploymentFieldWidthEnd - x.y - x.big]);
  95. const insStr = deployment.map(x => x.join("#")).join("^") + "^"; console.log(insStr);
  96. pole.useinsertion_cre(insStr); // Расстановка по данным из текстовой строки
  97. }
  98. function getVerticalSegmentsAmount() {
  99. const playersPositions = getPlayersPositions();
  100. const playerPosition = playersPositions.find(x => x.playerId == PlayerId).playerPosition;
  101. const staticAmountByBattleType = staticAmounts[windowObject.btype];
  102. if(staticAmountByBattleType) {
  103. return staticAmountByBattleType;
  104. }
  105. return 1; // Должно возвращать количество отрядов со стороны игрока по вертикали. Предполагается, что каждому отряду выделяется одинаковая ширина.
  106. }
  107. function getPlayersPositions() {
  108. //const playersPositions = Object.keys(windowObject).filter(k => k.startsWith("plid")).map(k => ({ playerId: windowObject[k], playerPosition: parseInt(k.slice(4)) }));
  109. const playersPositions = [];
  110. let plidExec;
  111. const plidRe = /plid(\d+)\|(\d+)/g;
  112. while(plidExec = plidRe.exec(document.documentElement.innerHTML)) {
  113. playersPositions.push({ playerId: plidExec[2], playerPosition: parseInt(plidExec[1]) });
  114. }
  115. console.log(playersPositions);
  116. return playersPositions;
  117. }
  118. //defxn: 14, defyn: 20, deploymentFieldWidthBegin: 1, deploymentFieldWidthEnd: 10 //162#77#1#8^167#11#1#6^169#4#1#4^163#68#2#10^165#22#1#10^
  119. // warlog|0|crclink||show_enemy||nb|0|gtype|18|pl_level|21|abilversion|72796|soundstereo|1|soundeff|0|soundvol|100|iscastle|0|stackcount|7|opera|0|imgpath||lshift|3|quality|1|firstbattle|0|hint_arrow|0|soundon|0|
  120. //btype|80|btypeo|80|fastbut|0|fastbut2|0|animspeed|15|
  121. // player|1939235|ruler|0|warid|1424105634|rwi|0|chksum|341|clanid|8433|playero|3|playero2|3|timer|45|
  122. // defxn|14|defyn|20|fb_tutorial|0|width|0|lng|0|lt|-2|no_trees|0|isshadow|1|israstr|0|isblood|1|
  123. // plid1|2945143|plid3|1939235|umka|16BBBEBABBBB002600000C00000038988DEA8D980047000000C00000 |
  124. // insertions|
  125. // 7#4#1#12^3#77#1#15^6#11#1#18^4#32#2#14^5#22#1#17^4#36#2#17^:
  126. // 3#84#1#15^7#4#1#12^6#11#1#18^4#36#2#14^5#23#1#11^4#36#2#17^:
  127. // 3#81#1#12^6#11#1#14^7#4#1#18^4#34#2#11^5#10#1#20^4#33#2#20^5#10#1#11^:
  128. // 4#79#2#12^7#4#1#15^3#84#1#17^6#11#1#13^5#10#1#19^4#1#2#19^5#10#1#11^:
  129. // 7#4#1#13^4#79#2#15^5#20#1#15^6#11#1#16^3#84#1#18^4#1#2#12^:
  130. // 3#81#1#12^6#11#1#15^7#4#1#18^4#31#2#11^5#22#1#20^4#30#2#20^4#1#2#14^:
  131. // 7#4#1#14^6#11#1#16^3#77#1#18^4#78#2#11^5#17#1#13^4#2#2#13^:
  132. // 3#70#1#14^6#11#1#12^4#73#2#18^7#4#1#16^5#22#1#11^:
  133. // 4#40#2#17^6#11#1#15^7#4#1#18^3#84#1#12^5#10#1#20^4#40#2#14^5#10#1#11^:
  134. // 4#79#2#12^7#4#1#15^3#77#1#13^6#11#1#17^5#6#1#19^4#1#2#19^5#11#1#11^:|", "pole", 0, 0, 0, "https://dcdn.heroeswm.ru/i/", 1000, 1000, 1);};