Genshin Impact AppSample Map - More Markable Markers

Mark more things on the interactive map

  1. // ==UserScript==
  2. // @name Genshin Impact AppSample Map - More Markable Markers
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.4
  5. // @description Mark more things on the interactive map
  6. // @author 2KRN4U
  7. // @match https://genshin-impact-map.appsample.com/*
  8. // @run-at document-start
  9. // @icon https://genshin-impact-map.appsample.com/favicon.ico
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. const changeAll = false; // Change to true if you want everything to be markable
  18.  
  19. // List of markers to change
  20. const keys = [
  21. "o128", // Geo Sigil
  22. "o317", // Interaction Rewards
  23. "o409", // Clusterleaf of Cultivation
  24. "o415", // Dendro Rock
  25. "o416", // Dendro Pile
  26. // Natlan
  27. "o596", // Natlan Mora Chest
  28. "o601", // Shattered Night Jade
  29. "o602", // Broken, Graffiti-Marked Stone
  30. "o639", // Tribal Secret Spaces
  31. "o641", // Courier's Trial Keystone
  32. "o647", // Totem Challenge
  33. "o666", // Oozing Core
  34. "o681", // Coagulation Pearl
  35. "o684", // Iridescent Inscription
  36. // Nod-Krai
  37. "o723", // Nod-Krai Mora Chest
  38. "o724", // Hidden Troves
  39. "o725", // Kuuhenki
  40. "o726", // Robot Unit
  41. "o727", // "Engraving" Fragment
  42. "o728", // Kuuvahki Relay Mechanism
  43. "o729", // ID Cards
  44. "o730", // Stellafruit
  45. "o731", // Proof of the Cognoscenti
  46. "o732", // Krumkake Bolt
  47. "o733", // Bounty Token
  48. "o734", // Conch-Patterned Item
  49. "o735", // Sigurd's Relic
  50. "o741", // Valiant Chronicles
  51. "o742", // Strange Creatures
  52. "o760", // Oath Lantern
  53. ];
  54.  
  55. // 🚫 Do not change anything below this line 🚫
  56.  
  57. const targetFilenameStart = "markers_all"; // Filename of the markers file
  58.  
  59. const allowMarkComment = 5; // Value to allow marking and commenting
  60.  
  61. // Save references to the original XHR methods
  62. const originalOpen = XMLHttpRequest.prototype.open;
  63. const originalSend = XMLHttpRequest.prototype.send;
  64.  
  65. // Override the open method
  66. XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
  67. this._filename = url.split('/').pop(); // Extract the filename from the URL
  68. this._url = url; // Store the URL for later use
  69. originalOpen.apply(this, arguments); // Call the original open method
  70. };
  71.  
  72. // Override the send method
  73. XMLHttpRequest.prototype.send = function (body) {
  74. this.addEventListener('readystatechange', function () {
  75. // Only process requests if the filename matches the target prefix
  76. if (
  77. this.readyState === 4 &&
  78. this.status === 200 &&
  79. this._filename.startsWith(targetFilenameStart) // Check if filename starts with the target string
  80. ) {
  81. try {
  82. let modifiedResponseText = this.responseText;
  83.  
  84. if (changeAll) {
  85. const searchPattern = /("o\d+",\d+,)(\d+)(,)/g;
  86. modifiedResponseText = modifiedResponseText.replace(
  87. searchPattern,
  88. (_, prefix, lastDigits, suffix) => `${prefix}${allowMarkComment}${suffix}`
  89. ); // Make everything markable + comments
  90. } else {
  91. // Apply replacements for each key in the list
  92. keys.forEach(key => {
  93. const searchPattern = new RegExp(`("${key}",\\d+,)(\\d+)(,)`, 'g'); // Search pattern for markers
  94. modifiedResponseText = modifiedResponseText.replace(
  95. searchPattern,
  96. (_, prefix, lastDigits, suffix) => `${prefix}${allowMarkComment}${suffix}`
  97. ); // Replace to allow marking and commenting
  98. });
  99. }
  100.  
  101.  
  102. // Overwrite the responseText property with the modified content
  103. Object.defineProperty(this, 'responseText', {
  104. value: modifiedResponseText,
  105. configurable: true,
  106. });
  107.  
  108. // Optional: Overwrite response (useful if response is accessed differently)
  109. Object.defineProperty(this, 'response', {
  110. value: modifiedResponseText,
  111. configurable: true,
  112. });
  113. } catch (e) {
  114. console.error('Error modifying JSON response:', e);
  115. }
  116. }
  117. });
  118.  
  119. // Call the original send method
  120. originalSend.apply(this, arguments);
  121. };
  122.  
  123. // Wait for the DOM to fully load
  124. window.addEventListener('load', function () {
  125. // Function to modify the title
  126. const modifyTitle = (originalTitle, dataTestId) => {
  127. // Trim the first 4 characters of data-testid
  128. const trimmedData = dataTestId ? dataTestId.slice(4) : 'Unknown';
  129. // Combine the original title with the trimmed data-testid
  130. return `${originalTitle}: ${trimmedData}`;
  131. };
  132.  
  133. // Select all buttons with the class "MuiButtonBase-root"
  134. const buttons = document.querySelectorAll('.MuiButtonBase-root');
  135.  
  136. // Iterate over each button
  137. buttons.forEach(button => {
  138. const originalTitle = button.getAttribute('title');
  139. const dataTestId = button.getAttribute('data-testid');
  140.  
  141. // Only proceed if both title and data-testid exist
  142. if (originalTitle && dataTestId) {
  143. const newTitle = modifyTitle(originalTitle, dataTestId);
  144. button.setAttribute('title', newTitle);
  145. }
  146. });
  147. });
  148. })();