Dead Frontier – Browser Implants + True CSS Hover (v5.32 Final Fancy)

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 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Dead Frontier – Browser Implants + True CSS Hover (v5.32 Final Fancy)
// @namespace    Zega
// @version      5.32
// @description  Browser Implants injected below QuickBuy; full hover popups; collapsible/expandable panel; state save; scroll and zoom stable; polished style matching QuickBuy/AutoBank
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
  'use strict';

  let _autoBankQueued = false, _autoBankDone = false;
  let _qbQueued = false, _qbDone = false;

  function _onAutoBank() {
    if (_autoBankDone) return;
    _autoBankQueued = true;
    if (typeof fillAutoBankSlot === 'function') fillAutoBankSlot();
  }
  function _onQuickBuy() {
    if (_qbDone) return;
    _qbQueued = true;
    if (typeof fillQuickBuySlot === 'function') fillQuickBuySlot();
  }

  Object.defineProperty(window, 'BrowserImplant_AutoBank', {
    configurable: true,
    enumerable: true,
    set(val) {
      if (val) _onAutoBank();
      Object.defineProperty(window, 'BrowserImplant_AutoBank', {
        value: val,
        writable: true,
        configurable: true,
        enumerable: true
      });
    },
    get() { return false; }
  });

  Object.defineProperty(window, 'BrowserImplant_QuickBuy', {
    configurable: true,
    enumerable: true,
    set(val) {
      if (val) _onQuickBuy();
      Object.defineProperty(window, 'BrowserImplant_QuickBuy', {
        value: val,
        writable: true,
        configurable: true,
        enumerable: true
      });
    },
    get() { return false; }
  });

  window.addEventListener('load', initWhenReady);

  function initWhenReady() {
    const tryAttach = setInterval(() => {
      const rightTd = document.querySelector('td.design2010[style*="right_margin.jpg"]');
      const quickBuyFieldset = rightTd?.querySelector('fieldset');
      if (rightTd && quickBuyFieldset) {
        clearInterval(tryAttach);
        attachImplants(rightTd);
      }
    }, 100);
  }

  function attachImplants(rightTd) {
    rightTd.style.position = 'relative';

    const panel = document.createElement('div');
    panel.id = 'browser-implant-panel';
    panel.innerHTML = `
      <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;">
        <strong style="color:#ffd700;">Browser Implants</strong>
        <button id="collapse-browser-implant" style="background:none;border:none;color:#ffd700;font-size:16px;cursor:pointer;">[–]</button>
      </div>
      <div class="implant-grid" id="implant-grid-container">
        ${Array(8).fill(0).map((_,i)=>`
          <div class="slot" data-slot="${i}">
            <img class="implant-icon" style="display:none;" />
            <div class="hover-popup">
              <img class="hover-img" src="" />
              <div class="hover-name"></div>
              <div class="hover-stat"></div>
            </div>
          </div>
        `).join('')}
      </div>
    `;
    Object.assign(panel.style, {
      position: 'absolute',
      top: '660px',
      left: '10px',
      width: '420px',
      background: 'rgba(0,0,0,0.35)',
      padding: '8px 12px',
      border: '1px solid #666',
      borderRadius: '8px',
      boxShadow: '0 4px 12px rgba(0,0,0,0.6)',
      textAlign: 'center',
      zIndex: '10000'
    });

    rightTd.appendChild(panel);

    const slots = panel.querySelectorAll('.slot');
    const grid = document.getElementById('implant-grid-container');
    const collapseBtn = document.getElementById('collapse-browser-implant');

    // Restore collapse state
    if (localStorage.getItem('browserImplantCollapsed') === 'true') {
      grid.style.display = 'none';
      collapseBtn.textContent = '[+]';
    }

    collapseBtn.addEventListener('click', () => {
      if (grid.style.display === 'none') {
        grid.style.display = 'grid';
        collapseBtn.textContent = '[–]';
        localStorage.setItem('browserImplantCollapsed', 'false');
      } else {
        grid.style.display = 'none';
        collapseBtn.textContent = '[+]';
        localStorage.setItem('browserImplantCollapsed', 'true');
      }
    });

    let next = 0;

    function fill(slot, url, name, stat) {
      const img = slot.querySelector('img.implant-icon');
      const pop = slot.querySelector('.hover-popup');
      img.src = url;
      img.style.display = 'block';
      img.style.width = '100%';
      img.style.height = '100%';
      img.style.objectFit = 'contain';
      pop.querySelector('.hover-img').src = url;
      pop.querySelector('.hover-name').textContent = name;
      pop.querySelector('.hover-stat').textContent = stat;
    }

    fill(slots[next++], 'https://files.catbox.moe/y2n5ij.png', 'Browser Implant', 'Gain Efficiency In Outpost +20%');

    if (window.BrowserImplant_MarketHover) {
      fill(slots[next++], 'https://files.catbox.moe/kqee23.png', 'Market Hover Implant', 'Quick Access to Trade Values +15%');
    }

    window.fillAutoBankSlot = () => {
      if (_autoBankDone || next >= slots.length) return;
      fill(slots[next++], 'https://files.catbox.moe/ry7yd2.png', 'Auto Bank Implant', 'Instant bank link—deposits & withdrawals +60% speed!');
      _autoBankDone = true;
    };
    if (_autoBankQueued) window.fillAutoBankSlot();

    window.fillQuickBuySlot = () => {
      if (_qbDone || next >= slots.length) return;
      fill(slots[next++], 'https://files.catbox.moe/urko7b.png', 'QuickBuy Implant', 'Quickly buy your survival items. 70% Barter Speed!');
      _qbDone = true;
    };
    if (_qbQueued) window.fillQuickBuySlot();
  }

  const css = `
    #browser-implant-panel .implant-grid {
      display: grid;
      grid-template-columns: repeat(4, 36px);
      grid-template-rows: repeat(2, 36px);
      gap: 4px;
      justify-content: center;
    }
    #browser-implant-panel .slot {
      width: 36px;
      height: 36px;
      background: rgba(255,255,255,0.05);
      border: 1px solid #888;
      border-radius: 4px;
      position: relative;
    }
    #browser-implant-panel .slot img.implant-icon {
      position: absolute;
      top: 0; left: 0;
      width: 100%; height: 100%;
      object-fit: contain;
      cursor: default;
      display: none;
    }
    #browser-implant-panel .hover-popup {
      display: none;
      position: absolute;
      bottom: -18px;
      left: 50%;
      transform: translateX(-50%);
      background: rgba(0,0,0,0.85);
      padding: 6px;
      border: 1px solid #555;
      border-radius: 6px;
      flex-direction: column;
      align-items: center;
      z-index: 1000;
      opacity: 0;
      transition: opacity .2s;
      width: 130px;
    }
    #browser-implant-panel .hover-popup .hover-img {
      width: 50px;
      height: 50px;
      margin-bottom: 4px;
      object-fit: contain;
    }
    #browser-implant-panel .hover-name,
    #browser-implant-panel .hover-stat {
      color: gold;
      font-size: 12px;
      margin: 1px 0;
      line-height: 1.1;
      text-align: center;
    }
    #browser-implant-panel .slot:hover .hover-popup {
      display: flex;
      opacity: 1;
    }
    #browser-implant-panel .slot:not(:has(img.implant-icon[style*="display: block"])) .hover-popup {
      display: none!important;
      opacity: 0!important;
    }
  `;
  const style = document.createElement('style');
  style.textContent = css;
  document.head.appendChild(style);

})();