Dead Frontier Value On Hover (Fixed Version)

Show only the total stack market value on hover in Dead Frontier Outpost. (Fixed data-name priority)

  1. // ==UserScript==
  2. // @name Dead Frontier Value On Hover (Fixed Version)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3
  5. // @license MIT
  6. // @description Show only the total stack market value on hover in Dead Frontier Outpost. (Fixed data-name priority)
  7. // @author Zega (Fixed by ChatGPT)
  8. // @match https://fairview.deadfrontier.com/*
  9. // @grant unsafeWindow
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. // 🚀 Signal implant system if needed
  16. window.BrowserImplant_MarketHover = true;
  17.  
  18. // (Optional) still pull pageData, but we'll favor element attributes
  19. const pageData = unsafeWindow.globalData || {};
  20. const itemNames = {};
  21. for (let id in pageData) {
  22. if (pageData[id] && pageData[id].name) {
  23. itemNames[id] = pageData[id].name;
  24. }
  25. }
  26.  
  27. // Tooltip style
  28. const style = document.createElement('style');
  29. style.textContent = `
  30. .price-tooltip {
  31. position: absolute;
  32. background: rgba(0,0,0,0.85);
  33. color: #fff;
  34. padding: 6px 10px;
  35. font-size: 12px;
  36. border-radius: 6px;
  37. pointer-events: none;
  38. z-index: 9999;
  39. display: none;
  40. }
  41. `;
  42. document.head.appendChild(style);
  43.  
  44. const tooltip = document.createElement('div');
  45. tooltip.className = 'price-tooltip';
  46. document.body.appendChild(tooltip);
  47.  
  48. // Attach hover listeners
  49. function attachListeners() {
  50. document.querySelectorAll('.item:not([data-hover-added])').forEach(el => {
  51. el.setAttribute('data-hover-added', 'true');
  52.  
  53. el.addEventListener('mouseenter', async e => {
  54. const type = el.getAttribute('data-type');
  55. const name = el.getAttribute('data-name') || itemNames[type]; // 🛠️ Prioritize element's data-name
  56. const stack = parseInt(el.getAttribute('data-quantity')) || 1;
  57. if (!name || stack < 1) return;
  58.  
  59. console.log('Hovering over:', { name, stack }); // 🔍 For easy debugging
  60.  
  61. // fetch per-unit price
  62. const unit = await fetchUnitPrice(name);
  63. if (unit == null) {
  64. tooltip.textContent = 'No listings';
  65. } else {
  66. const total = unit * stack;
  67. tooltip.textContent = `$${total.toFixed(2)} total`;
  68. }
  69.  
  70. // Delay a bit to ensure tooltip appears smooth (optional)
  71. setTimeout(() => {
  72. tooltip.style.left = `${e.pageX + 12}px`;
  73. tooltip.style.top = `${e.pageY + 12}px`;
  74. tooltip.style.display = 'block';
  75. }, 0);
  76. });
  77.  
  78. el.addEventListener('mouseleave', () => {
  79. tooltip.style.display = 'none';
  80. });
  81. });
  82. }
  83.  
  84. const observer = new MutationObserver(attachListeners);
  85. observer.observe(document.body, { childList: true, subtree: true });
  86. attachListeners();
  87.  
  88. // Fetch best per-unit price
  89. async function fetchUnitPrice(itemName) {
  90. const rawHash = getCookie('DeadFrontierFairview') || '';
  91. const hash = decodeURIComponent(rawHash);
  92. const pagetime = Math.floor(Date.now() / 1000);
  93. const payload = {
  94. hash,
  95. pagetime,
  96. tradezone: 21,
  97. search: 'trades',
  98. searchtype: 'buyinglistitemname',
  99. searchname: itemName
  100. };
  101.  
  102. try {
  103. const res = await fetch('https://fairview.deadfrontier.com/onlinezombiemmo/trade_search.php', {
  104. method: 'POST',
  105. headers: {
  106. 'Content-Type': 'application/x-www-form-urlencoded',
  107. 'X-Requested-With': 'XMLHttpRequest',
  108. 'Referer': location.href,
  109. 'Origin': location.origin
  110. },
  111. body: Object.entries(payload)
  112. .map(([k,v])=>`${k}=${encodeURIComponent(v)}`)
  113. .join('&')
  114. });
  115. const text = await res.text();
  116. const matches = [...text.matchAll(/tradelist_\d+_price=(\d+)&.*?tradelist_\d+_quantity=(\d+)/g)]
  117. .map(m => Number(m[1]) / Number(m[2]))
  118. .sort((a,b) => a - b);
  119. return matches.length ? matches[0] : null;
  120. } catch (err) {
  121. console.error('fetchUnitPrice error', err);
  122. return null;
  123. }
  124. }
  125.  
  126. // Get cookie helper
  127. function getCookie(name) {
  128. const v = `; ${document.cookie}`;
  129. const parts = v.split(`; ${name}=`);
  130. return parts.length === 2 ? parts.pop().split(';')[0] : '';
  131. }
  132. })();