OWOT Toolbox

Useful tools for OWOT.

  1. // ==UserScript==
  2. // @name OWOT Toolbox
  3. // @namespace http://tampermonkey.net/
  4. // @version 2025-07-07
  5. // @description Useful tools for OWOT.
  6. // @author DefunctUser
  7. // @match https://ourworldoftext.com/*
  8. // @match https://*.ourworldoftext.com/*
  9. // @match https://test.ourworldoftext.com/*
  10. // @icon https://ourworldoftext.com/static/favicon.png
  11. // @grant none
  12. // @license GNU GPLv3
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. var version = "1.3.6";
  19. // Toolbox title
  20. menu.addEntry("<h2 style='background: linear-gradient(180deg, red,orange);-webkit-text-fill-color: transparent;-webkit-background-clip: text;background-clip: text;' id='tb-title'>OWOT<br>TOOLBOX</h2><h4>Version " + version + "</h4>")
  21. // Colors & rate-limit detection
  22. menu.addEntry( `${state.worldModel.color_text <= 0 ? "<div style='float: left; margin-left: 5px; margin-top: 6px; display: inline-block; border: 1px solid grey; background-color: #99ff66; width: 16px; height: 16px;'></div><span>Colors allowed</span>'" : "<div style='float: left; margin-left: 5px; margin-top: 6px; display: inline-block; border: 1px solid grey; background-color: #ff5050; width: 16px; height: 16px;''></div><span>Colors disallowed</span>"}`);
  23. /*
  24. if(state.worldModel.color_text>0){alert("WARNING\n========================\nColors are disabled on this world")}
  25. /* // Chars per second detection
  26. if(state.worldModel.char_rate[1]<513){
  27. if(state.worldModel.char_rate[1]<100){
  28. alert("WARNING\n========================\nThis world has a very low characters per second value.\nThis heavily affects all scripts.")
  29. } else {
  30. alert("!!!WARNING!!!\n========================\nThis world has a low characters per second value.\nThis affects all scripts.")
  31. }
  32. }
  33. /*
  34. if(state.worldModel.char_rate[1]>2000){
  35. alert("WARNING\n========================\nThis world has a high rate-limit ("+ state.worldModel.char_rate[0].toString() + " chars per " + state.worldModel.char_rate[1].toString() + "ms" + "). \nScripts will be slow.")
  36. }
  37. */
  38. // Automatic paste permission bypass.
  39. if(state.worldModel.feature_paste>0){
  40. (function(){Permissions.can_paste = function() {return true;};})();
  41. console.log("No pasting detected - Bypassed");
  42. }
  43. menu.addEntry(`<span>Rate limit: <b>${state.worldModel.char_rate[0].toString()} chars per ${state.worldModel.char_rate[1].toString()} ms</b></span>`);
  44. /* Instant Write (previously InstaPaste) v1.1
  45. Supports linebreaks.
  46. */
  47. function instapaste(str,col,loc) {
  48. var scriptloc = loc;
  49. var originalloc = loc;
  50. for(let i=0;i<str.length;i++){
  51. var char = str.charAt(i)
  52. var charsintostring = "-" + i+1
  53. if(char !== "°") {
  54. writeCharTo(char,0x000000,...scriptloc);
  55. scriptloc = coordinateAdd(...scriptloc,0,0,1,0);
  56. } else {
  57. originalloc = coordinateAdd(...originalloc,0,0,0,1)
  58. scriptloc = originalloc;
  59. }
  60. }
  61. }
  62. function aa(){
  63. var kk=prompt("what text to write?\nUse ° for linebreaks :)");
  64. instapaste(kk,0x000000,cursorCoords);
  65. }
  66. menu.addOption("Instant Write",aa)
  67.  
  68. // Fill Script
  69. var fillselection = new RegionSelection();
  70. fillselection.color = 'rgba(255,0,0,0.1)';
  71. fillselection.charColor = '#FF4848';
  72. var fillchar = " ";
  73. var fillcolor = 0x000000;
  74. var fillbcolor = null;
  75. var fillbold = false;
  76. var fillunder = false;
  77. var fillstrike = false;
  78. var fillitalic = false;
  79. var fillbcolorenabled = false;
  80. var filltargetenabled = false;
  81. var filltarget = 0x000000;
  82. // Fill settings modal
  83. // i = input
  84. var modalColorUnchanged = true;
  85. var fillmodal = new Modal();
  86. fillmodal.createForm();
  87. fillmodal.setFormTitle("Fill settings");
  88. // input values are accessed by [variable].input.value
  89. var ifillchar = fillmodal.addEntry("Fill char (leave empty to use it as a wiper)","text");
  90. var ifillcolor = fillmodal.addEntry("Color","color");
  91. var ifillbcolor = fillmodal.addEntry("Background color (if enabled below)","color");
  92. var ifilltarget = fillmodal.addEntry("Fill target (if enabled below)","color");
  93. fillmodal.createCheckboxField();
  94. // checkbox values are accessed by [variable].elm.firstChild.checked
  95. var ifillbold = fillmodal.addCheckbox("Bold text");
  96. var ifillitalic = fillmodal.addCheckbox("Italic text");
  97. var ifillunder = fillmodal.addCheckbox("Underline text");
  98. var ifillstrike = fillmodal.addCheckbox("Strikethrough text");
  99. var ifillbcolorenabled = fillmodal.addCheckbox("Enable background color");
  100. var ifilltargetenabled = fillmodal.addCheckbox("Enable fill target. If enabled, you can set the fill target to a color and only the chars with that color will get filled. Useful for erasing spam while keeping everything else intact.");
  101.  
  102. fillmodal.onOpen(function(){
  103. if(modalColorUnchanged) {
  104. ifillcolor.input.value = "000000";
  105. }
  106. });
  107. fillmodal.onSubmit(function(){
  108. if(ifillcolor.input.value !== "000000"){
  109. modalColorUnchanged = false;
  110. }
  111. fillchar = ifillchar.input.value.charAt(0); // only the first char will be saved
  112. if(fillchar == ""){
  113. fillchar = " ";
  114. };
  115. filltargetenabled = ifilltargetenabled.elm.firstChild.checked;
  116.  
  117. if(filltargetenabled == true){
  118. filltarget = parseInt(ifilltarget.input.value,16);
  119. };
  120. // 0x must be added so it is treated as a hex value because for some fucking reason the value from the input doesn't have that at the start
  121. if(ifillbcolorenabled.elm.firstChild.checked == true){
  122. fillbcolor = "0x" + ifillbcolor.input.value;
  123. } else {
  124. fillbcolor = null;
  125. };
  126. fillcolor = "0x" + ifillcolor.input.value;
  127. fillbold = ifillbold.elm.firstChild.checked;
  128. fillunder = ifillunder.elm.firstChild.checked;
  129. fillstrike = ifillstrike.elm.firstChild.checked;
  130. fillitalic = ifillitalic.elm.firstChild.checked;
  131. });
  132. // Main fill function
  133. fillselection.tiled = false;
  134. fillselection.onselection(function(coordA, coordB, regWidth, regHeight) {
  135. var charCoord = coordA;
  136. for(let yy = 0; yy < regHeight; yy++) {
  137. for(let xx = 0; xx < regWidth; xx++) {
  138. var charCol = getCharInfo(...charCoord).color;
  139. if(filltargetenabled == true){ // Target mode
  140. if(charCol == parseInt(filltarget,10)){
  141. writeCharTo(fillchar,fillcolor,...charCoord,true,true,fillbcolor,fillbold,fillitalic,fillunder,fillstrike);
  142. }
  143. } else if(fillchar == " " && fillbcolor === null) { // Wiping
  144. var charSymbol = getCharInfo(...charCoord).char
  145. var charBcol = getCharInfo(...charCoord).bgColor
  146. if(charSymbol !== " " || charBcol !== -1) { // Ignore empty chars to optimize wiping
  147. writeCharTo(fillchar,fillcolor,...charCoord,true,true,fillbcolor,fillbold,fillitalic,fillunder,fillstrike);
  148. }
  149. } else { // Filling
  150. writeCharTo(fillchar,fillcolor,...charCoord,true,true,fillbcolor,fillbold,fillitalic,fillunder,fillstrike);
  151. }
  152. charCoord = coordinateAdd(...charCoord,0,0,1,0);
  153. }
  154. charCoord = coordinateAdd(...charCoord,0,0,-regWidth,1);
  155. }
  156. });
  157. w.on("keyDown", function(e) {
  158. if(checkKeyPress(e, "ALT+F")) {
  159. fillselection.startSelection();
  160. }
  161. });
  162. // Menu buttons
  163. menu.addOption("Fill Area\n(ALT+F)",function(){fillselection.startSelection();});
  164. menu.addCheckboxOption("Fill Tiles",function(){fillselection.tiled = true;},function(){fillselection.tiled = false;},false);
  165. menu.addOption("Fill Settings",function(){fillmodal.open();});
  166.  
  167. // Stickman Script
  168. // Variable setup
  169. var col = 0x000000;
  170. var col_h = col;
  171. var col_la = col;
  172. var col_ra = col;
  173. var col_ll = col;
  174. var col_rl = col;
  175. var col_body = col;
  176. var loc = [];
  177. // Modals setup
  178. // Limb colors modal
  179. const colormodal2 = new Modal()
  180. colormodal2.createForm()
  181. colormodal2.setFormTitle("Stickman limb colors")
  182. var head = colormodal2.addEntry("Head color","color");
  183. var leftarm = colormodal2.addEntry("Left arm color","color");
  184. var rightarm = colormodal2.addEntry("Right arm color","color");
  185. var body = colormodal2.addEntry("Body color","color");
  186. var leftleg = colormodal2.addEntry("Left leg color","color");
  187. var rightleg = colormodal2.addEntry("Right leg color","color");
  188. colormodal2.onSubmit(function setColors() {
  189. col_h = parseInt(head.input.value,16);
  190. col_la = parseInt(leftarm.input.value,16)
  191. col_ra = parseInt(rightarm.input.value,16)
  192. col_ll = parseInt(leftleg.input.value,16)
  193. col_rl = parseInt(rightleg.input.value,16)
  194. col_body = parseInt(body.input.value,16)
  195. });
  196. // Single color modal
  197. const colormodal = new Modal();
  198. colormodal.createForm();
  199. var stickcolor = colormodal.addEntry("Stickman color","color");
  200. colormodal.setFormTitle("Stickman color. This will override any previously set limb colors.");
  201. colormodal.onSubmit(function setStickCol() {
  202. col = parseInt(stickcolor.input.value,16);
  203. col_h = col;
  204. col_la = col;
  205. col_ra = col;
  206. col_ll = col;
  207. col_rl = col;
  208. col_body = col;
  209. });
  210. col_h = col;
  211. col_la = col;
  212. col_ra = col;
  213. col_ll = col;
  214. col_rl = col;
  215. col_body = col;
  216. // Stickman paster function
  217. function stickman(){
  218. loc = cursorCoords;
  219. writeCharTo("O",col_h,...loc)// Head
  220. loc = coordinateAdd(...loc,0,0,-1,1)
  221. writeCharTo("/",col_la,...loc)// Left arm
  222. loc = coordinateAdd(...loc,0,0,1,0)
  223. writeCharTo("|",col_body,...loc)// Body
  224. loc = coordinateAdd(...loc,0,0,1,0)
  225. writeCharTo('\\',col_ra,...loc)//Right arm
  226. loc = coordinateAdd(...loc,0,0,-2,1)
  227. writeCharTo("/",col_ll,...loc)//Left leg
  228. loc = coordinateAdd(...loc,0,0,2,0)
  229. writeCharTo('\\',col_rl,...loc)//Right leg
  230. }
  231. // Menu options to access the modals
  232. menu.addOption("Add Stickman",()=>{stickman()});
  233. menu.addOption("Set Stickman Color",()=>{
  234. colormodal.open()
  235. });
  236. menu.addOption("Set Limb Colors",()=>{
  237. colormodal2.open()
  238. });
  239.  
  240. w.doAnnounce("OWOT Toolbox Loaded - v" + version + " - Enjoy :)");
  241. })();