SugarCube Game Cheat Panel

Edit variables in SugarCube games easily via a draggable, collapsible UI with dynamic suggestions and auto-populated values.

目前为 2025-02-17 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name SugarCube Game Cheat Panel
  3. // @version 1.0
  4. // @description Edit variables in SugarCube games easily via a draggable, collapsible UI with dynamic suggestions and auto-populated values.
  5. // @author skydk
  6. // @match *://*/*
  7. // @grant none
  8. // @license MIT
  9. // @namespace https://greasyfork.org/users/1436204
  10. // ==/UserScript==
  11.  
  12. /* global SugarCube */
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. function checkSugarCube() {
  18. return typeof SugarCube !== 'undefined' &&
  19. SugarCube.version &&
  20. typeof SugarCube.version.build !== 'undefined' &&
  21. Number(SugarCube.version.build) > 500 &&
  22. typeof SugarCube.State !== 'undefined' &&
  23. typeof SugarCube.State.variables !== 'undefined';
  24. }
  25.  
  26. function setVariable(varName, value) {
  27. if (checkSugarCube()) {
  28. SugarCube.State.variables[varName] = value;
  29. } else {
  30. alert("SugarCube not detected or incompatible version!");
  31. }
  32. }
  33.  
  34. function updateSuggestions() {
  35. const dataList = document.getElementById('varSuggestions');
  36. if (!dataList) return;
  37. // Clear existing options
  38. dataList.innerHTML = '';
  39. if (checkSugarCube()) {
  40. Object.keys(SugarCube.State.variables).forEach(key => {
  41. const option = document.createElement('option');
  42. option.value = key;
  43. dataList.appendChild(option);
  44. });
  45. }
  46. }
  47.  
  48. function createUI() {
  49. let panel = document.createElement('div');
  50. panel.id = 'sugarcube-cheat-panel';
  51. panel.innerHTML = `
  52. <div id="scp-header">
  53. <span>SugarCube Cheat Panel</span>
  54. <span id="scp-toggle">–</span>
  55. </div>
  56. <div id="scp-content">
  57. <div class="scp-field">
  58. <label for="varName">Variable:</label>
  59. <input type="text" id="varName" placeholder="Enter variable" list="varSuggestions">
  60. <datalist id="varSuggestions"></datalist>
  61. </div>
  62. <div class="scp-field">
  63. <label for="varValue">Value:</label>
  64. <input type="text" id="varValue" placeholder="Enter value">
  65. </div>
  66. <button id="setVar">Set Variable</button>
  67. </div>
  68. `;
  69. document.body.appendChild(panel);
  70.  
  71. makeDraggable(panel, document.getElementById('scp-header'));
  72.  
  73. document.getElementById('scp-toggle').addEventListener('click', function(e) {
  74. e.stopPropagation();
  75. let content = document.getElementById('scp-content');
  76. if (content.style.display === 'none') {
  77. content.style.display = 'block';
  78. this.textContent = '–';
  79. } else {
  80. content.style.display = 'none';
  81. this.textContent = '+';
  82. }
  83. });
  84.  
  85. const varNameInput = document.getElementById('varName');
  86. varNameInput.addEventListener('focus', updateSuggestions);
  87.  
  88. varNameInput.addEventListener('change', function() {
  89. let varName = this.value;
  90. const varValueInput = document.getElementById('varValue');
  91. if (checkSugarCube() && SugarCube.State.variables.hasOwnProperty(varName)) {
  92. varValueInput.value = SugarCube.State.variables[varName];
  93. } else {
  94. varValueInput.value = '';
  95. }
  96. });
  97.  
  98. document.getElementById("setVar").addEventListener("click", function() {
  99. let varName = document.getElementById("varName").value;
  100. let varValue = document.getElementById("varValue").value;
  101. setVariable(varName, isNaN(varValue) ? varValue : Number(varValue));
  102. });
  103. }
  104.  
  105. function makeDraggable(el, handle) {
  106. handle.style.cursor = 'move';
  107. let posX = 0, posY = 0, mouseX = 0, mouseY = 0;
  108. handle.addEventListener('mousedown', dragMouseDown);
  109.  
  110. function dragMouseDown(e) {
  111. e.preventDefault();
  112. mouseX = e.clientX;
  113. mouseY = e.clientY;
  114. document.addEventListener('mousemove', elementDrag);
  115. document.addEventListener('mouseup', closeDragElement);
  116. }
  117.  
  118. function elementDrag(e) {
  119. e.preventDefault();
  120. posX = mouseX - e.clientX;
  121. posY = mouseY - e.clientY;
  122. mouseX = e.clientX;
  123. mouseY = e.clientY;
  124. el.style.top = (el.offsetTop - posY) + "px";
  125. el.style.left = (el.offsetLeft - posX) + "px";
  126. }
  127.  
  128. function closeDragElement() {
  129. document.removeEventListener('mousemove', elementDrag);
  130. document.removeEventListener('mouseup', closeDragElement);
  131. }
  132. }
  133.  
  134. function addCustomCSS() {
  135. const css = `
  136. #sugarcube-cheat-panel {
  137. position: fixed;
  138. top: 10px;
  139. right: 10px;
  140. background: #2e2e2e;
  141. color: #e0e0e0;
  142. border: 1px solid #444;
  143. border-radius: 8px;
  144. z-index: 10000;
  145. width: 310px;
  146. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
  147. font-family: Arial, sans-serif;
  148. }
  149. #scp-header {
  150. padding: 10px;
  151. background: #3a3a3a;
  152. border-top-left-radius: 8px;
  153. border-top-right-radius: 8px;
  154. font-weight: bold;
  155. display: flex;
  156. justify-content: space-between;
  157. align-items: center;
  158. user-select: none;
  159. }
  160. #scp-content {
  161. padding: 10px;
  162. }
  163. .scp-field {
  164. margin-bottom: 10px;
  165. }
  166. .scp-field label {
  167. display: block;
  168. margin-bottom: 4px;
  169. font-size: 0.9em;
  170. }
  171. .scp-field input {
  172. padding: 6px;
  173. border: 1px solid #555;
  174. border-radius: 4px;
  175. background: #444;
  176. color: #e0e0e0;
  177. box-sizing: border-box;
  178. }
  179. #setVar {
  180. width: 100%;
  181. padding: 8px;
  182. border: none;
  183. border-radius: 4px;
  184. background: #5a5a5a;
  185. color: #e0e0e0;
  186. cursor: pointer;
  187. font-size: 1em;
  188. }
  189. #setVar:hover {
  190. background: #6a6a6a;
  191. }
  192. #scp-toggle {
  193. cursor: pointer;
  194. padding: 5px 10px;
  195. display: inline-block;
  196. text-align: center;
  197. font-size: 1.2em;
  198. user-select: none;
  199. }
  200. #scp-toggle:hover {
  201. background: rgba(255, 255, 255, 0.1);
  202. border-radius: 4px;
  203. }
  204. `;
  205. let style = document.createElement('style');
  206. style.type = 'text/css';
  207. style.appendChild(document.createTextNode(css));
  208. document.head.appendChild(style);
  209. }
  210.  
  211. setTimeout(function() {
  212. if (checkSugarCube()) {
  213. addCustomCSS();
  214. createUI();
  215. } else {
  216. console.log("SugarCube not detected or incompatible version. Cheat panel will not be loaded.");
  217. }
  218. }, 3000);
  219.  
  220. })();