TC Bootlegging Plus v2

Tools to help with Bootlegging

当前为 2025-03-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name TC Bootlegging Plus v2
  3. // @namespace DieselBladeScripts
  4. // @version 0.94
  5. // @description Tools to help with Bootlegging
  6. // @license GPLv3
  7. // @author DieselBlade [1701621]
  8. // @match *https://www.torn.com/loader.php?sid=crimes*
  9. // @grant unsafeWindow
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13.  
  14. const originalFetch = fetch;
  15.  
  16. unsafeWindow.fetch = async (input, init) => {
  17. const response = await originalFetch(input, init);
  18. if (input.includes('crimesData')) {
  19. crimesMain(response.clone()).catch(console.error);
  20. }
  21. return response;
  22. };
  23.  
  24. async function crimesMain(res) {
  25. const crimesData = await res.json();
  26. const crimeType = crimesData?.DB?.currentUserStatistics?.[1]?.value;
  27.  
  28. if (crimeType === 'Counterfeiting') {
  29. counterfeiting(crimesData.DB);
  30. } else {
  31. console.log(crimesData);
  32. }
  33. }
  34.  
  35. async function counterfeiting(db) {
  36. const { generalInfo, currentUserStats, crimesByType } = db;
  37. const CDs = {
  38. have: generalInfo.CDs,
  39. sold: {
  40. 1: currentUserStats.CDType1Sold,
  41. 2: currentUserStats.CDType2Sold,
  42. 3: currentUserStats.CDType3Sold,
  43. 4: currentUserStats.CDType4Sold,
  44. 5: currentUserStats.CDType5Sold,
  45. 6: currentUserStats.CDType6Sold,
  46. 7: currentUserStats.CDType7Sold,
  47. 8: currentUserStats.CDType8Sold
  48. },
  49. genres: {
  50. 'Action': '1',
  51. 'Comedy': '2',
  52. 'Drama': '3',
  53. 'Fantasy': '4',
  54. 'Horror': '5',
  55. 'Romance': '6',
  56. 'Thriller': '7',
  57. 'Sci-Fi': '8'
  58. }
  59. };
  60.  
  61. const currentQueue = crimesByType?.['0']?.additionalInfo?.currentQueue || [];
  62. currentQueue.forEach(cdID => CDs.have[cdID] += 1);
  63.  
  64. const observer = new MutationObserver(() => {
  65. const genreButtons = document.querySelectorAll('button[class^=genreStock]');
  66. if (genreButtons.length > 0) {
  67. updateGenreButtons(CDs);
  68. observer.disconnect();
  69. }
  70. });
  71.  
  72. observer.observe(document, { childList: true, subtree: true });
  73. }
  74.  
  75. function updateGenreButtons(CDs) {
  76. const GREEN_HSL = 120; // Green for excess copies
  77. const RED_HSL = 0; // Red for biggest shortages
  78.  
  79. const totalHave = sumValues(CDs.have);
  80. const totalSold = sumValues(CDs.sold);
  81.  
  82. let maxShortage = 0; // Track the worst shortage
  83.  
  84. // First pass: Determine the maximum shortage
  85. document.querySelectorAll('button[class^=genreStock]').forEach((genreButton) => {
  86. const genre = genreButton.getAttribute('aria-label').split(' - ')[0].replace('Copying ', '');
  87. const typeID = CDs.genres[genre];
  88. const target = Math.floor((CDs.sold[typeID] / totalSold) * totalHave);
  89. const diff = target - CDs.have[typeID]; // Positive means more are needed, negative means excess
  90. if (diff > maxShortage) {
  91. maxShortage = diff; // Store the highest shortage
  92. }
  93. });
  94.  
  95. // Second pass: Apply colors based on shortage severity
  96. document.querySelectorAll('button[class^=genreStock]').forEach((genreButton) => {
  97. const genre = genreButton.getAttribute('aria-label').split(' - ')[0].replace('Copying ', '');
  98. const typeID = CDs.genres[genre];
  99. const target = Math.floor((CDs.sold[typeID] / totalSold) * totalHave);
  100. const diff = target - CDs.have[typeID]; // Positive means more are needed, negative means excess
  101.  
  102. let h;
  103. if (diff > 0) {
  104. // Shortage: scale from red (0) to neutral
  105. h = RED_HSL + (1 - diff / maxShortage) * (GREEN_HSL - RED_HSL);
  106. } else {
  107. // Excess: Make it green
  108. h = GREEN_HSL;
  109. }
  110.  
  111. genreButton.style.backgroundColor = `hsl(${h}, 100%, 90%)`;
  112.  
  113. // Ensure text remains readable
  114. genreButton.style.color = "#888"; // Ensure button text is dark grey
  115.  
  116. // Update the "copying" text color
  117. const statusText = genreButton.querySelector('.statusText___fRZso');
  118. if (statusText) {
  119. statusText.style.color = "#888";
  120. }
  121.  
  122. // Update the text for how many more are needed or if there are excess copies
  123. const existingDiffText = genreButton.querySelector('.diffText');
  124. if (existingDiffText) {
  125. existingDiffText.remove();
  126. }
  127.  
  128. const diffText = document.createElement('div');
  129. diffText.className = 'diffText';
  130. diffText.textContent = diff > 0 ? `${diff} more needed` : 'Excess copies';
  131. diffText.style.color = "#888"; // Ensure text remains readable
  132. genreButton.appendChild(diffText);
  133. });
  134. }
  135.  
  136.  
  137.  
  138.  
  139.  
  140. function sumValues(obj) {
  141. return Object.values(obj).reduce((a, b) => a + b, 0);
  142. }
  143.