defens finder

testie

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/539479/1607869/defens%20finder.js

  1. Tabs.Defend = {
  2. tabOrder: 1000,
  3. tabLabel: 'Defend',
  4. tabDisabled: false,
  5. myDiv: null,
  6. timer: null,
  7. defendingCities: [],
  8. mapScanInProgress: false,
  9. mapScanX: 0,
  10. mapScanY: 0,
  11. mapScanRadius: 10,
  12. mapScanDelay: 500, // ms between map tile checks
  13. init: function(div) {
  14. var t = Tabs.Defend;
  15. t.myDiv = div;
  16. div.innerHTML = '<DIV class=divHeader align=center>' + tx('Defending Cities Scanner') + '</DIV>' +
  17. '<DIV id=btDefendMain class=btPopMain style="height:100%">' +
  18. '<CENTER><BR><DIV id=btDefendStatus style="min-width:400px;height:20px;font-weight:bold;"></DIV></CENTER>' +
  19. '<DIV id=btDefendOptions>' +
  20. '<TABLE width=100% class=xtab><TR>' +
  21. '<TD><B>Scan Center:</B> X: <INPUT id=btDefendScanX type=text size=3 maxlength=3 value="' + uW.currentcityid.x + '" /> ' +
  22. 'Y: <INPUT id=btDefendScanY type=text size=3 maxlength=3 value="' + uW.currentcityid.y + '" /></TD>' +
  23. '<TD>Radius: <INPUT id=btDefendScanRadius type=text size=2 maxlength=2 value="10" /></TD>' +
  24. '<TD align=right><INPUT id=btDefendScanMap type=button value="Scan Map" /></TD>' +
  25. '</TR></TABLE>' +
  26. '<HR>' +
  27. '<TABLE width=100% class=xtab><TR>' +
  28. '<TD><INPUT id=btDefendShowOwn type=checkbox checked /> Show my cities</TD>' +
  29. '<TD><INPUT id=btDefendShowAlliance type=checkbox checked /> Show alliance cities</TD>' +
  30. '<TD><INPUT id=btDefendShowOthers type=checkbox checked /> Show enemy cities</TD>' +
  31. '</TR></TABLE>' +
  32. '</DIV>' +
  33. '<DIV id=btDefendProgress style="width:100%;height:20px;margin-top:5px;display:none;">' +
  34. '<DIV style="width:100%;height:10px;background-color:#ddd;border:1px solid #888;">' +
  35. '<DIV id=btDefendProgressBar style="width:0%;height:10px;background-color:#00a;"></DIV>' +
  36. '</DIV>' +
  37. '<DIV id=btDefendProgressText style="text-align:center;font-size:10px;margin-top:2px;"></DIV>' +
  38. '</DIV>' +
  39. '<DIV id=btDefendCityList style="max-height:400px; overflow-y:auto;margin-top:10px;"></DIV>' +
  40. '</DIV>';
  41. // Event listeners
  42. ById('btDefendScanMap').addEventListener('click', t.startMapScan, false);
  43. ById('btDefendShowOwn').addEventListener('change', t.filterResults, false);
  44. ById('btDefendShowAlliance').addEventListener('change', t.filterResults, false);
  45. ById('btDefendShowOthers').addEventListener('change', t.filterResults, false);
  46. // Initial message
  47. ById('btDefendStatus').innerHTML = 'Ready to scan for defending cities on the map';
  48. },
  49. show: function() {
  50. var t = Tabs.Defend;
  51. // Update center coordinates to current city when tab is shown
  52. if (uW.currentcityid) {
  53. ById('btDefendScanX').value = uW.currentcityid.x;
  54. ById('btDefendScanY').value = uW.currentcityid.y;
  55. }
  56. },
  57. hide: function() {
  58. var t = Tabs.Defend;
  59. // Stop any ongoing scan when tab is hidden
  60. t.stopMapScan();
  61. },
  62. startMapScan: function() {
  63. var t = Tabs.Defend;
  64. if (t.mapScanInProgress) {
  65. t.stopMapScan();
  66. return;
  67. }
  68. // Get scan parameters
  69. t.mapScanX = parseInt(ById('btDefendScanX').value);
  70. t.mapScanY = parseInt(ById('btDefendScanY').value);
  71. t.mapScanRadius = parseInt(ById('btDefendScanRadius').value);
  72. // Validate inputs
  73. if (isNaN(t.mapScanX) || isNaN(t.mapScanY) || isNaN(t.mapScanRadius)) {
  74. ById('btDefendStatus').innerHTML = '<SPAN style="color:#800;">Invalid coordinates or radius!</SPAN>';
  75. return;
  76. }
  77. if (t.mapScanRadius < 1) t.mapScanRadius = 1;
  78. if (t.mapScanRadius > 35) t.mapScanRadius = 35; // Limit to reasonable size
  79. // Reset results
  80. t.defendingCities = [];
  81. t.mapScanInProgress = true;
  82. ById('btDefendScanMap').value = "Stop Scan";
  83. // Show progress bar
  84. ById('btDefendProgress').style.display = '';
  85. ById('btDefendProgressBar').style.width = '0%';
  86. ById('btDefendProgressText').innerHTML = 'Preparing scan...';
  87. ById('btDefendStatus').innerHTML = 'Scanning map for defending cities...';
  88. // Create list of coordinates to scan
  89. t.scanCoords = [];
  90. for (var x = t.mapScanX - t.mapScanRadius; x <= t.mapScanX + t.mapScanRadius; x++) {
  91. for (var y = t.mapScanY - t.mapScanRadius; y <= t.mapScanY + t.mapScanRadius; y++) {
  92. // Check if coordinates are within map bounds
  93. if (x >= 0 && x <= 749 && y >= 0 && y <= 749) {
  94. // Calculate distance from center
  95. var dist = Math.sqrt(Math.pow(x - t.mapScanX, 2) + Math.pow(y - t.mapScanY, 2));
  96. if (dist <= t.mapScanRadius) {
  97. t.scanCoords.push({x: x, y: y});
  98. }
  99. }
  100. }
  101. }
  102. t.totalTiles = t.scanCoords.length;
  103. t.tilesScanned = 0;
  104. // Start scanning
  105. t.scanNextTile();
  106. },
  107. scanNextTile: function() {
  108. var t = Tabs.Defend;
  109. if (!t.mapScanInProgress || t.scanCoords.length === 0) {
  110. t.finishMapScan();
  111. return;
  112. }
  113. // Get next coordinate to scan
  114. var coord = t.scanCoords.shift();
  115. t.tilesScanned++;
  116. // Update progress
  117. var progress = Math.floor((t.tilesScanned / t.totalTiles) * 100);
  118. ById('btDefendProgressBar').style.width = progress + '%';
  119. ById('btDefendProgressText').innerHTML = 'Scanning: ' + t.tilesScanned + ' / ' + t.totalTiles + ' tiles';
  120. // Check map data for this tile
  121. uW.cm.MapController.fetchTileData(coord.x, coord.y, function(result) {
  122. if (result && result.tileInfo) {
  123. var tile = result.tileInfo;
  124. // Check if it's a city and if it's defending
  125. if (tile.tileType == 51 && tile.cityInfo) { // 51 is city tile type
  126. var cityInfo = tile.cityInfo;
  127. // Check if city is defending (look for defense status or defense boost)
  128. var isDefending = false;
  129. // Method 1: Check defense status directly if available
  130. if (cityInfo.defStatus && cityInfo.defStatus == 1) {
  131. isDefending = true;
  132. }
  133. // Method 2: Check for defense boost effects
  134. if (cityInfo.effects) {
  135. for (var i = 0; i < cityInfo.effects.length; i++) {
  136. var effect = cityInfo.effects[i];
  137. // Defense boost effects typically have IDs in certain ranges
  138. // This is an approximation - actual IDs may vary
  139. if (DefenceEffects.indexOf(effect.effectId) >= 0) {
  140. isDefending = true;
  141. break;
  142. }
  143. }
  144. }
  145. if (isDefending) {
  146. // Determine ownership type
  147. var ownerType = "enemy";
  148. if (cityInfo.playerId == uW.tvuid) {
  149. ownerType = "own";
  150. } else if (cityInfo.allianceId && cityInfo.allianceId == uW.seed.allianceInfo.allianceId) {
  151. ownerType = "alliance";
  152. }
  153. t.defendingCities.push({
  154. x: coord.x,
  155. y: coord.y,
  156. name: cityInfo.cityName || "Unknown City",
  157. ownerName: cityInfo.playerName || "Unknown Player",
  158. ownerType: ownerType,
  159. might: cityInfo.totalMight || 0
  160. });
  161. }
  162. }
  163. }
  164. // Schedule next tile scan with delay to prevent server overload
  165. setTimeout(t.scanNextTile, t.mapScanDelay);
  166. });
  167. },
  168. stopMapScan: function() {
  169. var t = Tabs.Defend;
  170. t.mapScanInProgress = false;
  171. ById('btDefendScanMap').value = "Scan Map";
  172. ById('btDefendStatus').innerHTML = 'Scan stopped. Found ' + t.defendingCities.length + ' defending cities.';
  173. },
  174. finishMapScan: function() {
  175. var t = Tabs.Defend;
  176. t.mapScanInProgress = false;
  177. ById('btDefendScanMap').value = "Scan Map";
  178. ById('btDefendStatus').innerHTML = 'Scan complete! Found ' + t.defendingCities.length + ' defending cities.';
  179. ById('btDefendProgress').style.display = 'none';
  180. // Display results
  181. t.displayResults();
  182. },
  183. filterResults: function() {
  184. var t = Tabs.Defend;
  185. t.displayResults();
  186. },
  187. displayResults: function() {
  188. var t = Tabs.Defend;
  189. // Get filter settings
  190. var showOwn = ById('btDefendShowOwn').checked;
  191. var showAlliance = ById('btDefendShowAlliance').checked;
  192. var showOthers = ById('btDefendShowOthers').checked;
  193. // Filter cities based on settings
  194. var filteredCities = t.defendingCities.filter(function(city) {
  195. if (city.ownerType === "own" && !showOwn) return false;
  196. if (city.ownerType === "alliance" && !showAlliance) return false;
  197. if (city.ownerType === "enemy" && !showOthers) return false;
  198. return true;
  199. });
  200. var m = '<TABLE width=100% class=xtab><TR class="xtabHD">' +
  201. '<TD width=15%>Coordinates</TD>' +
  202. '<TD width=25%>City Name</TD>' +
  203. '<TD width=25%>Owner</TD>' +
  204. '<TD width=15%>Might</TD>' +
  205. '<TD width=20%>Actions</TD></TR>';
  206. if (filteredCities.length === 0) {
  207. m += '<TR><TD colspan=5 align=center><BR><SPAN style="color:#800;">No defending cities found matching your filters.</SPAN></TD></TR>';
  208. } else {
  209. // Sort cities by distance from scan center
  210. filteredCities.sort(function(a, b) {
  211. var distA = Math.sqrt(Math.pow(a.x - t.mapScanX, 2) + Math.pow(a.y - t.mapScanY, 2));
  212. var distB = Math.sqrt(Math.pow(b.x - t.mapScanX, 2) + Math.pow(b.y - t.mapScanY, 2));
  213. return distA - distB;
  214. });
  215. for (var i = 0; i < filteredCities.length; i++) {
  216. var city = filteredCities[i];
  217. var rowClass = i % 2 ? 'evenRow' : 'oddRow';
  218. var ownerColor = '#000';
  219. // Color-code by owner type
  220. if (city.ownerType === "own") {
  221. ownerColor = '#080'; // Green for own cities
  222. } else if (city.ownerType === "alliance") {
  223. ownerColor = '#008'; // Blue for alliance cities
  224. } else {
  225. ownerColor = '#800'; // Red for enemy cities
  226. }
  227. m += '<TR class="' + rowClass + '">' +
  228. '<TD>(' + city.x + ',' + city.y + ')</TD>' +
  229. '<TD>' + city.name + '</TD>' +
  230. '<TD style="color:' + ownerColor + ';">' + city.ownerName + '</TD>' +
  231. '<TD>' + addCommas(city.might) + '</TD>' +
  232. '<TD>' +
  233. '<INPUT type=button value="View" class="btDefendViewMap" x="' + city.x + '" y="' + city.y + '" /> &nbsp;';
  234. // Add attack button for enemy cities
  235. if (city.ownerType === "enemy") {
  236. m += '<INPUT type=button value="Attack" class="btDefendAttack" x="' + city.x + '" y="' + city.y + '" />';
  237. }
  238. m += '</TD></TR>';
  239. }
  240. }
  241. m += '</TABLE>';
  242. ById('btDefendCityList').innerHTML = m;
  243. // Add event listeners to buttons
  244. var mapButtons = document.getElementsByClassName('btDefendViewMap');
  245. for (var i = 0; i < mapButtons.length; i++) {
  246. mapButtons[i].addEventListener('click', function() {
  247. var x = parseInt(this.getAttribute('x'));
  248. var y = parseInt(this.getAttribute('y'));
  249. uW.cm.MapController.centerMapOnCoord(x, y);
  250. }, false);
  251. }
  252. var attackButtons = document.getElementsByClassName('btDefendAttack');
  253. for (var i = 0; i < attackButtons.length; i++) {
  254. attackButtons[i].addEventListener('click', function() {
  255. var x = parseInt(this.getAttribute('x'));
  256. var y = parseInt(this.getAttribute('y'));
  257. t.prepareAttack(x, y);
  258. }, false);
  259. }
  260. },
  261. prepareAttack: function(x, y) {
  262. var t = Tabs.Defend;
  263. // Center map on target
  264. uW.cm.MapController.centerMapOnCoord(x, y);
  265. // Open attack dialog
  266. setTimeout(function() {
  267. // Find the city tile and click it
  268. var cityDiv = document.querySelector('div[data-tileclass="city"][data-x="' + x + '"][data-y="' + y + '"]');
  269. if (cityDiv) {
  270. nHtml.Click(cityDiv);
  271. // Wait for city info popup to appear
  272. setTimeout(function() {
  273. // Find and click the attack button
  274. var attackBtn = document.querySelector('.cityInfoAttackButton');
  275. if (attackBtn) {
  276. nHtml.Click(attackBtn);
  277. } else {
  278. actionLog('Could not find attack button for city at ' + x + ',' + y, 'DEFEND');
  279. }
  280. }, 1000);
  281. } else {
  282. actionLog('Could not find city at ' + x + ',' + y + ' on the map', 'DEFEND');
  283. }
  284. }, 1000);
  285. },
  286. // Helper function to detect if a city is defending
  287. isCityDefending: function(cityInfo) {
  288. // This is a more comprehensive check for defending status
  289. // Check direct defense status if available
  290. if (cityInfo.defStatus && cityInfo.defStatus == 1) {
  291. return true;
  292. }
  293. // Check for defense-related effects
  294. if (cityInfo.effects) {
  295. for (var i = 0; i < cityInfo.effects.length; i++) {
  296. var effectId = cityInfo.effects[i].effectId;
  297. // Check against known defense effect IDs
  298. if (DefenceEffects.indexOf(effectId) >= 0) {
  299. return true;
  300. }
  301. // Additional checks for specific defense effects
  302. // These IDs may need to be adjusted based on the game's current effect system
  303. if ([2, 18, 25, 30, 35, 40, 45, 51].indexOf(effectId) >= 0) {
  304. return true;
  305. }
  306. }
  307. }
  308. // Check for defense boost items
  309. if (cityInfo.activeItems) {
  310. for (var i = 0; i < cityInfo.activeItems.length; i++) {
  311. var item = cityInfo.activeItems[i];
  312. // Shield items typically have IDs like 362, 363, etc.
  313. if ([362, 363, 364, 365, 366].indexOf(item.itemId) >= 0) {
  314. return true;
  315. }
  316. }
  317. }
  318. return false;
  319. }
  320. };
  321.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址