Torn Territory War Time Left

Shows time left until territory is captured given the current or bestcase attackers & defenders count right underneath war timeout ticker.

安装此脚本?
作者推荐脚本

您可能也喜欢Torn Bazaar Filler

安装此脚本
  1. // ==UserScript==
  2. // @name Torn Territory War Time Left
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description Shows time left until territory is captured given the current or bestcase attackers & defenders count right underneath war timeout ticker.
  6. // @author Ramin Quluzade, Silmaril [2665762]
  7. // @license MIT License
  8. // @match https://www.torn.com/factions.php?step=your*
  9. // @match https://www.torn.com/factions.php?step=profile&ID=*
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. const targetElementSelector = '.f-war-list.war-new';
  18. const observerOptions = { childList: true, subtree: true };
  19.  
  20. const observerCallback = async function(mutationsList, observer) {
  21. for (const mutation of mutationsList) {
  22. if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
  23. const targetElement = document.querySelector(targetElementSelector);
  24. if (targetElement) {
  25. let territoryWars = mutation.target.querySelectorAll(".f-war-list.war-new div[class^='status-wrap territoryBox']");
  26. if (territoryWars.length > 0) {
  27. console.log('Target element found!');
  28. territoryWars.forEach(war => {
  29. war.querySelector('.info .faction-progress-wrap').style.paddingTop = '0px';
  30. let timeLeftElement = document.createElement('div');
  31. timeLeftElement.classList.add('time-left', 'timer');
  32. let timeLeftBestElement = document.createElement('div');
  33. timeLeftBestElement.classList.add('time-left-best', 'timer');
  34. war.querySelector('.info .faction-progress-wrap').append(timeLeftElement, timeLeftBestElement);
  35. });
  36. territoryWars.forEach(war => {
  37. let enemyCountDiv = war.querySelector('.info .member-count.enemy-count .count');
  38. let allyCountDiv = war.querySelector('.info .member-count.your-count .count');
  39.  
  40. renderTimeLeft(war);
  41.  
  42. // Set up a MutationObserver on the added child element
  43. const childObserver = new MutationObserver(function(childMutations) {
  44. childMutations.forEach(function(childMutation) {
  45. if (childMutation.type === 'characterData') {
  46. let territoryWar = childMutation.target.parentNode.parentNode.parentNode.parentNode;
  47. renderTimeLeft(territoryWar);
  48. }
  49. });
  50. });
  51.  
  52. setInterval(renderTimeLeft, 1000 + Math.floor(Math.random() * 10) + 1, war);
  53.  
  54. childObserver.observe(enemyCountDiv, { characterData: true, subtree: true });
  55. childObserver.observe(allyCountDiv, { characterData: true, subtree: true });
  56. });
  57. observer.disconnect();
  58. }
  59. }
  60. }
  61. }
  62. };
  63.  
  64. const observer = new MutationObserver(observerCallback);
  65. observer.observe(document.documentElement, observerOptions);
  66. console.log('Observer started. Waiting for target element to appear...');
  67.  
  68. function renderTimeLeft(war) {
  69. let enemyCountDiv = war.querySelector('.info .member-count.enemy-count .count');
  70. let allyCountDiv = war.querySelector('.info .member-count.your-count .count');
  71. let enemyCount = Number(enemyCountDiv.innerText);
  72. let allyCount = Number(allyCountDiv.innerText);
  73. let isAllyAttack = war.querySelector('.info .member-count.your-count .count i').classList.contains('swords-icon');
  74. let remainder = isAllyAttack ? allyCount - enemyCount : enemyCount - allyCount;
  75. let timeLeft = '??:??:??:??';
  76. let timeLeftBest = '??:??:??:??';
  77. let scoreText = war.querySelector('.info .faction-progress-wrap .score').innerText;
  78. let score = scoreText.replaceAll(',', '').split('/');
  79. let pointsLeft = Number(score[1]) - Number(score[0]);
  80. let maximumSlots = Number(score[1]) / 50000;
  81. if (remainder > 0) {
  82. let secondsUntilGoal = pointsLeft / remainder;
  83. timeLeft = convertSecondsToDHMS(secondsUntilGoal);
  84. }
  85. timeLeftBest = convertSecondsToDHMS(pointsLeft / maximumSlots);
  86. let timeLeftDiv = war.querySelector('.info .faction-progress-wrap .time-left');
  87. let timeLeftBestDiv = war.querySelector('.info .faction-progress-wrap .time-left-best');
  88. const timeLeftCharacters = timeLeft.split('');
  89. const timeLeftBestCharacters = timeLeftBest.split('');
  90. const timeLeftSpanArray = ['CURRENT '];
  91. timeLeftCharacters.forEach(char => {
  92. const span = document.createElement('span');
  93. span.textContent = char;
  94. timeLeftSpanArray.push(span);
  95. });
  96. timeLeftDiv.replaceChildren(...timeLeftSpanArray);
  97. const timeLeftBestSpanArray = ['BESTCASE '];
  98. timeLeftBestCharacters.forEach(char => {
  99. const span = document.createElement('span');
  100. span.textContent = char;
  101. timeLeftBestSpanArray.push(span);
  102. });
  103. timeLeftBestDiv.replaceChildren(...timeLeftBestSpanArray);
  104. }
  105.  
  106. function convertSecondsToDHMS(seconds) {
  107. if (seconds === Infinity){
  108. return '??:??:??:??';
  109. }
  110.  
  111. const oneDay = 86400; // number of seconds in a day
  112. const oneHour = 3600; // number of seconds in an hour
  113. const oneMinute = 60; // number of seconds in a minute
  114.  
  115. // Calculate the number of days, hours, minutes, and seconds
  116. const days = Math.floor(seconds / oneDay);
  117. const hours = Math.floor((seconds % oneDay) / oneHour);
  118. const minutes = Math.floor((seconds % oneHour) / oneMinute);
  119. const remainingSeconds = Math.round(seconds % oneMinute);
  120.  
  121. // Construct a formatted string with the results
  122. let output = '';
  123. output += `${days.toString().padStart(2, '0')}:`;
  124. output += `${hours.toString().padStart(2, '0')}:`;
  125. output += `${minutes.toString().padStart(2, '0')}:`;
  126. output += `${remainingSeconds.toString().padStart(2, '0')}`;
  127.  
  128. return output;
  129. }
  130. })();

QingJ © 2025

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