SDL evo2

Extension du jeu seduis-les.fr

  1.  
  2. // ==UserScript==
  3. // @name SDL evo2
  4. // @version 0.2
  5. // @license MIT
  6. // @description Extension du jeu seduis-les.fr
  7. // @match *://*.seduis-les.fr/seduire_new.php?scen=*
  8. // @author Un nouveau Khey, qui remercie "Un Khey Sûr"
  9. // @grant none
  10. // @namespace https://greasyfork.org/users/706973
  11. // ==/UserScript==
  12. let script = [];
  13. let path = [];
  14. let playing = false;
  15. let queueStep = false;
  16. const core = {
  17. ready: async () => {
  18. await utils.waitFor(() => {
  19. const coco = document.getElementById("coco");
  20. return coco && coco.style && coco.style["background-image"] && coco.style["background-image"] !== "";
  21. });
  22. },
  23. isGameOver: () => {
  24. const coco = document.getElementById("coco");
  25. return coco.style["background-image"].includes("go.jpg");
  26. },
  27. getGame: () => {
  28. const title = document.querySelector("body > div:nth-child(7) > table > tbody > tr > td > table:nth-child(4) > tbody > tr:nth-child(1) > td:nth-child(2)").innerHTML.split(":")[1].trim();
  29. const question = document.querySelector("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table.style7 > tbody > tr > td").innerText.trim();
  30. const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
  31. let answers = [];
  32. let str = question;
  33. for (let elem of table) {
  34. answers.push(elem.innerText.trim());
  35. }
  36. answers = answers.sort();
  37. for (let answer of answers) {
  38. str += answer;
  39. }
  40. answers = answers.sort();
  41. return {
  42. title,
  43. question,
  44. answers,
  45. hash: utils.hashCode(str)
  46. }
  47. },
  48. getPath: () => {
  49. return path;
  50. },
  51. play: () => {
  52. playing = true;
  53. core.processScript(core.getGame());
  54. },
  55. stop: () => {
  56. queueStep = false;
  57. playing = false;
  58. },
  59. step: () => {
  60. queueStep = true;
  61. core.processScript(core.getGame());
  62. },
  63. processScript: (game) => {
  64. let answer = null;
  65. let i = 0;
  66. for (let entry of script) {
  67. i++;
  68. if (!entry.h || !entry.r || !entry.q) {
  69. alert("invalid line " + i);
  70. return;
  71. }
  72. if (entry.h === game.hash && entry.q === game.question) {
  73. answer = entry.r;
  74. break;
  75. }
  76. }
  77. const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
  78. for (let elem of table) {
  79. if (answer && elem.innerText.trim() === answer) {
  80. elem.style["color"] = "green";
  81. elem.style["font-weight"] = "bold";
  82. } else {
  83. elem.style["color"] = "black";
  84. elem.style["font-weight"] = "normal";
  85. }
  86. }
  87. if (!answer) {
  88. core.stop();
  89. const play = document.getElementById("sdl-play");
  90. const pause = document.getElementById("sdl-pause");
  91. play.style["display"] = "inline-block";
  92. pause.style["display"] = "none";
  93. return;
  94. };
  95. if (!playing && !queueStep) return;
  96. else if (queueStep) queueStep = false;
  97. core.choose(answer);
  98. },
  99. hook: () => {
  100. const original = window.showText;
  101. window.showText = async (nb, sco, com, scen) => {
  102. const prevGame = core.getGame();
  103. path.push({
  104. q: prevGame.question,
  105. r: core.getAnswer(nb, sco, com, scen),
  106. h: prevGame.hash,
  107. });
  108. original(nb, sco, com, scen);
  109. let game;
  110. while ((game = core.getGame()).hash === prevGame.hash)
  111. await utils.sleep(10);
  112. if (!core.isGameOver()) {
  113. core.processScript(game);
  114. }
  115. };
  116. },
  117. setScript: (json) => {
  118. script = json;
  119. core.processScript(core.getGame());
  120. },
  121. getAnswer: (nb, sco, com, scen) => {
  122. const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
  123. for (let elem of table) {
  124. const args = /[^\(]+\(([^\)]+)\)/.exec(elem.getAttribute("onclick"))[1].split(",").map(a => parseInt(a));
  125. if (args[0] == nb && args[1] == sco && args[2] == com && args[3] == scen)
  126. return elem.innerText.trim();
  127. }
  128. return null;
  129. },
  130. getArgs: (answer) => {
  131. const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
  132. for (let elem of table) {
  133. if (elem.innerText.trim() === answer)
  134. return /[^\(]+\(([^\)]+)\)/.exec(elem.getAttribute("onclick"))[1].split(",").map(a => parseInt(a));
  135. }
  136. return null;
  137. },
  138. choose: (answer) => {
  139. const args = core.getArgs(answer);
  140. if (args === null) {
  141. console.log("can't find arguments for '" + answer + "'");
  142. return;
  143. }
  144. window.showText.apply(null, args);
  145. }
  146. }
  147. const gui = {
  148. saveJSON: (data, filename) => {
  149. if (!data) {
  150. console.error("No data")
  151. return;
  152. }
  153. if (typeof data === "object") {
  154. data = JSON.stringify(data, undefined, 4)
  155. }
  156. var blob = new Blob([data], {
  157. type: "text/json"
  158. }),
  159. e = document.createEvent("MouseEvents"),
  160. a = document.createElement("a")
  161. a.download = filename
  162. a.href = window.URL.createObjectURL(blob);
  163. a.dataset.downloadurl = ["text/json", a.download, a.href].join(':')
  164. e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
  165. a.dispatchEvent(e)
  166. },
  167. init: () => {
  168. const parent = document.querySelector("body > div:nth-child(7) > table > tbody > tr > td > table:nth-child(4) > tbody > tr:nth-child(2) > td:nth-child(2)");
  169. parent.align = "left";
  170. parent.style["padding-bottom"] = "5px";
  171. document.head.innerHTML += `
  172. <style>
  173. #sdl {
  174. padding: 2px;
  175. vertical-align: middle;
  176. }
  177. #sdl button {
  178. cursor: pointer;
  179. margin-right: 3px;
  180. margin: 0;
  181. font-size: 18px;
  182. }
  183. #sdl-player {
  184. vertical-align: middle;
  185. margin-left: 10px;
  186. }
  187. #sdl-pcontainer {
  188. height: 30px;
  189. vertical-align: middle;
  190. }
  191. #sdl-pcontainer > p {
  192. margin: 0;
  193. padding: 0;
  194. margin-right: 5px;
  195. }
  196. #sdl-player, #sdl-player > * {
  197. display: inline-block;
  198. }
  199. #sdl-unload, #sdl-player, #sdl-file, #sdl-pause {
  200. display: none;
  201. }
  202. </style>
  203. `
  204. parent.innerHTML = `
  205. <div id="sdl">
  206. <button id="sdl-save" title="exporter la progression en fichier script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-arrow-down-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm2.354 6.854l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 1 1 .708-.708L7.5 9.293V5.5a.5.5 0 0 1 1 0v3.793l1.146-1.147a.5.5 0 0 1 .708.708z"/></svg></button>
  207. <button id="sdl-load" title="importer un fichier script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-arrow-up-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm2.354 5.146l-2-2a.5.5 0 0 0-.708 0l-2 2a.5.5 0 1 0 .708.708L7.5 6.707V10.5a.5.5 0 0 0 1 0V6.707l1.146 1.147a.5.5 0 0 0 .708-.708z"/></svg></button>
  208. <button id="sdl-unload" title="decharger le script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-slash" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M3.112 5.112a3.125 3.125 0 0 0-.17.613C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13H11l-1-1H3.781C2.231 12 1 10.785 1 9.318c0-1.365 1.064-2.513 2.46-2.666l.446-.05v-.447c0-.075.006-.152.018-.231l-.812-.812zm2.55-1.45l-.725-.725A5.512 5.512 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773a3.2 3.2 0 0 1-1.516 2.711l-.733-.733C14.498 11.378 15 10.626 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3c-.875 0-1.678.26-2.339.661zm7.984 10.692l-12-12 .708-.708 12 12-.707.707z"/></svg></button>
  209. <div id="sdl-player">
  210. <div id="sdl-pcontainer"><p id="sdl-script">sdl_scene2.json</p></div>
  211. <button id="sdl-play" title="jouer tout"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-play-fill" fill="currentColor"><path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/></svg></button>
  212. <button id="sdl-pause" title="arrêter"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pause-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/></svg></button>
  213. <button id="sdl-step" title="jouer une étape"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-skip-end-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M12 3.5a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5z"/> <path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/></svg></button>
  214. </div>
  215. <input id="sdl-file" type="file" accept=".json" />
  216. </div>
  217. `;
  218. const reader = new FileReader();
  219. const scriptLabel = document.getElementById("sdl-script");
  220. const player = document.getElementById("sdl-player");
  221. const file = document.getElementById("sdl-file");
  222. const load = document.getElementById("sdl-load");
  223. const unload = document.getElementById("sdl-unload");
  224. const save = document.getElementById("sdl-save");
  225. const play = document.getElementById("sdl-play");
  226. const pause = document.getElementById("sdl-pause");
  227. const step = document.getElementById("sdl-step");
  228. reader.onload = e => {
  229. try {
  230. core.setScript(JSON.parse(e.target.result));
  231. const split = file.value.split("\\");
  232. scriptLabel.innerText = split[split.length - 1];
  233. load.style["display"] = "none";
  234. unload.style["display"] = "inline-block";
  235. player.style["display"] = "inline-block";
  236. } catch (e) {
  237. alert("can't parse JSON");
  238. console.error(e);
  239. }
  240. }
  241. file.addEventListener("change", e => {
  242. reader.readAsText(e.target.files[0]);
  243. });
  244. load.addEventListener("click", e => {
  245. file.click();
  246. });
  247. unload.addEventListener("click", e => {
  248. load.style["display"] = "inline-block";
  249. unload.style["display"] = "none";
  250. player.style["display"] = "none";
  251. core.setScript([]);
  252. core.stop();
  253. });
  254. save.addEventListener("click", e => {
  255. gui.saveJSON(core.getPath(), "sdl_" + Math.floor(Date.now() / 1000) + ".json");
  256. });
  257. play.addEventListener("click", e => {
  258. play.style["display"] = "none";
  259. pause.style["display"] = "inline-block";
  260. core.play();
  261. });
  262. pause.addEventListener("click", e => {
  263. play.style["display"] = "inline-block";
  264. pause.style["display"] = "none";
  265. core.stop();
  266. });
  267. step.addEventListener("click", e => {
  268. core.step();
  269. });
  270. }
  271. }
  272. const utils = {
  273. sleep: (ms) => {
  274. return new Promise(resolve => {
  275. setTimeout(() => resolve(), ms);
  276. });
  277. },
  278. waitFor: (fnc) => {
  279. return new Promise(async resolve => {
  280. for (;;) {
  281. if (fnc() === true) {
  282. resolve();
  283. return;
  284. }
  285. await utils.sleep(100);
  286. }
  287. });
  288. },
  289. hashCode: (str) => {
  290. let hash = 0;
  291. if (str.length == 0) return hash;
  292. for (let i = 0; i < str.length; i++) {
  293. let char = str.charCodeAt(i);
  294. hash = ((hash << 5) - hash) + char;
  295. hash = hash & hash;
  296. }
  297. return hash;
  298. }
  299. }
  300. async function run(){
  301. await core.ready();
  302. if (core.isGameOver())
  303. return;
  304. core.hook();
  305. gui.init();
  306. }
  307. run();
  308.