Browser Implants + True CSS Hover v5.32

Browser Implants injected below QuickBuy; full hover popups; collapsible/expandable panel; state save; scroll and zoom stable; polished style matching QuickBuy/AutoBank

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

  1. // ==UserScript==
  2. // @name Browser Implants + True CSS Hover v5.32
  3. // @namespace Zega
  4. // @version 5.32
  5. // @description Browser Implants injected below QuickBuy; full hover popups; collapsible/expandable panel; state save; scroll and zoom stable; polished style matching QuickBuy/AutoBank
  6. // @match https://fairview.deadfrontier.com/onlinezombiemmo/index.php*
  7. // @grant none
  8. // @run-at document-start
  9. // ==/UserScript==
  10. (function() {
  11. 'use strict';
  12. let _autoBankQueued = false, _autoBankDone = false;
  13. let _qbQueued = false, _qbDone = false;
  14. function _onAutoBank() {
  15. if (_autoBankDone) return;
  16. _autoBankQueued = true;
  17. if (typeof fillAutoBankSlot === 'function') fillAutoBankSlot();
  18. }
  19. function _onQuickBuy() {
  20. if (_qbDone) return;
  21. _qbQueued = true;
  22. if (typeof fillQuickBuySlot === 'function') fillQuickBuySlot();
  23. }
  24. Object.defineProperty(window, 'BrowserImplant_AutoBank', {
  25. configurable: true,
  26. enumerable: true,
  27. set(val) {
  28. if (val) _onAutoBank();
  29. Object.defineProperty(window, 'BrowserImplant_AutoBank', {
  30. value: val,
  31. writable: true,
  32. configurable: true,
  33. enumerable: true
  34. });
  35. },
  36. get() { return false; }
  37. });
  38. Object.defineProperty(window, 'BrowserImplant_QuickBuy', {
  39. configurable: true,
  40. enumerable: true,
  41. set(val) {
  42. if (val) _onQuickBuy();
  43. Object.defineProperty(window, 'BrowserImplant_QuickBuy', {
  44. value: val,
  45. writable: true,
  46. configurable: true,
  47. enumerable: true
  48. });
  49. },
  50. get() { return false; }
  51. });
  52. window.addEventListener('load', initWhenReady);
  53. function initWhenReady() {
  54. const tryAttach = setInterval(() => {
  55. const rightTd = document.querySelector('td.design2010[style*="right_margin.jpg"]');
  56. const quickBuyFieldset = rightTd?.querySelector('fieldset');
  57. if (rightTd && quickBuyFieldset) {
  58. clearInterval(tryAttach);
  59. attachImplants(rightTd);
  60. }
  61. }, 100);
  62. }
  63. function attachImplants(rightTd) {
  64. rightTd.style.position = 'relative';
  65. const panel = document.createElement('div');
  66. panel.id = 'browser-implant-panel';
  67. panel.innerHTML = `
  68. <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;">
  69. <strong style="color:#ffd700;">Browser Implants</strong>
  70. <button id="collapse-browser-implant" style="background:none;border:none;color:#ffd700;font-size:16px;cursor:pointer;">[–]</button>
  71. </div>
  72. <div class="implant-grid" id="implant-grid-container">
  73. ${Array(8).fill(0).map((_,i)=>`
  74. <div class="slot" data-slot="${i}">
  75. <img class="implant-icon" style="display:none;" />
  76. <div class="hover-popup">
  77. <img class="hover-img" src="" />
  78. <div class="hover-name"></div>
  79. <div class="hover-stat"></div>
  80. </div>
  81. </div>
  82. `).join('')}
  83. </div>
  84. `;
  85. Object.assign(panel.style, {
  86. position: 'absolute',
  87. top: '660px',
  88. left: '10px',
  89. width: '420px',
  90. background: 'rgba(0,0,0,0.35)',
  91. padding: '8px 12px',
  92. border: '1px solid #666',
  93. borderRadius: '8px',
  94. boxShadow: '0 4px 12px rgba(0,0,0,0.6)',
  95. textAlign: 'center',
  96. zIndex: '10000'
  97. });
  98. rightTd.appendChild(panel);
  99. const slots = panel.querySelectorAll('.slot');
  100. const grid = document.getElementById('implant-grid-container');
  101. const collapseBtn = document.getElementById('collapse-browser-implant');
  102. // Restore collapse state
  103. if (localStorage.getItem('browserImplantCollapsed') === 'true') {
  104. grid.style.display = 'none';
  105. collapseBtn.textContent = '[+]';
  106. }
  107. collapseBtn.addEventListener('click', () => {
  108. if (grid.style.display === 'none') {
  109. grid.style.display = 'grid';
  110. collapseBtn.textContent = '[–]';
  111. localStorage.setItem('browserImplantCollapsed', 'false');
  112. } else {
  113. grid.style.display = 'none';
  114. collapseBtn.textContent = '[+]';
  115. localStorage.setItem('browserImplantCollapsed', 'true');
  116. }
  117. });
  118. let next = 0;
  119. function fill(slot, url, name, stat) {
  120. const img = slot.querySelector('img.implant-icon');
  121. const pop = slot.querySelector('.hover-popup');
  122. img.src = url;
  123. img.style.display = 'block';
  124. img.style.width = '100%';
  125. img.style.height = '100%';
  126. img.style.objectFit = 'contain';
  127. pop.querySelector('.hover-img').src = url;
  128. pop.querySelector('.hover-name').textContent = name;
  129. pop.querySelector('.hover-stat').textContent = stat;
  130. }
  131. fill(slots[next++], 'https://files.catbox.moe/y2n5ij.png', 'Browser Implant', 'Gain Efficiency In Outpost +20%');
  132. if (window.BrowserImplant_MarketHover) {
  133. fill(slots[next++], 'https://files.catbox.moe/kqee23.png', 'Market Hover Implant', 'Quick Access to Trade Values +15%');
  134. }
  135. window.fillAutoBankSlot = () => {
  136. if (_autoBankDone || next >= slots.length) return;
  137. fill(slots[next++], 'https://files.catbox.moe/ry7yd2.png', 'Auto Bank Implant', 'Instant bank link—deposits & withdrawals +60% speed!');
  138. _autoBankDone = true;
  139. };
  140. if (_autoBankQueued) window.fillAutoBankSlot();
  141. window.fillQuickBuySlot = () => {
  142. if (_qbDone || next >= slots.length) return;
  143. fill(slots[next++], 'https://files.catbox.moe/urko7b.png', 'QuickBuy Implant', 'Quickly buy your survival items. 70% Barter Speed!');
  144. _qbDone = true;
  145. };
  146. if (_qbQueued) window.fillQuickBuySlot();
  147. }
  148. const css = `
  149. #browser-implant-panel .implant-grid {
  150. display: grid;
  151. grid-template-columns: repeat(4, 36px);
  152. grid-template-rows: repeat(2, 36px);
  153. gap: 4px;
  154. justify-content: center;
  155. }
  156. #browser-implant-panel .slot {
  157. width: 36px;
  158. height: 36px;
  159. background: rgba(255,255,255,0.05);
  160. border: 1px solid #888;
  161. border-radius: 4px;
  162. position: relative;
  163. }
  164. #browser-implant-panel .slot img.implant-icon {
  165. position: absolute;
  166. top: 0; left: 0;
  167. width: 100%; height: 100%;
  168. object-fit: contain;
  169. cursor: default;
  170. display: none;
  171. }
  172. #browser-implant-panel .hover-popup {
  173. display: none;
  174. position: absolute;
  175. bottom: -18px;
  176. left: 50%;
  177. transform: translateX(-50%);
  178. background: rgba(0,0,0,0.85);
  179. padding: 6px;
  180. border: 1px solid #555;
  181. border-radius: 6px;
  182. flex-direction: column;
  183. align-items: center;
  184. z-index: 1000;
  185. opacity: 0;
  186. transition: opacity .2s;
  187. width: 130px;
  188. }
  189. #browser-implant-panel .hover-popup .hover-img {
  190. width: 50px;
  191. height: 50px;
  192. margin-bottom: 4px;
  193. object-fit: contain;
  194. }
  195. #browser-implant-panel .hover-name,
  196. #browser-implant-panel .hover-stat {
  197. color: gold;
  198. font-size: 12px;
  199. margin: 1px 0;
  200. line-height: 1.1;
  201. text-align: center;
  202. }
  203. #browser-implant-panel .slot:hover .hover-popup {
  204. display: flex;
  205. opacity: 1;
  206. }
  207. #browser-implant-panel .slot:not(:has(img.implant-icon[style*="display: block"])) .hover-popup {
  208. display: none!important;
  209. opacity: 0!important;
  210. }
  211. `;
  212. const style = document.createElement('style');
  213. style.textContent = css;
  214. document.head.appendChild(style);
  215. })();