Naltrexone's KoL Scripts - WikiLink

Version 2.6

  1. // Naltrexone's KoL Scripts
  2. //
  3. // ==UserScript==
  4. // @name Naltrexone's KoL Scripts - WikiLink
  5. // @namespace http://www.batmantis.com/kol
  6. // @include *kingdomofloathing.com/desc_item.php*
  7. // @include *127.0.0.1:600*/desc_item.php*
  8. // @include *kingdomofloathing.com/desc_familiar.php*
  9. // @include *127.0.0.1:600*/desc_familiar.php*
  10. // @include *kingdomofloathing.com/desc_effect.php*
  11. // @include *127.0.0.1:600*/desc_effect.php*
  12. // @include *kingdomofloathing.com/inventory.php*
  13. // @include *127.0.0.1:600*/inventory.php*
  14. // @include *kingdomofloathing.com/hermit.php*
  15. // @include *127.0.0.1:600*/hermit.php*
  16. // @include *kingdomofloathing.com/store.php*
  17. // @include *127.0.0.1:600*/store.php*
  18. // @include *kingdomofloathing.com/mallstore.php*
  19. // @include *127.0.0.1:600*/mallstore.php*
  20. // @include *kingdomofloathing.com/searchmall.php*
  21. // @include *127.0.0.1:600*/searchmall.php*
  22. // @include *kingdomofloathing.com/galaktik.php*
  23. // @include *127.0.0.1:600*/galaktik.php*
  24. // @include *kingdomofloathing.com/mrstore.php*
  25. // @include *127.0.0.1:600*/mrstore.php*
  26. // @include *kingdomofloathing.com/fight.php*
  27. // @include *127.0.0.1:600*/fight.php*
  28. // @include *kingdomofloathing.com/charpane.php*
  29. // @include *127.0.0.1:600*/charpane.php*
  30. // @include *kingdomofloathing.com/familiar.php*
  31. // @include *127.0.0.1:600*/familiar.php*
  32. // @include *kingdomofloathing.com/adventure.php*
  33. // @include *127.0.0.1:600*/adventure.php*
  34. // @include *kingdomofloathing.com/dungeon.php*
  35. // @include *127.0.0.1:600*/dungeon.php*
  36. // @include *kingdomofloathing.com/campground.php*
  37. // @include *127.0.0.1:600*/campground.php*
  38. // @include *kingdomofloathing.com/shore.php*
  39. // @include *127.0.0.1:600*/shore.php*
  40. // @include *kingdomofloathing.com/council.php*
  41. // @include *127.0.0.1:600*/council.php*
  42. // @include *kingdomofloathing.com/main.php*
  43. // @include *127.0.0.1:600*/main.php*
  44. // @include *kingdomofloathing.com/sewer.php*
  45. // @include *127.0.0.1:600*/sewer.php*
  46. // @include *kingdomofloathing.com/charsheet.php*
  47. // @include *127.0.0.1:600*/charsheet.php*
  48. // @include *kingdomofloathing.com/showplayer.php*
  49. // @include *127.0.0.1:600*/showplayer.php*
  50. // @include *kingdomofloathing.com/displaycollection.php*
  51. // @include *127.0.0.1:600*/displaycollection.php*
  52. // @include *kingdomofloathing.com/rats.php*
  53. // @include *127.0.0.1:600*/rats.php*
  54. // @include *kingdomofloathing.com/restaurant.php*
  55. // @include *127.0.0.1:600*/restaurant.php*
  56. // @description Version 2.6
  57. // @grant GM_getValue
  58. // @grant GM_setValue
  59. // @grant GM_xmlhttpRequest
  60.  
  61. // @version 0.0.1.20140830173008
  62. // ==/UserScript==
  63.  
  64.  
  65. /********************************** Recent Changes **********************************************
  66. Recent Updates:
  67. 2.6 Updated to respect GreaseMonkey 2.0 (or greater) security settings
  68. This is obviously just a first pass to get it back up and working-- will
  69. add support for new pages and item types later this weekend.
  70. 2.5 Avoided conflict with "Down the Rabbit Hole". More fixes coming soon.
  71. 2.4 Internal build
  72. 2.3 Updated the familiar decoder
  73. Avoided some combat messages that shouldn't be wikified.
  74. 2.2 Fixes conflicts with Picklish's scripts
  75. Avoids extraneous tag in the Desktop Globe fight
  76. 2.1 Prevented double-tagging of familiars in Full Mode
  77. 2.0 Added wikification to restaurants and user pages.
  78. Support for kolmafia relay browser (thanks macman104!)
  79. Added wikification to compact mode charpane-- (most of the work done by Picklish (#841340)--Thanks!!)
  80. 1.9 Fixes to the Character Page (correct wikifying of effects and items)
  81. Fixed extraneous linebreak in familiar name on left-hand character pane
  82. 1.8: Fixed line-break in wikified familiar name in charpane.
  83. Handled familiar names with parentheses in them. Yes, really.
  84. Fixes to bad wiki links on charpage when events or results are displayed.
  85. Updates to some patterns for some HTML changes in KoL.
  86. 1.7: Fixed collision with MonsterStats script
  87. Set info box on main page to only show if there's a problem
  88.  
  89.  
  90. ********************************************************************************************/
  91. GM_setValue("scriptVer","2.6");
  92. GM_setValue("scriptName","WikiLink");
  93. GM_setValue("scriptURL","http://batmantis.com/kol/WikiLink.user.js");
  94.  
  95. const wikiWrapperPre = '<font size=1><sup><a tabindex="-1" href="http://kol.coldfront.net/thekolwiki/index.php/';
  96. const wikiWrapperPost = '" TARGET="_blank">w</a></sup></font>&nbsp; ';
  97.  
  98. // Familiars are numbered in KoL-- this is a magic decoder ring going from number to familiar.
  99. // Note that javascript arrays are zero-based and the familiar numbering is one-based, so the first entry is blank.
  100. // Also, Familiar 13 doesn't exist because of Jick's aversion to the number 13.
  101. const familiarDecoder = ["","Mosquito","Leprechaun","Levitating Potato","Angry Goat","Sabre-Toothed Lime","Fuzzy Dice",
  102. "Spooky Pirate Skeleton","Barrrnacle","Howling Balloon Monkey","Stab Bat","Grue","Blood-Faced Volleyball","","Ghuol Whelp",
  103. "Baby Gravy Fairy","Cocoabo","Star Starfish","Hovering Sombrero","Ghost Pickle on a Stick","Killer Bee","Whirling Maple Leaf",
  104. "Coffee Pixie","Cheshire Bat","Jill-O-Lantern","Hand Turkey","Crimbo Elf","Hanukkimbo Dreidl","Baby Yeti","Feather Boa Constrictor","Emo Squid",
  105. "Personal Raincloud","Clockwork Grapefruit","MagiMechTech MicroMechaMech","Flaming Gravy Fairy","Frozen Gravy Fairy",
  106. "Stinky Gravy Fairy","Spooky Gravy Fairy","Inflatable Dodecapede","Pygmy Bugbear Shaman","Doppelshifter","Attention-Deficit Demon",
  107. "Cymbal-Playing Monkey","Temporal Riftlet","Sweet Nutcracker","Pet Rock","Snowy Owl","Teddy Bear","Ninja Pirate Zombie Robot",
  108. "Sleazy Gravy Fairy","Wild Hare","Wind-up Chattering Teeth","Spirit Hobo","Astral Badger","Comma Chameleon","Misshapen Animal Skeleton",
  109. "Scary Death Orb","Jitterbug","Nervous Tick","","Origami Towel Crane","","","Toothsome Rock","","Ancient Yuletide Troll"];
  110. // Rather annoyingly, some familiars can't be identified in the charpane by number or name-- so we remap from image name to familiar.
  111. const familiarImageNameDecoder = [["hat2","Hovering Sombrero"],["sgfairy","Spooky Gravy Fairy"],["npzr","Ninja Pirate Zombie Robot"],
  112. ["slgfairy","Sleazy Gravy Fairy"],["chatteeth","Wind-up Chattering Teeth"],["ghobo","Spirit Hobo"],
  113. ["badger","Astral Badger"],["commacha","Comma Chameleon"],["animskel","Misshapen Animal Skeleton"],["orb","Scary Death Orb"],
  114. ["jitterbug","Jitterbug"],["tick","Nervous Tick"],["crane1","Origami Towel Crane"],["pettoothrock","Toothsome Rock"],
  115. ["crimbotroll","Ancient Yuletide Troll"]];
  116.  
  117. // Some things look like they should be wikified, but shouldn't. Here's a list to check against before applying markup.
  118. const exceptionStrings = [];
  119.  
  120. function wikify(EntryName)
  121. {
  122. return wikiWrapperPre + EntryName + wikiWrapperPost;
  123. }
  124.  
  125. function insertWikiLink(itemElement, wikiEntryName, textToInsertAfter) {
  126. if ((itemElement.tagName == 'A') || (itemElement.tagName == 'IMG') || (itemElement.getAttribute('id') == 'monname')) {
  127. var newElement = document.createElement("span");
  128. newElement.innerHTML = wikify(wikiEntryName);
  129.  
  130. var itemParent = itemElement.parentNode;
  131. if (itemElement.nextSibling){
  132. itemParent.insertBefore(newElement,itemElement.nextSibling);
  133. }
  134. else{
  135. itemParent.appendChild(newElement);
  136. }
  137. }
  138. else {
  139. var insertionPoint = itemElement.innerHTML.indexOf(textToInsertAfter) + textToInsertAfter.length;
  140. var newInnerHTML = itemElement.innerHTML.substring(0, insertionPoint) +
  141. wikify(wikiEntryName) + itemElement.innerHTML.substring(insertionPoint);
  142. itemElement.innerHTML = newInnerHTML;
  143. }
  144. }
  145.  
  146. // Function: imgToFamiliar
  147. // Coded by Picklish
  148. //
  149. // Takes an image link and returns the full familiar name as a string.
  150. // Returns 0 if it can't match.
  151. //
  152. // NOTE: Slight modifications for clarity and compactness made by Numfar
  153.  
  154. function imgToFamiliar(imgLink) {
  155. var imgMatch = imgLink.match(/\/familiar([0-9]+)\.gif$/);
  156. if (imgMatch && imgMatch[0] && parseInt(imgMatch[1]))
  157. {
  158. var familiarName = familiarDecoder[parseInt(imgMatch[1])];
  159. if (familiarName != "") { return familiarName; } else { return 0; }
  160. }
  161. // Not all familiars follow the above pattern.
  162. // I'm not quite sure why in the world that is. -Picklish
  163. imgMatch = imgLink.match(/\/([^\/]*)\.gif$/);
  164. if (!imgMatch || !imgMatch[0] || !imgMatch[1])
  165. {
  166. // Bail out-- this isn't an image of a familiar
  167. // or it's a new pattern we don't recognize.
  168. return 0;
  169. }
  170. for (decoderIndex in familiarImageNameDecoder) {
  171. if (imgMatch[1] == familiarImageNameDecoder[decoderIndex] [0]) { return familiarImageNameDecoder[decoderIndex] [1]; }
  172. }
  173.  
  174. // Okay we've totally struck out. Give up.
  175. return 0;
  176. }
  177.  
  178. function trimString(targetString) {
  179. targetString = targetString.replace( /^\s+/g, "" );
  180. targetString = targetString.replace( /\s+$/g, "" );
  181. return targetString;
  182. }
  183.  
  184. function updateScriptBox() {
  185. //if (needUpdate) {
  186. mainPageBody.innerHTML = addedHTML + '</table></center>' + oldHTML;
  187. // }
  188. // Only displaying the status box if there's a problem. It was annoying people.
  189. // else {
  190. // mainPageBody.innerHTML = oldHTML + addedHTML + '</table></center>';
  191. // }
  192. }
  193.  
  194. function checkForUpdate() {
  195. // If possible, grab the latest version of this script from Batmantis
  196. // and see if it's newer than this version.
  197. GM_xmlhttpRequest({
  198. method: 'GET',
  199. url: GM_getValue("scriptURL"),
  200. headers: {'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey','Accept': 'text/html',},
  201. onload: function(responseDetails) {
  202. if (responseDetails.status == "200") {
  203. var strHTML = responseDetails.responseText;
  204. var newVer = strHTML.match(/description\s*Version \w+\.\w+/);
  205. if (newVer.length > 0) {
  206. newVer[0] = newVer[0].substring(newVer[0].indexOf('Version') + 8);
  207. GM_setValue("scriptWebVer",newVer[0]);
  208. } else {
  209. GM_setValue("scriptWebVer","Error");
  210. }
  211. } else {
  212. GM_setValue("scriptWebVer","Error");
  213. }
  214. }
  215. });
  216. }
  217.  
  218. if (window.location.pathname == "/main.php") {
  219. checkForUpdate();
  220. var needUpdate = ((GM_getValue("scriptWebVer","Error") != "Error") && ((GM_getValue("scriptWebVer")+0.0) > (GM_getValue("scriptVer") + 0.0)));
  221. if (needUpdate) {
  222. var boxColor = 'red';
  223. } else {
  224. var boxColor = 'blue';
  225. }
  226. var mainPageBody= document.getElementsByTagName("body")[0];
  227. var oldHTML = mainPageBody.innerHTML;
  228. var addedHTML = '<center><table style="border: 1px solid ' + boxColor + '; margin-bottom: 4px;" width=95% cellpadding=1 cellspacing=0>' +
  229. '<tr><td bgcolor=' + boxColor + '><font color=white size=-2><b>' + GM_getValue("scriptName") + '</b> Script ' + GM_getValue("scriptVer") + ':</font></td></tr>' +
  230. '<tr><td><font size=-2>&nbsp;&#42;&nbsp;Installed and active.</font></td></tr>';
  231. if (GM_getValue("scriptWebVer","Error") == "Error") {
  232. addedHTML = addedHTML + '<tr><td><font size=-2>&nbsp;&#42;&nbsp;Failed to check website for updated version of script.</font></td></tr>';
  233. mainPageBody.innerHTML = oldHTML + addedHTML + '</table></center>';
  234. } else {
  235. if (needUpdate) {
  236. addedHTML = addedHTML + '<tr><td><font size=-2>&nbsp;&#42;&nbsp;Checked website-- script is out-of-date. Click <a href="' + GM_getValue("scriptURL") + '" TARGET="_blank">here</a> for Version ' + GM_getValue("scriptWebVer") + '</font></td></tr>';
  237. updateScriptBox();
  238. } else {
  239. addedHTML = addedHTML + '<tr><td><font size=-2>&nbsp;&#42;&nbsp;Checked website-- script is latest version.</font></td></tr>';
  240. //updateScriptBox();
  241. }
  242. }
  243. }
  244. /*
  245. ****Charpane Handler****
  246. ------------------------
  247. The charpane appears on the left and displays the player's current familiar and any
  248. effects that are active. So we identify those elements and wikify them. Support for
  249. compact mode added by Picklish. (Thanks!)
  250. */
  251. if (window.location.pathname == "/charpane.php") {
  252. // Track whether we've already labeled the familiar so we don't double tag it in Full Mode
  253. var familiarTagged = 0;
  254. // Both effects and familiars are helpfully wrapped in font tags, so loop through those
  255. // to find them.
  256. var fontElements = document.getElementsByTagName("font");
  257. for (var i=0; i < fontElements.length; i++ ) {
  258. curFontElement = document.getElementsByTagName("font")[i];
  259. // If it has a '(' in it, it's an effect (as the remaining adventures are stored
  260. // after the effect in parens.
  261. if ((curFontElement.innerHTML.indexOf('(') != -1) &&
  262. (curFontElement.innerHTML.indexOf('cellpadding') == -1) &&
  263. (curFontElement.innerHTML.indexOf('mainpane') == -1)) {
  264. var turnsLeft= curFontElement.innerHTML.substring(curFontElement.innerHTML.indexOf('(')+1,
  265. curFontElement.innerHTML.indexOf(')'));
  266. if (("" + parseInt(turnsLeft)) == turnsLeft) {
  267. var EffectName = curFontElement.innerHTML.substring(0,curFontElement.innerHTML.indexOf('(')-1);
  268. insertWikiLink(curFontElement, EffectName, EffectName);
  269. }
  270. }
  271. // If it contains a '-pound' it's a familiar (ex: 17-pound Baby Gravy Fairy). So
  272. // just tack a wiki link onto the end of that.
  273. if (curFontElement.innerHTML.indexOf('-pound') != -1) {
  274.  
  275. var FamiliarName = curFontElement.innerHTML.substring(curFontElement.innerHTML.indexOf('-pound')+7);
  276. if (FamiliarName.indexOf('<') > 0) { FamiliarName = FamiliarName.substring(0,FamiliarName.indexOf('<')); } // Handle non fully-leveled-up familiars
  277. var curBody = document.getElementsByTagName("body")[0];
  278. curBody.innerHTML = curBody.innerHTML.substring(0,curBody.innerHTML.indexOf(FamiliarName) + FamiliarName.length) +
  279. wikiWrapperPre + FamiliarName + wikiWrapperPost +
  280. curBody.innerHTML.substring(curBody.innerHTML.indexOf(FamiliarName) + FamiliarName.length);
  281. familiarTagged = 1;
  282. }
  283. }
  284. // Now handle compact mode, if that's what we're dealing with...
  285. var imgElements = document.getElementsByTagName("img");
  286.  
  287. for (var i=0; i < imgElements.length; i++) {
  288. curImgElement = imgElements[i];
  289.  
  290. var imgOnClick = curImgElement.getAttribute('onClick');
  291. var imgTitle = curImgElement.getAttribute('title');
  292.  
  293. // If the image has a title and an onclick effect, then it's an effect
  294. if (imgTitle && imgOnClick && imgOnClick.indexOf('eff') != -1)
  295. {
  296. insertWikiLink(curImgElement, imgTitle, imgTitle);
  297. }
  298. else
  299. {
  300. var imgSrc = curImgElement.getAttribute("src");
  301. if (!imgSrc)
  302. {
  303. continue;
  304. }
  305. var famName = imgToFamiliar(imgSrc);
  306. if (famName)
  307. {
  308. // img is wrapped in a link to the familiar page, so
  309. // we should wikify after the parent to avoid weirdness
  310. // Also, only tag it if it hasn't previously been tagged
  311. // (to prevent double tagging in Full Mode)
  312. if (familiarTagged == 0) {
  313. insertWikiLink(curImgElement.parentNode, famName, famName);
  314. }
  315. }
  316. }
  317. }
  318. }
  319. /*
  320. ****Character Sheet Page Handler****
  321. ------------------------
  322. Follows none of the rules of a standard page.
  323. Special cases for all of it.
  324. */
  325. if (window.location.pathname == "/charsheet.php") {
  326. var tableRowElements = document.getElementsByTagName("tr");
  327. var startElement = 3;
  328. if ((document.getElementsByTagName("body")[0].innerHTML.indexOf('Results:') != -1) ||
  329. (document.getElementsByTagName("body")[0].innerHTML.indexOf('New Events:') != -1)) {
  330. startElement = 7;
  331. }
  332. for (var i=startElement; i < tableRowElements.length; i++ ) {
  333. curTableRow = tableRowElements[i];
  334. //Special case handle each row that matters:
  335. if ((curTableRow.innerHTML.indexOf('Favorite Food:') > 0) ||
  336. (curTableRow.innerHTML.indexOf('Favorite Booze:') > 0) ||
  337. (curTableRow.innerHTML.indexOf('whichitem') > 0)) {
  338. var elementToWikify = curTableRow.getElementsByTagName("b")[0];
  339. var itemName = elementToWikify.innerHTML;
  340. insertWikiLink(elementToWikify, itemName, itemName);
  341. }
  342. if (curTableRow.innerHTML.indexOf('Sign:') > 0) {
  343. var elementToWikify = curTableRow.getElementsByTagName("b")[0];
  344. var itemName = elementToWikify.innerHTML.substring(elementToWikify.innerHTML.indexOf('The ') + 4);
  345. insertWikiLink(elementToWikify, itemName, itemName);
  346. }
  347. if (curTableRow.innerHTML.indexOf('eff(') != -1) {
  348. var elementToWikify = curTableRow;
  349. var itemName = elementToWikify.innerHTML.substring(elementToWikify.innerHTML.indexOf('<td valign=')+1);
  350. itemName = itemName.substring(itemName.indexOf('>')+1);
  351. itemName = itemName.substring(0,itemName.indexOf('(')-1);
  352. insertWikiLink(elementToWikify, itemName, itemName);
  353. }
  354. if (curTableRow.innerHTML.indexOf('descitem(') != -1) {
  355. var itemCell = curTableRow.getElementsByTagName("td")[1];
  356. var itemElement = itemCell.getElementsByTagName("b")[0];
  357. var itemName = itemElement.innerHTML;
  358. insertWikiLink(itemElement, itemName, itemName);
  359. }
  360. if (curTableRow.innerHTML.indexOf(':skill') > 0) {
  361. var elementsToWikify = curTableRow.getElementsByTagName("a");
  362. for (var j=0; j < elementsToWikify.length; j = j + 2) {
  363. var itemName = elementsToWikify[j].innerHTML;
  364. if (itemName.indexOf('(') > 0) { itemName = itemName.substring(0,itemName.indexOf('(')-1); }
  365. insertWikiLink(elementsToWikify[j], itemName, itemName);
  366. }
  367. }
  368. if (curTableRow.innerHTML.indexOf('familiar.php') > 0) {
  369. var elementsToWikify = curTableRow.getElementsByTagName("td");
  370. var familiarName = elementsToWikify[1].innerHTML;
  371. familiarName = familiarName.substring(familiarName.indexOf('-pound ') + 7);
  372. if (familiarName.indexOf('(') > 0) { familiarName = familiarName.substring(0,familiarName.indexOf('(')-1); }
  373. insertWikiLink(elementsToWikify[1], familiarName, familiarName);
  374. }
  375. }
  376. }
  377. if (window.location.pathname == "/showplayer.php") {
  378. var tableRowElements = document.getElementsByTagName("tr");
  379. var startElement = 3;
  380. if ((document.getElementsByTagName("body")[0].innerHTML.indexOf('Results:') != -1) ||
  381. (document.getElementsByTagName("body")[0].innerHTML.indexOf('New Events:') != -1)) {
  382. startElement = 7;
  383. }
  384. for (var i=startElement; i < tableRowElements.length; i++ ) {
  385. curTableRow = tableRowElements[i];
  386. if ((curTableRow.innerHTML.indexOf('descitem(') != -1) &&
  387. (curTableRow.innerHTML.indexOf('showfamiliars') == -1)) {
  388. var itemCell = curTableRow.getElementsByTagName("td")[1];
  389. var itemElement = itemCell.getElementsByTagName("b")[0];
  390. if (itemElement) {
  391. var itemName = itemElement.innerHTML;
  392. insertWikiLink(itemElement, itemName, itemName);
  393. }
  394. }
  395. if ((curTableRow.innerHTML.indexOf('Favorite Food:') > 0) ||
  396. (curTableRow.innerHTML.indexOf('Favorite Booze:') > 0) ||
  397. (curTableRow.innerHTML.indexOf('whichitem') > 0)) {
  398. var elementToWikify = curTableRow.getElementsByTagName("td")[1];
  399. var itemName = elementToWikify.innerHTML;
  400. insertWikiLink(elementToWikify, itemName, itemName);
  401. }
  402. }
  403. }
  404. /*
  405. ****Display Case Page Handler****
  406. ------------------------
  407. Only wikify items. Easy...
  408. */
  409. if (window.location.pathname == "/displaycollection.php") {
  410. var tableElements = document.getElementsByTagName("tr");
  411. for (var i=3; i < tableElements.length; i++ ) {
  412. if (tableElements[i].innerHTML.indexOf('<tr') < 0) {
  413. curTableElement = tableElements[i];
  414. if (curTableElement.innerHTML.indexOf('whichitem') > 0) {
  415. var elementToWikify = curTableElement.getElementsByTagName("b")[0];
  416. var itemName = elementToWikify.innerHTML;
  417. insertWikiLink(elementToWikify, itemName, itemName);
  418. }
  419. }
  420. }
  421. }
  422. /*
  423. ****Effect Description Page Handler****
  424. ------------------------
  425. The description window that pops up to describe effects
  426. is structurally different from the ones that pop up to
  427. describe familiars and items. So we handle is separately.
  428. Notably, the bit we use to find the effect name is probably
  429. the item most likely to break if anything in KoL changes.
  430. */
  431. if (window.location.pathname == "/desc_effect.php") {
  432. if (document.getElementsByTagName("center").length > 0) {
  433. var EffectName = document.getElementsByTagName("center")[0].innerHTML;
  434. EffectName = EffectName.substring(EffectName.indexOf('>')+1);
  435. EffectName = EffectName.substring(0,EffectName.indexOf('<'));
  436. insertWikiLink(document.getElementsByTagName("body")[0], EffectName, EffectName);
  437. }
  438. }
  439. /*
  440. ****Fight Page Handler****
  441. ------------------------
  442. Remarkably and quite differently from most other pages,
  443. some bits of this page are marked up quite nicely. The
  444. monster name, for example is helpfully tagged with a
  445. span with a unique ID.
  446. */
  447. if (window.location.pathname == "/fight.php") {
  448. var MonsterName = document.getElementById('monname').innerHTML;
  449. MonsterName = MonsterName.substring(MonsterName.indexOf(' ')+1);
  450. if (MonsterName.indexOf('<') > 0) { MonsterName = MonsterName.substring(0,MonsterName.indexOf('<')); }
  451. MonsterName = trimString(MonsterName);
  452.  
  453. insertWikiLink(document.getElementsByTagName("span")[0], MonsterName, MonsterName);
  454. }
  455. /*
  456. ****Daily Dungeon Page Handler****
  457. ------------------------
  458. Because you can opt-in and opt-out of adventures in the
  459. Daily Dungeon, the page is different. So we have to
  460. special-case it.
  461. */
  462. if (window.location.pathname == "/dungeon.php") {
  463. var itemElements = document.getElementsByTagName("b");
  464. for (var i=0; i < itemElements.length; i++ ) {
  465. var curElement = itemElements[i];
  466. if (curElement.innerHTML.indexOf('Room 3') == 0) { insertWikiLink(document.getElementsByTagName("b")[i], 'Room_3', 'Room 3'); }
  467. else if (curElement.innerHTML.indexOf('Room 6') == 0) { insertWikiLink(document.getElementsByTagName("b")[i], 'Room_6', 'Room 6'); }
  468. else if (curElement.innerHTML.indexOf('Room 10') == 0) { insertWikiLink(document.getElementsByTagName("b")[i], 'Room_10', 'Room 10'); }
  469. else if ((curElement.innerHTML.indexOf('Room ') == 0) && (curElement.innerHTML.indexOf('!') < 0)) {
  470. var RoomName = curElement.innerHTML.substring(curElement.innerHTML.indexOf(':') + 1);
  471.  
  472. insertWikiLink(document.getElementsByTagName("b")[i], RoomName, RoomName);
  473. }
  474. }
  475. }
  476. /*
  477. ****Familiars Page Handler****
  478. ------------------------
  479. Anything between a "-pound" and a "(" is
  480. a familiar type. Piece-of-cake.
  481. */
  482. if (window.location.pathname == "/familiar.php") {
  483.  
  484. var familiarElements = document.getElementsByTagName("td");
  485. // This page includes nested tables, which means looping on the
  486. // TD element will cause us to process some entries multiple times.
  487. // So depending on whether it's the default or result version of
  488. // the page, skip past those outer TDs.
  489. var StartElement = 2;
  490. // If you don't have any familiar equipment, the page is structured differently
  491. if (document.getElementsByTagName("body")[0].innerHTML.indexOf('Familiar Equipment:') < 0) {
  492. StartElement = StartElement + 2;
  493. }
  494. if (document.getElementsByTagName("body")[0].innerHTML.indexOf('Results:') > 0) {
  495. StartElement = StartElement + 4;
  496. }
  497. for (var i= StartElement; i < familiarElements.length; i++ ) {
  498. var curFamiliar = document.getElementsByTagName("td")[i];
  499. if ((curFamiliar.innerHTML.indexOf('-pound') > 0)) {
  500. var curFamiliarName = curFamiliar.innerHTML.substring(curFamiliar.innerHTML.indexOf('-pound')+7);
  501. curFamiliarName = curFamiliarName.substring(0,curFamiliarName.indexOf('(')-1);
  502. insertWikiLink(document.getElementsByTagName("td")[i], curFamiliarName, curFamiliarName);
  503. }
  504. }
  505. }
  506.  
  507. // Handle the restaurant pages.
  508. // Basically any lowest-level TD that contains a 'Meat)' is an
  509. // item for sale. Grab everything before the price and wikify it.
  510. if (window.location.pathname == "/restaurant.php") {
  511. var itemElements = document.getElementsByTagName("td");
  512. for (var i=0; i < itemElements.length; i++ ) {
  513. if (
  514. (itemElements[i].innerHTML.indexOf('<') == -1) && // not an outer wrapper
  515. ((itemElements[i].innerHTML.indexOf('Meat)') != -1) ||
  516. (itemElements[i].innerHTML.indexOf('meat)') != -1))
  517. ) {
  518. // Grab everything before the price and treat that as the item name
  519. var itemToWikify = itemElements[i].innerHTML.substring(0,itemElements[i].innerHTML.indexOf('(')-1);
  520. insertWikiLink(itemElements[i], itemToWikify, itemToWikify);
  521. }
  522. }
  523. }
  524. /*
  525. ****General "Items" Handler****
  526. ------------------------
  527. With startling regularity, most things
  528. that are bolded are items. And the rules
  529. for exceptions are mostly straightforward
  530. and are documented below.
  531. */
  532. if ((window.location.pathname != "/charpane.php") &&
  533. (window.location.pathname != "/familiar.php") &&
  534. (window.location.pathname != "/main.php") &&
  535. (window.location.pathname != "/charsheet.php") &&
  536. (window.location.pathname != "/displaycollection.php") &&
  537. (window.location.pathname != "/showplayer.php")
  538. ) { // Some KoL pages don't follow the "bolded items" standard, so don't trigger for those.
  539.  
  540. var itemElements = document.getElementsByTagName("b");
  541. for (var i=0; i < itemElements.length; i++ ) {
  542. curItem = document.getElementsByTagName("b")[i];
  543. // Handle Intrinsic Effect
  544. if (curItem.innerHTML.indexOf('Intrinsic effect:') >= 0) {
  545. var IntrinsicName = curItem.innerHTML.substring(
  546. curItem.innerHTML.indexOf('Intrinsic effect:') + 17);
  547. IntrinsicName = IntrinsicName.substring(0,IntrinsicName.indexOf('<br>'));
  548. insertWikiLink(curItem, IntrinsicName, IntrinsicName);
  549. }
  550. // There are a couple of elements that get bolded that aren't really *things* as such and are ignored.
  551. // (Most) category headers have ':' chars after them.
  552. // Pricing indicators are sometimes bolded but appear to always end in 'Meat.'
  553. // Combat messages have plenty of bangs(!) in them.
  554. if (((curItem.innerHTML.indexOf(':') < 0) || (curItem.innerHTML.indexOf('NOTE:') >= 0)) && // Anything with a : other than a NOTE is a header.
  555. (curItem.innerHTML.indexOf('Meat.') < 0) &&
  556. (curItem.innerHTML.indexOf('!') < 0) &&
  557. (curItem.innerHTML.indexOf('?') < 0) &&
  558. (curItem.innerHTML.indexOf(', the Shopkeeper') < 0) &&
  559. (curItem.innerHTML.indexOf('Misc. Inv') < 0) &&
  560. (curItem.innerHTML.indexOf('perpendicular') < 0) && // avoids wikifying the "hint" bolding in the Giant Desktop Globe fight
  561. (("" + parseInt(curItem.innerHTML)) != curItem.innerHTML) // If the "item" is just a number, ignore it.
  562. ) {
  563. var ItemName = curItem.innerHTML;
  564. // Handle Special Cases
  565. var wasSpecialCase = 0;
  566. if ((curItem.innerHTML.indexOf('+') == 0) && (window.location.pathname == "/fight.php")) { wasSpecialCase = 1; } // ignore specialized damage tags
  567. if (curItem.innerHTML.indexOf('Mysticality +') >= 0) { insertWikiLink(curItem, 'Mysticality Increasers','Mysticality'); wasSpecialCase = 1; }
  568. if (curItem.innerHTML.indexOf('Muscle +') >= 0) { insertWikiLink(curItem, 'Muscle Increasers', 'Muscle'); wasSpecialCase = 1; }
  569. if (curItem.innerHTML.indexOf('Moxie +') >= 0) { insertWikiLink(curItem, 'Moxie Increasers', 'Moxie'); wasSpecialCase = 1; }
  570. if (curItem.innerHTML.indexOf('Combat Initiative') >= 0) { insertWikiLink(curItem, 'Combat Initiative', 'Combat Initiative'); wasSpecialCase = 1; }
  571. if (curItem.innerHTML.indexOf(' Resistance') >= 0) { insertWikiLink(curItem, 'Elemental Resistance', ' Resistance'); wasSpecialCase = 1; }
  572. if (curItem.innerHTML.indexOf('Item Drops') >= 0) { insertWikiLink(curItem, 'Maximizing Your Item Drops', 'Item Drops'); wasSpecialCase = 1; }
  573. if (curItem.innerHTML.indexOf('Meat from Monsters') >= 0) { insertWikiLink('Maximizing Your Meat Drops', 'Meat from Monsters'); wasSpecialCase = 1; }
  574. if (curItem.innerHTML.indexOf('Maximum HP +') >= 0) { insertWikiLink(curItem, 'Maximizing Your HP', 'Maximum HP'); wasSpecialCase = 1; }
  575. if (curItem.innerHTML.indexOf('Maximum MP +') >= 0) { insertWikiLink(curItem, 'Maximizing Your MP', 'Maximum MP'); wasSpecialCase = 1; }
  576. if (curItem.innerHTML.indexOf('Monster Level') >= 0) { insertWikiLink(curItem, 'Monster Level', 'Monster Level'); wasSpecialCase = 1; }
  577. if (curItem.innerHTML.indexOf('All Attributes') >= 0) { insertWikiLink(curItem, 'Game_Mechanics#Character_Base_Stats', 'All Attributes'); wasSpecialCase = 1; }
  578. if (curItem.innerHTML.indexOf('Melee Damage') >= 0) { insertWikiLink(curItem, 'Bonus Melee Damage', 'Melee Damage'); wasSpecialCase = 1; }
  579. if (curItem.innerHTML.indexOf('Spell Damage') >= 0) { insertWikiLink(curItem, 'Bonus Spell Damage', 'Spell Damage'); wasSpecialCase = 1; }
  580. if (curItem.innerHTML.indexOf('Damage Absorption') >= 0) { insertWikiLink(curItem, 'Maximizing_Your_Damage_Absorption', 'Damage Absorption'); wasSpecialCase = 1; }
  581. if (curItem.innerHTML.indexOf('Familiar Weight') >= 0) { insertWikiLink(curItem, 'Familiar_Weight', 'Familiar Weight'); wasSpecialCase = 1; }
  582. if (curItem.innerHTML.indexOf('chance of Critical Hit') >= 0) { insertWikiLink(curItem, 'Critical_Hit_Chance', 'chance of Critical Hit'); wasSpecialCase = 1; }
  583. if (curItem.innerHTML.indexOf('Cold') >= 0) { insertWikiLink(curItem, 'Cold', 'Cold'); wasSpecialCase = 1; }
  584. if (curItem.innerHTML.indexOf('Hot ') >= 0) { insertWikiLink(curItem, 'Hot', 'Hot'); wasSpecialCase = 1; }
  585. if (curItem.innerHTML.indexOf('Fire ') >= 0) { insertWikiLink(curItem, 'Hot', 'Fire'); wasSpecialCase = 1; }
  586. if (curItem.innerHTML.indexOf('Sleaze') >= 0) { insertWikiLink(curItem, 'Sleaze', 'Sleaze'); wasSpecialCase = 1; }
  587. if ((curItem.innerHTML.indexOf('Spooky') >= 0) && (curItem.innerHTML.indexOf('Spooky-') < 0)) { insertWikiLink(curItem, 'Spooky', 'Spooky'); wasSpecialCase = 1; }
  588. if (curItem.innerHTML.indexOf('Stench') >= 0) { insertWikiLink(curItem, 'Stench', 'Stench'); wasSpecialCase = 1; }
  589. if (curItem.innerHTML.indexOf('Adventure(s)') >= 0) { insertWikiLink(curItem, 'Extra_Rollover_Adventures', 'Adventure(s)'); wasSpecialCase = 1; }
  590. if (curItem.innerHTML.indexOf(' staff)') >= 0) { insertWikiLink(curItem, 'Category:Staves', 'staff)'); wasSpecialCase = 1; }
  591. if (curItem.innerHTML.indexOf(' axe)') >= 0) { insertWikiLink(curItem, 'Category:Axes', 'axe)'); wasSpecialCase = 1; }
  592. if (curItem.innerHTML.indexOf(' utensil)') >= 0) { insertWikiLink(curItem, 'Category:Utensils', ' utensil)'); wasSpecialCase = 1; }
  593. if (curItem.innerHTML.indexOf(' sword)') >= 0) { insertWikiLink(curItem, 'Category:Swords', ' sword)'); wasSpecialCase = 1; }
  594. if (curItem.innerHTML.indexOf(' polearm)') >= 0) { insertWikiLink(curItem, 'Category:Polearms', ' polearm)'); wasSpecialCase = 1; }
  595. if (curItem.innerHTML.indexOf(' knife)') >= 0) { insertWikiLink(curItem, 'Category:Knives', ' knife)'); wasSpecialCase = 1; }
  596. if (curItem.innerHTML.indexOf(' accordion)') >= 0) { insertWikiLink(curItem, 'Category:Accordions', ' accordion)'); wasSpecialCase = 1; }
  597. if (curItem.innerHTML.indexOf(' club)') >= 0) { insertWikiLink(curItem, 'Category:Clubs', ' club)'); wasSpecialCase = 1; }
  598. if (curItem.innerHTML.indexOf(' crossbow)') >= 0) { insertWikiLink(curItem, 'Category:Crossbows', ' crossbow)'); wasSpecialCase = 1; }
  599. if (curItem.innerHTML.indexOf(' knife)') >= 0) { insertWikiLink(curItem, 'Category:Knives', ' knife)'); wasSpecialCase = 1; }
  600. if (curItem.innerHTML.indexOf(' saucepan)') >= 0) { insertWikiLink(curItem, 'Category:Saucepans', ' saucepan)'); wasSpecialCase = 1; }
  601. if (curItem.innerHTML.indexOf(' spear)') >= 0) { insertWikiLink(curItem, 'Category:Spears', ' spear)'); wasSpecialCase = 1; }
  602. if (curItem.innerHTML.indexOf(' umbrella)') >= 0) { insertWikiLink(curItem, 'Category:Umbrellas', ' umbrella)'); wasSpecialCase = 1; }
  603. if (curItem.innerHTML.indexOf(' whip)') >= 0) { insertWikiLink(curItem, 'Category:Whips', ' whip)'); wasSpecialCase = 1; }
  604. if (curItem.innerHTML.indexOf(' autopult)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' autopult)'); wasSpecialCase = 1; }
  605. if (curItem.innerHTML.indexOf(' banjo)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' banjo)'); wasSpecialCase = 1; }
  606. if (curItem.innerHTML.indexOf(' ball)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' ball)'); wasSpecialCase = 1; }
  607. if (curItem.innerHTML.indexOf(' flail)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' flail)'); wasSpecialCase = 1; }
  608. if (curItem.innerHTML.indexOf(' sack)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' sack)'); wasSpecialCase = 1; }
  609. if (curItem.innerHTML.indexOf(' bow)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' bow)'); wasSpecialCase = 1; }
  610. if (curItem.innerHTML.indexOf(' slingshot)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' slingshot)'); wasSpecialCase = 1; }
  611. if (curItem.innerHTML.indexOf(' wand)') >= 0) { insertWikiLink(curItem, 'Category:Other', ' wand)'); wasSpecialCase = 1; }
  612. if (curItem.innerHTML.indexOf('1-handed ') >= 0) { insertWikiLink(curItem, 'Category:One-Handed_Weapons', '1-handed'); wasSpecialCase = 1; }
  613. if (curItem.innerHTML.indexOf('Successful hit weakens opponent.') >= 0) { insertWikiLink(curItem, 'Monster_Level', 'weakens opponent.'); wasSpecialCase = 1; }
  614. if (ItemName == 'Food') { insertWikiLink(curItem, 'Category:Food', 'Food'); wasSpecialCase = 1; }
  615. if (ItemName == 'Beverage') { insertWikiLink(curItem, 'Category:Beverages', 'Beverage'); wasSpecialCase = 1; }
  616. if (ItemName == 'Usable') { insertWikiLink(curItem, 'Category:Usable_Items', 'Usable'); wasSpecialCase = 1; }
  617. if (ItemName == 'Combat Item') { insertWikiLink(curItem, 'Category:Combat_Items', 'Combat Item'); wasSpecialCase = 1; }
  618. if (ItemName == 'combat / usable item') { insertWikiLink(curItem, 'Category:Combat_Items','combat'); insertWikiLink(curItem, 'Category:Usable_Items', 'usable'); wasSpecialCase = 1; }
  619. if (ItemName == 'Quest Item') { insertWikiLink(curItem, 'Category:Quest_Items', 'Quest Item'); wasSpecialCase = 1; }
  620. if (curItem.innerHTML.indexOf('100% Legal') >= 0) { insertWikiLink(curItem, '100%25_Legal', '100% Legal'); wasSpecialCase = 1; } // need to escape out the percent sign in the link. Should handle this more generally, really.
  621. if (curItem.innerHTML.indexOf('NOTE:') >= 0) { wasSpecialCase = 1; } // Just act like we did something to it, but really ignore it.
  622. if (curItem.innerHTML.indexOf('Your Campsite') >= 0) { wasSpecialCase = 1; } // Just act like we did something to it, but really ignore it.
  623. if (curItem.innerHTML.indexOf('Brrrrr') >=0) { wasSpecialCase = 1; }
  624. if ((wasSpecialCase == 0) && (ItemName != '')) {
  625. // In some odd cases KoL uses placeholder comment tags hidden in names and titles.
  626. // We need to scrub these.
  627. if (ItemName.indexOf('>') > 0) {
  628. ItemName = ItemName.substring(ItemName.indexOf('>')+1);
  629. }
  630.  
  631. // In some places (certain stores, mostly), item names are embedded in
  632. // links. If we don't get outside of that, the wiki link will trigger
  633. // that link too. So we burrow our way up a level to get out from under it.
  634. var curParent = curItem.parentNode;
  635. if (curParent.tagName == 'A') {
  636. var newElement = document.createElement("span");
  637. newElement.innerHTML = wikify(ItemName);
  638.  
  639. var parentOfParent = curParent.parentNode;
  640. if (curParent.nextSibling){
  641. parentOfParent.insertBefore(newElement,curParent.nextSibling);
  642. }
  643. else{
  644. parentOfParent.appendChild(newElement);
  645. }
  646. }
  647. else {
  648. insertWikiLink(curItem, ItemName, ItemName);
  649. }
  650. }
  651. }
  652. }
  653. }