BvS_KageTools

Compute RP point earnings for villagers, among other things

  1. // ==UserScript==
  2. // @name BvS_KageTools
  3. // @namespace SirDuck36
  4. // @description Compute RP point earnings for villagers, among other things
  5. // @version 1.4
  6. // @history 1.4 New domain - animecubedgaming.com - Channel28
  7. // @history 1.3 Now https compatible (Updated by Channel28)
  8. // @history 1.2 Adjusted the change to ROBO FIGHTO Resource win message (Updated by Channel28)
  9. // @history 1.1 Added grant permissions (Updated by Channel28)
  10. // @history 1.0 Initial Release
  11. // @include http*://*animecubed.com/billy/bvs/village.*
  12. // @include http*://*animecubed.com/billy/bvs/villageresourcepoints.*
  13. // @include http*://*animecubedgaming.com/billy/bvs/village.*
  14. // @include http*://*animecubedgaming.com/billy/bvs/villageresourcepoints.*
  15. // @grant unsafeWindow
  16. // @grant GM_addStyle
  17. // @grant GM_log
  18. // ==/UserScript==
  19.  
  20.  
  21.  
  22.  
  23.  
  24. // TODO, possibly
  25. // Additional ideas: Free snakeman game
  26. // Nonja winding
  27. // blood altar
  28. // refresh applications
  29. // reversing hourglass
  30. //
  31. // Kaiju Kage Drop Tracker
  32. //
  33. // Daily information about science
  34. // Daily Resource information
  35.  
  36.  
  37.  
  38.  
  39. ////////////////////////////////////////////////////////////////////////
  40. /////////// LIBRARY CODE /////////////////
  41. ////////////////////////////////////////////////////////////////////////
  42.  
  43. /*
  44. DOM Storage wrapper class (credits: http://userscripts.org/users/dtkarlsson)
  45. Constructor:
  46. var store = new DOMStorage({"session"|"local"}, [<namespace>]);
  47. Set item:
  48. store.setItem(<key>, <value>);
  49. Get item:
  50. store.getItem(<key>[, <default value>]);
  51. Remove item:
  52. store.removeItem(<key>);
  53. Get all keys in namespace as array:
  54. var array = store.keys();
  55. */
  56.  
  57. function DOMStorage(type, namespace) {
  58. var my = this;
  59.  
  60. if (typeof(type) != "string")
  61. type = "session";
  62. switch (type) {
  63. case "local": my.storage = localStorage; break;
  64. case "session": my.storage = sessionStorage; break;
  65. default: my.storage = sessionStorage;
  66. }
  67.  
  68. if (!namespace || typeof(namespace) != "string")
  69. namespace = "Greasemonkey";
  70.  
  71. my.ns = namespace + ".";
  72. my.setItem = function(key, val) {
  73. try {
  74. my.storage.setItem(escape(my.ns + key), val);
  75. }
  76. catch (e) {
  77. GM_log(e);
  78. }
  79. },
  80. my.getItem = function(key, def) {
  81. try {
  82. var val = my.storage.getItem(escape(my.ns + key));
  83. if (val)
  84. return val;
  85. else
  86. return def;
  87. }
  88. catch (e) {
  89. return def;
  90. }
  91. }
  92. // Kludge, avoid Firefox crash
  93. my.removeItem = function(key) {
  94. try {
  95. my.storage.setItem(escape(my.ns + key), null);
  96. }
  97. catch (e) {
  98. GM_log(e);
  99. }
  100. }
  101. // Return array of all keys in this namespace
  102. my.keys = function() {
  103. var arr = [];
  104. var i = 0;
  105. do {
  106. try {
  107. var key = unescape(my.storage.key(i));
  108. if (key.indexOf(my.ns) == 0 && my.storage.getItem(key))
  109. arr.push(key.slice(my.ns.length));
  110. }
  111. catch (e) {
  112. break;
  113. }
  114. i++;
  115. } while (true);
  116. return arr;
  117. }
  118. }
  119. // End DOM Storage Wrapper class
  120.  
  121. // UI (credits: http://userscripts.org/users/dtkarlsson)
  122. function Window(id, storage)
  123. {
  124. var my = this;
  125. my.id = id;
  126. my.offsetX = 0;
  127. my.offsetY = 0;
  128. my.moving = false;
  129.  
  130. // Window dragging events
  131. my.drag = function(event) {
  132. if (my.moving) {
  133. my.element.style.left = (event.clientX - my.offsetX)+'px';
  134. my.element.style.top = (event.clientY - my.offsetY)+'px';
  135. event.preventDefault();
  136. }
  137. }
  138. my.stopDrag = function(event) {
  139. if (my.moving) {
  140. my.moving = false;
  141. var x = parseInt(my.element.style.left);
  142. var y = parseInt(my.element.style.top);
  143. if(x < 0) x = 0;
  144. if(y < 0) y = 0;
  145. storage.setItem(my.id + ".coord.x", x);
  146. storage.setItem(my.id + ".coord.y", y);
  147. my.element.style.opacity = 1;
  148. window.removeEventListener('mouseup', my.stopDrag, true);
  149. window.removeEventListener('mousemove', my.drag, true);
  150. }
  151. }
  152. my.startDrag = function(event) {
  153. if (event.button != 0) {
  154. my.moving = false;
  155. return;
  156. }
  157. my.offsetX = event.clientX - parseInt(my.element.style.left);
  158. my.offsetY = event.clientY - parseInt(my.element.style.top);
  159. if (my.offsetY > 27)
  160. return;
  161.  
  162. my.moving = true;
  163. my.element.style.opacity = 0.75;
  164. event.preventDefault();
  165. window.addEventListener('mouseup', my.stopDrag, true);
  166. window.addEventListener('mousemove', my.drag, true);
  167. }
  168.  
  169. my.show = function()
  170. {
  171. this.element.style.visibility = 'visible';
  172. }
  173.  
  174. my.hide = function()
  175. {
  176. this.element.style.visibility = 'hidden';
  177. }
  178.  
  179. my.reset = function()
  180. {
  181. storage.setItem(my.id + ".coord.x", 6);
  182. storage.setItem(my.id + ".coord.y", 6);
  183. my.element.style.left = "6px";
  184. my.element.style.top = "6px";
  185. }
  186.  
  187.  
  188. my.element = document.createElement("div");
  189. my.element.id = id;
  190. document.body.appendChild(my.element);
  191. my.element.addEventListener('mousedown', my.startDrag, true);
  192.  
  193. if (storage.getItem(my.id + ".coord.x"))
  194. my.element.style.left = storage.getItem(my.id + ".coord.x") + "px";
  195. else
  196. my.element.style.left = "6px";
  197. if (storage.getItem(my.id + ".coord.y"))
  198. my.element.style.top = storage.getItem(my.id + ".coord.y") + "px";
  199. else
  200. my.element.style.top = "6px";
  201. }
  202. // End UI Window implementation
  203.  
  204.  
  205.  
  206.  
  207. ////////////////////////////////////////////////////////////////////////
  208. //////// QUICK RP DISTRIBUTION BY DORIAN //////////
  209. ////////////////////////////////////////////////////////////////////////
  210.  
  211. // Populates the "Amount to give" text field with the amount owed
  212. // to the name selected by the given select tag.
  213. function GetSelectedRP(nameDrop)
  214. {
  215. var name = nameDrop.item(nameDrop.selectedIndex).text;
  216.  
  217. kageTool.CheckPlayer(name);
  218. var rpOwed = kageTool.playerList[name].rpOwed;
  219.  
  220. rpOwed = 9*Math.floor(rpOwed/9);
  221.  
  222. document.getElementsByName('giveqty')[0].value = rpOwed;
  223. }
  224.  
  225. // Selects the next player (alphabetically) who is owed positive RP
  226. // from the RP distribution dropdown.
  227. function SelectNextOwedPlayer(nameDrop)
  228. {
  229. for (var i = 0; i < nameDrop.length; i++) {
  230. var name = nameDrop.item(i).text;
  231.  
  232. kageTool.CheckPlayer(name);
  233. rpOwed = kageTool.playerList[name].rpOwed;
  234.  
  235. rpOwed = 9*Math.floor(rpOwed/9);
  236.  
  237. if (rpOwed > 0) {
  238. nameDrop.selectedIndex = i;
  239. break;
  240. }
  241. }
  242. }
  243.  
  244. // Hotkeys for awarding RP to players
  245. function RPPageKeyCheck(event)
  246. {
  247. if (document.activeElement.type != "text" && document.activeElement.tagName != "SELECT") {
  248. var KeyID = event.keyCode;
  249.  
  250. if (KeyID == 71) // "g" key
  251. {
  252. // Give RP to the player
  253. document.forms.namedItem("resgive").submit();
  254. }
  255. else if (document.forms.namedItem("resgive2") && KeyID == 67) // "c" key on the confirm page
  256. {
  257. // Confirm giving RP
  258. document.forms.namedItem("resgive2").submit();
  259. }
  260. }
  261. }
  262.  
  263. // Sets up the RP distribution page to automatically populate fields and allow
  264. // hotkeys for giving RP to villagers.
  265. function SetupQuickDistribution()
  266. {
  267.  
  268. var nameDrop = document.getElementsByName('givename')[0];
  269. SelectNextOwedPlayer(nameDrop);
  270. GetSelectedRP(nameDrop);
  271. nameDrop.addEventListener("change", function(){GetSelectedRP(nameDrop)}, true);
  272.  
  273. // Add resource page hotkeys
  274. window.addEventListener("keyup", RPPageKeyCheck, false);
  275. }
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283. ////////////////////////////////////////////////////////////////////////
  284. /////////// DATA STRUCTURES /////////////////
  285. ////////////////////////////////////////////////////////////////////////
  286.  
  287.  
  288.  
  289. // Data structure for an individual player
  290. // Input: DOM storage data string (strData)
  291. // if null, default initialization data is used
  292. // Function toString: generate the player data string for DOM storage
  293. function PlayerData(strData)
  294. {
  295. // Set default values
  296. this.dateInitialized = (new Date()).getTime(); // Beginning of recorded history
  297. this.rpOwed = 0; // RP owed to the player by kage
  298. this.rpAwardedTotal = 0; // Total RP awarded to the player via storehouse
  299. this.ryoRaid = 0; // Total vryo earned via invasions
  300. this.numRaid = 0; // Total number of raids
  301. this.resInvasionBasic = 0; // Basic resources acquired via invasion
  302. this.resInvasionAdvanced = 0; // Advanced resources acquired via invasion
  303. this.numInvasion = 0; // Total number invasions
  304. this.resWheel = 0; // Basic resources earned from PH wheel
  305. this.resRobo = 0; // Basic resources earned from robo fighto tourney
  306. this.ryoContract = 0; // Total vryo brought in via contracts
  307. this.resContractBasic = 0; // Total resources from contract milling
  308. this.resContractAdvanced = 0; // Advanced resources from contract milling
  309. this.numSpies = 0; // Total number of spies placed
  310. this.numKaijuFavors = 0; // Total number of favors used on kaiju
  311. this.numDaysActive = 0; // Total number of days active in the village (did a village action)
  312. this.numDaysLazy = 0; // Total number of days lazy in village
  313. this.rpStorehouseGift = 0; // Total rp value of items donated to storehouse
  314. this.rpStorehouseTake = 0; // Total rp value of items taken from storehouse
  315. this.rpBonus = 0; // Discretionary RP
  316. this.resSnakeOilBasic = 0; // Total Snake Oil basic resources
  317. this.resSnakeOilAdvanced = 0; // Total Snake Oil advanced resources
  318. this.numZReward = 0; // Total ZReward donated to village
  319.  
  320. this.logText = ""; // Logging info, not stored for now but possibly displayed when script is run
  321.  
  322.  
  323. // Extract information from DOM Storage format, if strData not null
  324. if (strData)
  325. {
  326. var data = strData.split("|");
  327. this.dateInitialized = parseInt(data[0], 10);
  328. this.rpOwed = parseInt(data[1], 10);
  329. this.rpAwardedTotal = parseInt(data[2], 10);
  330. this.ryoRaid = parseInt(data[3], 10);
  331. this.numRaid = parseInt(data[4], 10);
  332. this.resInvasionBasic = parseInt(data[5], 10);
  333. this.resInvasionAdvanced = parseInt(data[6], 10);
  334. this.numInvasion = parseInt(data[7], 10);
  335. this.resWheel = parseInt(data[8], 10);
  336. this.resRobo = parseInt(data[9], 10);
  337. this.ryoContract = parseInt(data[10], 10);
  338. this.resContractBasic = parseInt(data[11], 10);
  339. this.resContractAdvanced = parseInt(data[12], 10);
  340. this.numSpies = parseInt(data[13], 10);
  341. this.numKaijuFavors = parseInt(data[14], 10);
  342. this.numDaysActive = parseInt(data[15], 10);
  343. this.numDaysLazy = parseInt(data[16], 10);
  344. this.rpStorehouseGift = parseInt(data[17], 10);
  345. this.rpStorehouseTake = parseInt(data[18], 10);
  346. this.rpBonus = parseInt(data[19], 10);
  347. this.resSnakeOilBasic = parseInt(data[20], 10);
  348. this.resSnakeOilAdvanced = parseInt(data[21], 10);
  349. this.numZReward = parseInt(data[22], 10);
  350. }
  351.  
  352. // Convert data to | delimited string format
  353. // Used for DOM Storage
  354. this.toString = function()
  355. {
  356. var retArr = new Array(
  357. this.dateInitialized ,
  358. this.rpOwed ,
  359. this.rpAwardedTotal ,
  360. this.ryoRaid ,
  361. this.numRaid ,
  362. this.resInvasionBasic ,
  363. this.resInvasionAdvanced ,
  364. this.numInvasion ,
  365. this.resWheel ,
  366. this.resRobo ,
  367. this.ryoContract ,
  368. this.resContractBasic ,
  369. this.resContractAdvanced ,
  370. this.numSpies ,
  371. this.numKaijuFavors ,
  372. this.numDaysActive ,
  373. this.numDaysLazy ,
  374. this.rpStorehouseGift ,
  375. this.rpStorehouseTake ,
  376. this.rpBonus ,
  377. this.resSnakeOilBasic ,
  378. this.resSnakeOilAdvanced ,
  379. this.numZReward
  380. );
  381.  
  382. return retArr.join("|");
  383. }
  384.  
  385. } // End PlayerData Definition
  386.  
  387.  
  388. // TODO: KaijuData()
  389. // this.dateDefeated // date kaiju is defeated
  390. // this.nameKaiju // name of kaiju
  391. // this.winnerT3 // T3 drop winner
  392. // this.winnerRNG // RNG drop winner
  393. // this.winnerKage // Kage drop winner or winners
  394. // this.kageDropGiven // Did kage send the drop?
  395.  
  396.  
  397.  
  398. // Data structure for KageTools Information
  399. // Input: DOM storage object
  400. function KageToolInfo(storage)
  401. {
  402. // Storage object
  403. this.storage = storage;
  404.  
  405. // Get Village Name
  406. this.namePlayer = GetPlayerName();
  407.  
  408. // Default values for script related storage
  409. this.prevVillageId = 0; // Most recent parsed village message id
  410. this.prevVillageTime = 0; // Timestamp of most recent village log parsing
  411. this.prevStorehouseId = 0; // Most recent parsed storehouse message id
  412. this.prevStorehouseTime = 0; // Timestamp of most recent storehouse log parsing
  413.  
  414. // Default RP value policy
  415. this.rpvalSpy = 1; // RP value for each successful spy placed
  416. this.rpvalBRoSpy = 1; // RP value for successful spy placed with Big Ro 2
  417. this.rpvalResWheel = 10; // RP value for each wheel resource win
  418. this.rpvalResInvasionBasic = 10; // RP value for each basic resource from invasion
  419. this.rpvalResInvasionAdvanced = 30; // RP value for each advanced resource from invasion
  420. this.rpvalRaidBase = 5; // Base and Incremental RP for successful raid
  421. this.rpvalRaidIncrement = 0; // DEPRECATED
  422. this.rpvalContractRyoIncrement = 0; // DEPRECATED
  423. this.rpvalContractResBasic = 10; // RP value for each milled basic resource
  424. this.rpvalContractResAdvanced = 30; // RP value for each milled advanced resource
  425. this.rpvalKaijuFavor = 25; // RP value for a kaiju favor
  426. this.rpvalSnakeOilBasic = 10; // RP value for basic res from snake oil
  427. this.rpvalSnakeOilAdvanced = 30; // RP value for advanced res from snake oil
  428. this.rpvalRoboResBasic = 10; // RP value for each basic resource from ROBO FIGHTO
  429. this.rpvalZReward = 1; // RP value for each ZR donated
  430. this.rpvalDayActive = 1; // RP value for each village action performed
  431. this.rpvalDayLazy = -5; // RP (penalty) for each day ninja is lazy
  432. this.rpvalContractPackMajor = 0; // RP value for pack of major contracts
  433. this.sizeContractPackMajor = 100; // size of a pack of major contracts
  434. this.rpvalContractPackMinor = 0; // RP value for a pack of minor contracts
  435. this.sizeContractPackMinor = 100; // size of a pack of minor contracts
  436. this.rpvalRaidRyoPack = 0; // RP value for a pack of raid ryo
  437. this.sizeRaidRyoPack = 250000; // size of a pack of raid ryo
  438.  
  439. // Array of all variable nambes and descriptions, used to build Preferences window
  440. this.arrInfoVars = [
  441. 'rpvalDayActive' , 'RP for village action (any kind)',
  442. 'rpvalDayLazy' , 'RP penalty for lazy ninja',
  443.  
  444. 'rpvalResWheel' , 'RP for PH wheel resource won',
  445. 'rpvalRoboResBasic' , 'RP for each ROBO FIGHTO resource won',
  446. 'rpvalZReward' , 'RP for each Z-Reward donated',
  447. 'rpvalKaijuFavor' , 'RP for each Kaiju Favor',
  448.  
  449. 'rpvalSnakeOilBasic' , 'RP for each SNAKE OIL basic resource',
  450. 'rpvalSnakeOilAdvanced' , 'RP for each SNAKE OIL advanced resource',
  451.  
  452. 'rpvalContractPackMajor' , 'RP for each pack of major contracts',
  453. 'sizeContractPackMajor' , 'Number of major contracts in a pack',
  454.  
  455. 'rpvalContractPackMinor' , 'RP for each pack of minor contracts',
  456. 'sizeContractPackMinor' , 'Number of minor contracts in a pack',
  457.  
  458. 'rpvalContractResBasic' , 'RP for each Contract Mill basic resource',
  459. 'rpvalContractResAdvanced' , 'RP for each Contract Mill advanced resource',
  460.  
  461. 'rpvalSpy' , 'RP for each successful spy placed',
  462. 'rpvalBRoSpy' , 'RP for each spy placed with Big Ro lvl. 2',
  463.  
  464. 'rpvalResInvasionBasic' , 'RP for each Invasion basic resource',
  465. 'rpvalResInvasionAdvanced' , 'RP for each Invasion advanced resource',
  466.  
  467. 'rpvalRaidBase' , 'RP base value for each raid',
  468. 'rpvalRaidRyoPack' , 'RP value for each pack of raid ryo',
  469. 'sizeRaidRyoPack' , 'Amount of raid ryo in each pack'
  470.  
  471. ];
  472.  
  473.  
  474. // Function to clear information from DOM storage
  475. this.ClearInfo = function()
  476. {
  477. this.storage.removeItem(this.namePlayer + "_Info");
  478. }
  479.  
  480. // Function to load information from DOM storage
  481. this.LoadInfo = function()
  482. {
  483. var strData = this.storage.getItem(this.namePlayer + "_Info", null);
  484. if (!strData)
  485. return;
  486.  
  487. var data = strData.split("|");
  488. var i = -1;
  489.  
  490. if (++i < data.length) this.prevVillageId = parseInt(data[i], 10);
  491. if (++i < data.length) this.prevVillageTime = parseInt(data[i], 10);
  492. if (++i < data.length) this.prevStorehouseId = parseInt(data[i], 10);
  493. if (++i < data.length) this.prevStorehouseTime = parseInt(data[i], 10);
  494. if (++i < data.length) this.rpvalSpy = parseInt(data[i], 10);
  495. if (++i < data.length) this.rpvalResWheel = parseInt(data[i], 10);
  496. if (++i < data.length) this.rpvalResInvasionBasic = parseInt(data[i], 10);
  497. if (++i < data.length) this.rpvalResInvasionAdvanced = parseInt(data[i], 10);
  498. if (++i < data.length) this.rpvalRaidBase = parseInt(data[i], 10);
  499. if (++i < data.length) this.rpvalRaidIncrement = parseInt(data[i], 10);
  500. if (++i < data.length) this.rpvalContractRyoIncrement = parseInt(data[i], 10);
  501. if (++i < data.length) this.rpvalContractResBasic = parseInt(data[i], 10);
  502. if (++i < data.length) this.rpvalContractResAdvanced = parseInt(data[i], 10);
  503. if (++i < data.length) this.rpvalKaijuFavor = parseInt(data[i], 10);
  504. if (++i < data.length) this.rpvalSnakeOilBasic = parseInt(data[i], 10);
  505. if (++i < data.length) this.rpvalSnakeOilAdvanced = parseInt(data[i], 10);
  506. if (++i < data.length) this.rpvalRoboResBasic = parseInt(data[i], 10);
  507. if (++i < data.length) this.rpvalZReward = parseInt(data[i], 10);
  508. if (++i < data.length) this.rpvalDayActive = parseInt(data[i], 10);
  509. if (++i < data.length) this.rpvalDayLazy = parseInt(data[i], 10);
  510. if (++i < data.length) this.rpvalContractPackMajor = parseInt(data[i], 10);
  511. if (++i < data.length) this.sizeContractPackMajor = parseInt(data[i], 10);
  512. if (++i < data.length) this.rpvalContractPackMinor = parseInt(data[i], 10);
  513. if (++i < data.length) this.sizeContractPackMinor = parseInt(data[i], 10);
  514. if (++i < data.length) this.rpvalRaidRyoPack = parseInt(data[i], 10);
  515. if (++i < data.length) this.sizeRaidRyoPack = parseInt(data[i], 10);
  516. if (++i < data.length) this.rpvalBRoSpy = parseInt(data[i], 10);
  517.  
  518. }
  519.  
  520. // Function to save information to DOM storage
  521. this.SaveInfo = function()
  522. {
  523. // Ensure quality of player data before saving
  524. // In particular, don't update log markers or times if data was corrupted
  525. kageTool.CheckPlayerData();
  526.  
  527. var dataArr = new Array(
  528. this.prevVillageId ,
  529. this.prevVillageTime ,
  530. this.prevStorehouseId ,
  531. this.prevStorehouseTime ,
  532. this.rpvalSpy ,
  533. this.rpvalResWheel ,
  534. this.rpvalResInvasionBasic ,
  535. this.rpvalResInvasionAdvanced ,
  536. this.rpvalRaidBase ,
  537. this.rpvalRaidIncrement ,
  538. this.rpvalContractRyoIncrement ,
  539. this.rpvalContractResBasic ,
  540. this.rpvalContractResAdvanced ,
  541. this.rpvalKaijuFavor ,
  542. this.rpvalSnakeOilBasic ,
  543. this.rpvalSnakeOilAdvanced ,
  544. this.rpvalRoboResBasic ,
  545. this.rpvalZReward ,
  546. this.rpvalDayActive ,
  547. this.rpvalDayLazy ,
  548. this.rpvalContractPackMajor ,
  549. this.sizeContractPackMajor ,
  550. this.rpvalContractPackMinor ,
  551. this.sizeContractPackMinor ,
  552. this.rpvalRaidRyoPack ,
  553. this.sizeRaidRyoPack ,
  554. this.rpvalBRoSpy
  555. );
  556.  
  557. this.storage.setItem(this.namePlayer + "_Info", dataArr.join("|"));
  558.  
  559. }
  560.  
  561. } // End KageToolInfo Definition
  562.  
  563.  
  564. // KageTools master data structure
  565. function KageTool()
  566. {
  567. // Save the storage object
  568. this.storage = new DOMStorage("local", "BvSKageTools");
  569.  
  570. // KageTools Preferences and RP policy
  571. this.info = new KageToolInfo(this.storage);
  572. this.info.LoadInfo();
  573.  
  574. // Associative array of PlayerData objects -- indexed by player name
  575. this.playerList = new Object();
  576. this.playerListIsLoaded = false;
  577.  
  578. // Check whether a player is already in the player array, and create new player data if not
  579. this.CheckPlayer = function(name)
  580. {
  581. if (!this.playerList[name])
  582. this.playerList[name] = new PlayerData(null);
  583. }
  584.  
  585. // Clear player data from DOM storage
  586. this.ClearPlayerData = function()
  587. {
  588. this.storage.removeItem(this.info.namePlayer + "_Players");
  589. }
  590.  
  591. // Test for Nan or +/- infinity values in player data
  592. this.CheckPlayerData = function()
  593. {
  594. if (!this.playerListIsLoaded)
  595. return;
  596.  
  597. // Loop over all players
  598. for (name in this.playerList)
  599. {
  600. // Loop over all attributes of player data object
  601. for (attrib in this.playerList[name])
  602. {
  603. // Skip known nonnumeric entries
  604. if (attrib == 'logText' ||
  605. attrib == 'name')
  606. continue;
  607.  
  608. // Always trust functions
  609. if (typeof(this.playerList[name][attrib]) == 'function')
  610. continue;
  611.  
  612. CheckNum(this.playerList[name][attrib],
  613. name + "." + attrib,
  614. "KageTool.CheckPlayerData");
  615. }
  616. }
  617.  
  618. // Loop over all info attributes
  619. for (attrib in this.info)
  620. {
  621. if (attrib == 'storage' ||
  622. attrib == 'namePlayer' ||
  623. attrib == 'arrInfoVars')
  624. continue;
  625.  
  626. // Always trust functions
  627. if (typeof(this.info[attrib]) == 'function')
  628. continue;
  629.  
  630.  
  631. CheckNum(this.info[attrib],
  632. attrib,
  633. "KageTool.CheckPlayerData");
  634. }
  635. }
  636.  
  637. // Load player data from DOM storage into kageTool.playerList
  638. this.LoadPlayerData = function()
  639. {
  640. // Load data maximum one time per page
  641. if (this.playerListIsLoaded)
  642. return;
  643. else
  644. this.playerListIsLoaded = true;
  645.  
  646. var strData = this.storage.getItem(this.info.namePlayer + "_Players", null);
  647. if (strData)
  648. {
  649. arrData = strData.split("\n");
  650. for (var i=0; i<arrData.length; i++)
  651. this.playerList[arrData[i].split(":")[0]] = new PlayerData(arrData[i].split(":")[1]);
  652. }
  653. }
  654. // Save player data from kageTool.playerList to DOM Storage
  655. this.SavePlayerData = function()
  656. {
  657. // Ensure quality of data before saving
  658. this.CheckPlayerData();
  659.  
  660. var strData = new Array();
  661. for (name in this.playerList)
  662. strData.push(name + ":" + this.playerList[name].toString() );
  663. strData = strData.join("\n");
  664.  
  665. // Write the DOM storage
  666. this.storage.setItem(this.info.namePlayer + "_Players", strData);
  667. }
  668.  
  669. }
  670.  
  671. // End KageTools Definition
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678. ////////////////////////////////////////////////////////////////////////
  679. /////////// FLOATING WINDOWS ///////////////
  680. ////////////////////////////////////////////////////////////////////////
  681.  
  682.  
  683. function FloatingReport()
  684. {
  685.  
  686. this.window = new Window("floatingReport", kageTool.storage);
  687. // Add css style for report window
  688. GM_addStyle("#floatingReport {border: 2px solid #000000; position: fixed; z-index: 100; " +
  689. "color: #000000; background-color: #FFFFFF; padding: 0; text-align: left; " +
  690. "overflow-y: auto; overflow-x: hidden; width: 270; height: 500; " +
  691. "background: none repeat scroll 0% 0% rgb(216, 216, 255);}");
  692. GM_addStyle("#floatingReport tr.odd {background-color: #8888FF}");
  693. GM_addStyle("#floatingReport tr.even {background-color: #BBBBFF}");
  694. GM_addStyle("#floatingReport tr.head {padding: 2; color: #FFFFFF; background-color: #0000FF; cursor: move}");
  695.  
  696. // Hide the window for now
  697. this.window.hide();
  698.  
  699. // Draw the window, or hide if already visible
  700. this.Draw = function()
  701. {
  702. if (this.window.element.style.visibility == 'visible')
  703. {
  704. // Hide the window and return
  705. this.window.hide();
  706. return;
  707. }
  708.  
  709. // Extract the playerlist into an array
  710. var arrPlayerList = new Array();
  711. var i = 0;
  712. for (name in kageTool.playerList)
  713. {
  714. arrPlayerList[i] = kageTool.playerList[name];
  715. arrPlayerList[i].name = name;
  716. i++;
  717. }
  718.  
  719. // Sort the playerlist based on rpOwed in descending order
  720. arrPlayerList = arrPlayerList.sort(function(a,b) {return b.rpOwed - a.rpOwed});
  721.  
  722. // Helper array to build the HTML
  723. var arr = new Array();
  724.  
  725. // Player Table
  726. arr.push('<table style="color: black" width=255><tbody>',
  727. '<tr class="head"><td><b>Player</b></td><td width=100><b>RP Earned</b></td></tr>');
  728.  
  729. var cl = "odd";
  730. for (i=0; i<arrPlayerList.length; i++)
  731. {
  732. var cl = (i % 2 ? "odd" : "even");
  733. arr.push('<tr class="' + cl + '"><td>' + arrPlayerList[i].name + '</td><td>' +
  734. arrPlayerList[i].rpOwed + ' (' + 9*Math.floor(arrPlayerList[i].rpOwed/9) + ')</td></tr>');
  735. }
  736.  
  737. arr.push('</tbody></table><br><br>');
  738.  
  739. // LogText messages
  740. arr.push('<b>New RP Events:</b><br>');
  741. for (name in kageTool.playerList)
  742. if (kageTool.playerList[name].logText)
  743. arr.push('<br><b>' + name + ':</b><br>' + kageTool.playerList[name].logText.replace(/\n/g,"<br>"));
  744.  
  745. // Concatenate everything in the array to form the html
  746. this.window.element.innerHTML = arr.join("");
  747.  
  748. // Show the window
  749. this.window.show();
  750. }
  751.  
  752. }
  753.  
  754.  
  755. function FloatingPreferences()
  756. {
  757.  
  758. this.window = new Window("floatingPreferences", kageTool.storage);
  759. // Add css style for report window
  760. GM_addStyle("#floatingPreferences {border: 2px solid #FFFFFF; position: fixed; z-index: 100; " +
  761. "color: #FFFFFF; background-color: #222222; padding: 4px; text-align: center; " +
  762. "width: 420; height:500; overflow-y:auto; overflow-x:hidden;}");
  763. GM_addStyle("#floatingPreferences tr.odd {padding: 1px; background-color: #AAAAAA}");
  764. GM_addStyle("#floatingPreferences input.odd {background-color: #AAAAAA}");
  765. GM_addStyle("#floatingPreferences tr.even {padding: 1px; background-color: #EEEEEE}");
  766. GM_addStyle("#floatingPreferences input.even {background-color: #EEEEEE}");
  767. GM_addStyle("#floatingPreferences tr.head {padding: 2px; color: #FFFFFF; background-color: #222222; cursor: move}");
  768.  
  769. GM_addStyle("#floatingPreferences p.rpbonus {color: #FFFFFF; text-align: left; font-size: 14px}");
  770. GM_addStyle("#floatingPreferences input.rpbonus {background-color: #888888}; color: #FFFFFF");
  771. GM_addStyle("#floatingPreferences a {color: rgb(255, 255, 255); font-size: 14px; font-weight: bold}");
  772.  
  773. // Ininitialization flag
  774. this.initialized = 0;
  775. // Hide the window for now
  776. this.window.hide();
  777.  
  778. // Initialize the window html and set callbacks
  779. this.Init = function()
  780. {
  781. // Helper array to build the HTML
  782. var arr = new Array();
  783.  
  784. // Build the window
  785. arr.push('<table style="color: black" width=400><tbody>',
  786. '<tr class="head"><td><b>RP Policy Editor</b></td><td width=85><b></b></td></tr>');
  787.  
  788. for (var i=0; i<kageTool.info.arrInfoVars.length; i+=2)
  789. {
  790. var name = kageTool.info.arrInfoVars[i];
  791. var description = kageTool.info.arrInfoVars[i+1];
  792. var value = kageTool.info[name];
  793. var cl = (i%4 ? 'even' : 'odd');
  794.  
  795. arr.push('<tr class="' + cl + '"><td>' + description + '</td><td>',
  796. '<input id="pref_' + name + '" class="' + cl + '" ',
  797. 'type=text size=10>');
  798. }
  799.  
  800. arr.push('</tbody></table><br>');
  801. // Save RP Policy Button
  802. arr.push('<p style="margin: 0pt; text-align: right;">',
  803. '<a href="javascript:void(0)" id="PreferencesSaveRPPolicyButton">',
  804. 'Save RP Policy &gt;</a></p><br>');
  805.  
  806.  
  807. // Mechanism to award RP Bonuses
  808. arr.push('<p class="rpbonus">',
  809. 'Give RP to Player: ',
  810. '<input id="nameBonus", class="rpbonus", type="text", size=10>',
  811. '&nbsp&nbsp&nbsp&nbsp RP: ',
  812. '<input id="rpBonus", class="rpbonus", type="text", size=4>',
  813. '&nbsp&nbsp&nbsp&nbsp <a href="javascript:void(0)"',
  814. 'id="PreferencesBonusRPButton">Give RP &gt;</a>',
  815. '</p>');
  816.  
  817. // Mechanism to clear player data
  818. arr.push('<p class="rpbonus">',
  819. 'Clear Data for Player: ',
  820. '<input id="nameClearPlayer", class="rpbonus", type="text", size=10>',
  821. '&nbsp&nbsp&nbsp&nbsp <a href="javascript:void(0)"',
  822. 'id="PreferencesClearPlayerButton">Clear Player Data &gt;</a>',
  823. '</p><br>');
  824.  
  825. // General data reset buttons
  826. arr.push('<p style="margin: 0pt; text-align: left;">',
  827. '<a href="javascript:void(0)" id="PreferencesResetLogMarkersButton">',
  828. '&lt; Reset Log Markers</a></p>');
  829.  
  830. arr.push('<p style="margin: 0pt; text-align: left;">',
  831. '<a href="javascript:void(0)" id="PreferencesDefaultRPPolicyButton">',
  832. '&lt; Reset Default RP Policy</a></p>');
  833.  
  834. arr.push('<p style="margin: 0pt; text-align: left;">',
  835. '<a href="javascript:void(0)" id="PreferencesResetAllPlayerDataButton">',
  836. '&lt; Reset All Player Data</a></p>');
  837.  
  838. // Concatenate everything in the array to form the html
  839. this.window.element.innerHTML = arr.join("");
  840.  
  841. // Set event callback functions
  842. document.getElementById("PreferencesSaveRPPolicyButton").addEventListener("click", this.SaveRPPolicy, true);
  843. document.getElementById("PreferencesBonusRPButton").addEventListener("click", this.GiveBonusRP, true);
  844. document.getElementById("PreferencesClearPlayerButton").addEventListener("click", this.ClearPlayerData, true);
  845. document.getElementById("PreferencesResetLogMarkersButton").addEventListener("click", this.ResetLogMarkers, true);
  846. document.getElementById("PreferencesDefaultRPPolicyButton").addEventListener("click", this.DefaultRPPolicy, true);
  847. document.getElementById("PreferencesResetAllPlayerDataButton").addEventListener("click", this.ResetAllPlayerData, true);
  848.  
  849. this.initialized = 1;
  850. }
  851.  
  852. // Draw the window, or hide if already visible
  853. this.Draw = function()
  854. {
  855. // Load Player Data
  856. kageTool.LoadPlayerData();
  857.  
  858. if (this.window.element.style.visibility == 'visible')
  859. {
  860. // hide window and return
  861. this.window.hide();
  862. return;
  863. }
  864.  
  865. // Initialize the window if needed
  866. if (!this.initialize)
  867. this.Init();
  868.  
  869. // Populate cells with current values
  870. for (var i=0; i<kageTool.info.arrInfoVars.length; i+=2)
  871. {
  872. var name = kageTool.info.arrInfoVars[i];
  873. var value = kageTool.info[name];
  874. var elem = document.getElementById('pref_' + name);
  875. elem.value = value;
  876. }
  877.  
  878. // Show the window
  879. this.window.show();
  880. }
  881.  
  882. // Save the preferences from the input boxes
  883. this.SaveRPPolicy = function()
  884. {
  885. // Check for user error
  886. if (parseInt(document.getElementById('pref_sizeContractPackMajor').value,10) == 0 ||
  887. parseInt(document.getElementById('pref_sizeContractPackMinor').value,10) == 0 ||
  888. parseInt(document.getElementById('pref_sizeRaidRyoPack').value,10) == 0)
  889. {
  890. alert("The number of major/minor contracts in a pack, and amount of raid ryo in a pack may not be 0. (If you do not wish to award RP for these events, set the pack size to 1, and the corresponding RP awarded for each pack to 0.");
  891. return;
  892. }
  893.  
  894. // Load information back into information structure
  895. for (var i=0; i<kageTool.info.arrInfoVars.length; i+=2)
  896. {
  897. var name = kageTool.info.arrInfoVars[i];
  898. var elem = document.getElementById('pref_' + name);
  899. kageTool.info[name] = parseInt(elem.value, 10);
  900. }
  901.  
  902. // Save the information object
  903. kageTool.info.SaveInfo();
  904.  
  905. // Edit the innerHTML of save button to show that something actually happened
  906. document.getElementById("PreferencesSaveRPPolicyButton").innerHTML = '<font color="yellow">RP Policy Saved &gt;</font>';
  907. setTimeout(function(){document.getElementById("PreferencesSaveRPPolicyButton").innerHTML = "Save RP Policy &gt;";}, 3000);
  908. }
  909.  
  910. // Give Bonus RP to player
  911. this.GiveBonusRP = function()
  912. {
  913. var name = document.getElementById("nameBonus").value;
  914. var rp = document.getElementById("rpBonus").value;
  915.  
  916. // Early return if no name or RP given
  917. if (name == "" || rp == "")
  918. {
  919. alert("Please enter both name and RP amount");
  920. return;
  921. }
  922.  
  923. // Input validation
  924. rp = parseInt(rp);
  925. CheckNum(rp, "RP", "floatingPreferences.GiveBonusRP");
  926.  
  927. if (name === "ALL")
  928. {
  929. // Award RP to everybody
  930. for (pname in kageTool.playerList)
  931. {
  932. kageTool.playerList[pname].rpOwed += rp;
  933. kageTool.playerList[pname].rpAwardedTotal += rp;
  934.  
  935. kageTool.playerList[pname].logText += rp + " Bonus RP Awarded\n";
  936. }
  937. }
  938. else
  939. {
  940. // More input validation
  941. kageTool.CheckPlayer(name);
  942.  
  943. // Add bonuses
  944. kageTool.playerList[name].rpOwed += rp;
  945. kageTool.playerList[name].rpAwardedTotal += rp;
  946. // Write logText
  947. kageTool.playerList[name].logText += rp + " Bonus RP Awarded\n";
  948. }
  949.  
  950. // Edit the innerHTML of button to show that something actually happened
  951. document.getElementById("PreferencesBonusRPButton").innerHTML = '<font color="yellow">RP Given &gt;</font>';
  952. setTimeout(function(){document.getElementById("PreferencesBonusRPButton").innerHTML = "Give RP &gt;";}, 3000);
  953.  
  954. // Refresh the report window, if shown
  955. if (floatingReport.window.element.style.visibility == 'visible')
  956. {
  957. floatingReport.Draw(); // hides the window
  958. floatingReport.Draw(); // re-draws the window
  959. }
  960.  
  961. // Reset the text fields (avoid double RP given)
  962. document.getElementById("nameBonus").value = "";
  963. document.getElementById("rpBonus").value = "";
  964.  
  965. // Save the new player data
  966. kageTool.SavePlayerData();
  967. }
  968.  
  969. // Clear Data for Player
  970. this.ClearPlayerData = function()
  971. {
  972. var name = document.getElementById("nameClearPlayer").value;
  973. if (name == "")
  974. return;
  975.  
  976. // Confirm that the user really wants to do this
  977. if (!confirm("Really clear all player data for player " + name + "?"))
  978. return;
  979.  
  980. // Clear the player
  981. if (kageTool.playerList[name])
  982. delete kageTool.playerList[name];
  983.  
  984. // Edit the innerHTML of button to show that something actually happened
  985. document.getElementById("PreferencesClearPlayerButton").innerHTML = '<font color="yellow">Player Data Cleared &gt;</font>';
  986. setTimeout(function(){document.getElementById("PreferencesClearPlayerButton").innerHTML = "Clear Player Data &gt;";}, 3000);
  987.  
  988. // Refresh the report window, if shown
  989. if (floatingReport.window.element.style.visibility == 'visible')
  990. {
  991. floatingReport.Draw(); // hides the window
  992. floatingReport.Draw(); // re-draws the window
  993. }
  994.  
  995. // Reset the text fields
  996. document.getElementById("nameClearPlayer").value = "";
  997.  
  998. // Save the player data
  999. kageTool.SavePlayerData();
  1000. }
  1001.  
  1002. // Reset the log marker locations
  1003. this.ResetLogMarkers = function()
  1004. {
  1005. // Confirm that the user really wants to do this
  1006. if (!confirm("Really reset village/storehouse log markers?\n\nWarning: RP giving events will be duplicated if player data is not also cleared!"))
  1007. return;
  1008.  
  1009. // Reset the log markers
  1010. kageTool.info.prevVillageId = 0;
  1011. kageTool.info.prevVillageTime = 0;
  1012. kageTool.info.prevStorehouseId = 0;
  1013. kageTool.info.prevStorehouseTime = 0;
  1014.  
  1015. // Edit the innerHTML of button to show that something actually happened
  1016. document.getElementById("PreferencesResetLogMarkersButton").innerHTML = '<font color="yellow">&lt; Log Markers Reset</font>';
  1017. setTimeout(function(){document.getElementById("PreferencesResetLogMarkersButton").innerHTML = "&lt; Reset Log Markers";}, 3000);
  1018.  
  1019. // Save the new info
  1020. kageTool.info.SaveInfo();
  1021. }
  1022.  
  1023.  
  1024. // Restore the default preferences
  1025. this.DefaultRPPolicy = function()
  1026. {
  1027. // Confirm that the user really wants to do this
  1028. if (!confirm("Really reset default values for RP Policy?"))
  1029. return;
  1030.  
  1031. // Reset the RP policy (do not change log markers or update times)
  1032. var oldInfo = kageTool.info;
  1033. kageTool.info = new KageToolInfo(kageTool.storage);
  1034. kageTool.info.prevVillageId = oldInfo.prevVillageId;
  1035. kageTool.info.prevVillageTime = oldInfo.prevVillageTime;
  1036. kageTool.info.prevStorehouseId = oldInfo.prevStorehouseId;
  1037. kageTool.info.prevStorehouseTime = oldInfo.prevStorehouseTime;
  1038.  
  1039. // Populate cells with current values
  1040. for (var i=0; i<kageTool.info.arrInfoVars.length; i+=2)
  1041. {
  1042. var name = kageTool.info.arrInfoVars[i];
  1043. var value = kageTool.info[name];
  1044. var elem = document.getElementById('pref_' + name);
  1045. elem.value = value;
  1046. }
  1047.  
  1048. // Edit the innerHTML of button to show that something actually happened
  1049. document.getElementById("PreferencesDefaultRPPolicyButton").innerHTML = '<font color="yellow">&lt; Default RP Policy Reset</font>';
  1050. setTimeout(function(){document.getElementById("PreferencesDefaultRPPolicyButton").innerHTML = "&lt; Reset Default RP Policy";}, 3000);
  1051.  
  1052. // Save the information object
  1053. kageTool.info.SaveInfo();
  1054. }
  1055.  
  1056. // Reset all player data
  1057. this.ResetAllPlayerData = function()
  1058. {
  1059. // Confirm that the user really wants to do this
  1060. if (!confirm("Really delete ALL player data?"))
  1061. return;
  1062.  
  1063. kageTool.playerList = new Object();
  1064. kageTool.ClearPlayerData();
  1065.  
  1066. // Edit the innerHTML of button to show that something actually happened
  1067. document.getElementById("PreferencesResetAllPlayerDataButton").innerHTML = '<font color="yellow">&lt; All Player Data Reset</font>';
  1068. setTimeout(function(){document.getElementById("PreferencesResetAllPlayerDataButton").innerHTML = "&lt; Reset All Player Data";}, 3000);
  1069.  
  1070. // Refresh the report window, if shown
  1071. if (floatingReport.window.element.style.visibility == 'visible')
  1072. {
  1073. floatingReport.Draw(); // hides the window
  1074. floatingReport.Draw(); // re-draws the window
  1075. }
  1076.  
  1077. }
  1078.  
  1079. }
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090. ////////////////////////////////////////////////////////////////////////
  1091. /////////// GENERAL UTILITY FUNCTIONS ///////////////
  1092. ////////////////////////////////////////////////////////////////////////
  1093.  
  1094. // Get the Players Name
  1095. function GetPlayerName()
  1096. {
  1097. return document.evaluate("//input[@name='player' and @type='hidden']", document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue.value;
  1098. }
  1099.  
  1100. // Check RP values before use (Prevent NaN and infinity values from corrupting data)
  1101. // type: type of number for error reporting
  1102. // funStr: name of calling function for error reporting
  1103. function CheckNum(num, type, funStr)
  1104. {
  1105. if (isFinite(num))
  1106. return;
  1107.  
  1108. // Otherwise die and terminate further execution
  1109. alert("Bad " + type + " value: " + num + "\nError in function: " + funStr);
  1110. throw("Bad " + type + " value: " + num + "\nError in function: " + funStr);
  1111. }
  1112.  
  1113. // Check if all village log messages are shown and available for parsing
  1114. // returns true if ready, false if not
  1115. function VillageAllMessagesShown()
  1116. {
  1117. var textRefresh = document.evaluate("//form[@name='refreshmes']/p/a/b", document, null,
  1118. XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue.innerHTML;
  1119. if (textRefresh == "Refresh Messages")
  1120. return true;
  1121. else // textRefresh == "Refresh Messages / Show All"
  1122. return false;
  1123. }
  1124.  
  1125. // Put a KageTools button in the village actions menu
  1126. function InsertKageToolsButton()
  1127. {
  1128. // Table which houses everything in left column below the village message log
  1129. var leftTable = document.evaluate("//table/tbody/tr/td[@width=255]", document, null,
  1130. XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  1131.  
  1132. var msgText;
  1133. var msgReportButton;
  1134. var funReportCallback;
  1135.  
  1136. var msgStorehouseButton = "Update Storehouse &gt;";
  1137.  
  1138.  
  1139. var funStorehouseCallback = function() {location.href = "javascript:document.respoints.submit()";};
  1140.  
  1141. // var funStorehouseCallback = function()
  1142. // {
  1143. // document.forms.namedItem("respoints").submit();
  1144. //
  1145. // if(typeof(unsafeWindow) === 'undefined')
  1146. // document.respoints.submit();
  1147. // else unsafeWindow.document.respoints.submit();
  1148. // };
  1149.  
  1150. var msgPreferencesButton = "RP Policy / Admin &gt;";
  1151. var funPreferencesCallback = function() {floatingPreferences.Draw();};
  1152.  
  1153. var hrsVillageElapsed = Math.floor( ( (new Date()).getTime() - kageTool.info.prevVillageTime ) / (1000 * 60 * 60) );
  1154. var hrsStorehouseElapsed = Math.floor( ( (new Date()).getTime() - kageTool.info.prevStorehouseTime ) / (1000 * 60 * 60) );
  1155.  
  1156. // Build the message strings for button
  1157. if (VillageAllMessagesShown())
  1158. {
  1159. msgText =
  1160. "Use your KageTools!<br>" +
  1161. "(" + hrsVillageElapsed + "h since last village update)<br>" +
  1162. "(" + hrsStorehouseElapsed + "h since last storehouse update)";
  1163. msgReportButton = "KageTools Report &gt;";
  1164. funReportCallback = ParseVillageLogs;
  1165. }
  1166. else
  1167. {
  1168. msgText = "Show all messages to use KageTools<br>" +
  1169. "(" + hrsVillageElapsed + "h since last village update)<br>" +
  1170. "(" + hrsStorehouseElapsed + "h since last storehouse update)";
  1171. msgReportButton = "Show All Messages &gt;";
  1172.  
  1173.  
  1174. funReportCallback = function(){location.href = "javascript:document.refreshmes.submit();";};
  1175.  
  1176. // funReportCallback = function()
  1177. // {
  1178. // document.forms.namedItem("refreshmes").submit();
  1179. //
  1180. // if(typeof(unsafeWindow) === 'undefined')
  1181. // document.refreshmes.submit();
  1182. // else
  1183. // unsafeWindow.document.refreshmes.submit();
  1184. // };
  1185. }
  1186.  
  1187. // Build the new div element
  1188.  
  1189. var divElem = document.createElement("div");
  1190. divElem.id = "KageToolDiv";
  1191.  
  1192. divElem.innerHTML =
  1193. '<table style="border: 2px solid rgb(0, 0, 0); background-color: rgb(0,0,192); color: rgb(255, 255, 255); font-family: arial; font-size: 12px;" width="255"><tbody><tr><td>\n' +
  1194. msgText + '<br>\n' +
  1195. '<p style="margin: 0pt; text-align: right;"><a href="javascript:void(0)" id="KageToolsReportButton" style="color: rgb(255, 255, 255); font-size: 14px;"><b>' + msgReportButton + '</b></a></p>\n' +
  1196. '<p style="margin: 0pt; text-align: right;"><a href="javascript:void(0)" id="KageToolsStorehouseButton" style="color: rgb(255, 255, 255); font-size: 14px;"><b>' + msgStorehouseButton + '</b></a></p>\n' +
  1197. '<p style="margin: 0pt; text-align: right;"><a href="javascript:void(0)" id="KageToolsPreferencesButton" style="color: rgb(255, 255, 255); font-size: 14px;"><b>' + msgPreferencesButton + '</b></a></p>\n' +
  1198. '</td></tr></tbody></table>\n';
  1199.  
  1200. // Figure out where to put in the div element
  1201. leftTable.insertBefore(divElem, leftTable.firstChild);
  1202.  
  1203. // Add event listener for greassmonkey callback
  1204. document.getElementById("KageToolsReportButton").addEventListener("click", funReportCallback, true);
  1205. document.getElementById("KageToolsStorehouseButton").addEventListener("click", funStorehouseCallback, true);
  1206. document.getElementById("KageToolsPreferencesButton").addEventListener("click", funPreferencesCallback, true);
  1207. }
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.  
  1216. ////////////////////////////////////////////////////////////////////////
  1217. /////////// VILLAGE LOG PARSING ///////////////
  1218. ////////////////////////////////////////////////////////////////////////
  1219.  
  1220.  
  1221. // Handler for Daily Collection Log Message
  1222. // We don't actually care about the contents of the message
  1223. // This handler parses once a day stuff for active / lazy ninja
  1224. function HandlerDailyCollection(msg)
  1225. {
  1226. // Helper function for active ninja
  1227. function doActive(arr, action)
  1228. {
  1229. for(var i=0; i<arr.length; i++)
  1230. {
  1231. name = arr[i];
  1232. if (!name)
  1233. continue;
  1234.  
  1235. if (name == "None")
  1236. continue;
  1237.  
  1238. // Add bonuses
  1239. kageTool.CheckPlayer(name);
  1240. kageTool.playerList[name].numDaysActive++;
  1241. kageTool.playerList[name].rpOwed += kageTool.info.rpvalDayActive;
  1242.  
  1243. // Write logText
  1244. kageTool.playerList[name].logText += kageTool.info.rpvalDayActive + " RP for " + action + " action\n";
  1245. }
  1246. }
  1247.  
  1248. // Helper function for lazy ninja
  1249. function doLazy(arr)
  1250. {
  1251. for(var i=0; i<arr.length; i++)
  1252. {
  1253. if (!arr[i])
  1254. continue;
  1255.  
  1256. name = /^(.+?)($| \()/.exec(arr[i])[1];
  1257.  
  1258. if (name == "None")
  1259. continue;
  1260.  
  1261. // Add bonuses
  1262. kageTool.CheckPlayer(name);
  1263. kageTool.playerList[name].numDaysLazy++;
  1264. kageTool.playerList[name].rpOwed += kageTool.info.rpvalDayLazy;
  1265.  
  1266. // Write logText
  1267. kageTool.playerList[name].logText += kageTool.info.rpvalDayLazy + " RP for being lazy\n";
  1268. }
  1269. }
  1270.  
  1271. // Drill down to the text we are looking for
  1272. var result = /<b>Contributions:<\/b>(.+?)<b>Collectors:<\/b>(.+?)<b>Patrollers:<\/b>(.+?)<b>Repairers:<\/b>(.+?)<b>Paper-pushers:<\/b>(.+?)<b>Resuppliers:<\/b>(.+?)<b>Sappers:<\/b>(.+?)<b>Awesome Upkeep:<\/b>(.+?)<b>Lazy Ninja:<\/b>(.+?)<\/div>/.exec(document.body.innerHTML);
  1273.  
  1274. // Drill down to the text we are looking for
  1275. var result = /<b>Contributions:<\/b>(.+?)<b>Collectors:<\/b>(.+?)<b>Patrollers:<\/b>(.+?)<b>Repairers:<\/b>(.+?)<b>Paper-pushers:<\/b>(.+?)<b>Resuppliers:<\/b>(.+?)<b>Sappers:<\/b>(.+?)<b>Awesome Upkeep:<\/b>(.+?)<b>Lazy Ninja:<\/b>(.+?)<\/div>/.exec(document.body.innerHTML);
  1276.  
  1277. // Special case code if village has no awesome upkeep
  1278. if (!result)
  1279. {
  1280. var result = /<b>Contributions:<\/b>(.+?)<b>Collectors:<\/b>(.+?)<b>Patrollers:<\/b>(.+?)<b>Repairers:<\/b>(.+?)<b>Paper-pushers:<\/b>(.+?)<b>Resuppliers:<\/b>(.+?)<b>Sappers:<\/b>(.+?)<b>Lazy Ninja:<\/b>(.+?)<\/div>/.exec(document.body.innerHTML);
  1281. result[9] = result[8];
  1282. result[8] = "None";
  1283. }
  1284.  
  1285. var contributions = result[1].split("<br>");
  1286. var collect = result[2].split("<br>");
  1287. var patrol = result[3].split("<br>");
  1288. var repair = result[4].split("<br>");
  1289. var paperwork = result[5].split("<br>");
  1290. var resupply = result[6].split("<br>");
  1291. var sapper = result[7].split("<br>");
  1292. var upkeep = result[8].split("<br>");
  1293. var lazy = result[9].split("<br>");
  1294.  
  1295. // Call the helper scripts for each of the different categories
  1296. doActive(collect, "collect");
  1297. doActive(patrol, "patrol");
  1298. doActive(repair, "repair");
  1299. doActive(paperwork, "paperwork");
  1300. doActive(resupply, "resupply");
  1301. doActive(sapper, "sapper");
  1302.  
  1303. doLazy(lazy);
  1304. }
  1305.  
  1306. // Handler for PH Wheel Resource winnings
  1307. function HandlerResWheel(msg)
  1308. {
  1309. // Example msg.text
  1310. // <li class="alt2"><label for="message-9926413">&nbsp;&nbsp;<b>Party House Win 3/12 (Sat - 23:54):</b> Calico Blk has won a Basic Resource for the Village!</label></li>
  1311.  
  1312. // Extract player name
  1313. var name = /<\/b> (.+) has won a Basic Resource for the Village!/.exec(msg.text)[1];
  1314. kageTool.CheckPlayer(name);
  1315.  
  1316. // Add bonuses
  1317. kageTool.playerList[name].resWheel++;
  1318. kageTool.playerList[name].rpOwed += kageTool.info.rpvalResWheel;
  1319.  
  1320. // Write logText
  1321. kageTool.playerList[name].logText += kageTool.info.rpvalResWheel + " RP for wheel resource\n";
  1322. }
  1323.  
  1324. // Handler for ROBO FIGHTO resource tourney winnings
  1325. function HandlerResRobo(msg)
  1326. {
  1327. // Example msg.text
  1328. // <input id="message-8118301" name="message-8118301" value="1" type="checkbox"><b><b>ROBO FIGHTO</b>:</b> Simular has won one of each Basic Resource for your village!
  1329.  
  1330. // Extract player name
  1331. var name = /:<\/b> (.+) has won one of each Basic Resource for your village/.exec(msg.text)[1];
  1332. kageTool.CheckPlayer(name);
  1333.  
  1334. // Add bonuses
  1335. kageTool.playerList[name].resRobo += 3;
  1336. kageTool.playerList[name].rpOwed += 3 * kageTool.info.rpvalRoboResBasic;
  1337.  
  1338. // Write logText
  1339. kageTool.playerList[name].logText += 3* kageTool.info.rpvalRoboResBasic + " RP for ROBO FIGHTO win\n";
  1340. }
  1341.  
  1342. // Handler for Kaiju favors
  1343. function HandlerKaijuFavor(msg)
  1344. {
  1345. // Example msg.text
  1346. // &nbsp;&nbsp;<b>The Flash!:</b> Sabrac asks The Flash for a favor, and he does a whirlwind of damage to the Kaiju!
  1347.  
  1348. // Extract player name
  1349. var name = /<\/b> (.+) asks The Flash for a favor, and he does a whirlwind of damage to the Kaiju!/.exec(msg.text)[1];
  1350. kageTool.CheckPlayer(name);
  1351. // Add bonuses
  1352. kageTool.playerList[name].numKaijuFavors++;
  1353. kageTool.playerList[name].rpOwed += kageTool.info.rpvalKaijuFavor;
  1354.  
  1355. // Write logText
  1356. kageTool.playerList[name].logText += kageTool.info.rpvalKaijuFavor +
  1357. " RP for Kaiju Favor\n";
  1358. }
  1359.  
  1360. // Handler for Z-Reward donations
  1361. function HandlerZRewards(msg)
  1362. {
  1363. // Example msg.text
  1364. // &nbsp;&nbsp;<b>Z-Rewards 8/18 (Wed - 7:29):</b> quastle gave 15 Z-Rewards to the village.
  1365.  
  1366. // Extract player Name
  1367. var result = /<\/b> (.+) gave (\d+) Z-Rewards to the village./.exec(msg.text);
  1368. var name = result[1];
  1369. var numZReward = parseInt(result[2], 10);
  1370. kageTool.CheckPlayer(name);
  1371. // Add Bonuses
  1372. var rpOwed = numZReward * kageTool.info.rpvalZReward;
  1373. kageTool.playerList[name].numZReward += numZReward;
  1374. kageTool.playerList[name].rpOwed += rpOwed;
  1375.  
  1376. // Write logText
  1377. kageTool.playerList[name].logText += rpOwed + " RP for " + numZReward + " Z-Rewards\n";
  1378. }
  1379.  
  1380. // Handler for Snake Oil and snake oil lite
  1381. function HandlerSnakeOil(msg)
  1382. {
  1383. // Example msg.text
  1384. // &nbsp;&nbsp;<b>SNAKE Oil:</b> Kuwaii drank SNAKE Oil, and resources popped out all over! One of each Resource Granted!
  1385. // &nbsp;&nbsp;<b>SNAKE Oil:</b> Sabrac drank SNAKE Oil Lite, and resources popped out all over! Resources Granted - Precious Metals, Brilliant Crystals, Precious Metals
  1386. var result = /<\/b> (.+) drank (SNAKE Oil|SNAKE Oil Lite), and resources popped out all over!/.exec(msg.text);
  1387. var name = result[1];
  1388. var type = result[2];
  1389. kageTool.CheckPlayer(name);
  1390.  
  1391. var resBasic = 0;
  1392. var resAdvanced = 0;
  1393. if (type == "SNAKE Oil Lite")
  1394. {
  1395. var resTypes = /Resources Granted - (\w+ \w+), (\w+ \w+), (\w+ \w+)/.exec(msg.text);
  1396. for (var i=1; i<=3; i++)
  1397. {
  1398. if (resTypes[i] == "Brilliant Crystals" ||
  1399. resTypes[i] == "Medicinal Water" ||
  1400. resTypes[i] == "Precious Metals")
  1401. resBasic++;
  1402. if (resTypes[i] == "Solid Fire" ||
  1403. resTypes[i] == "Unmelting Ice")
  1404. resAdvanced++;
  1405. }
  1406. }
  1407. else // SNAKE OIL
  1408. {
  1409. resBasic = 3;
  1410. resAdvanced = 2;
  1411. }
  1412.  
  1413. // Add bonuses
  1414. kageTool.playerList[name].resSnakeOilBasic += resBasic;
  1415. kageTool.playerList[name].resSnakeOilAdvanced += resAdvanced;
  1416.  
  1417. var rpOwed = resBasic * kageTool.info.rpvalSnakeOilBasic + resAdvanced * kageTool.info.rpvalSnakeOilAdvanced;
  1418. kageTool.playerList[name].rpOwed += rpOwed;
  1419.  
  1420. // Write logText
  1421. kageTool.playerList[name].logText += rpOwed + " RP for " + type + " -- " + resBasic + " basic, " + resAdvanced + " advanced\n";
  1422. }
  1423.  
  1424. // Handler for Spy Success log messages
  1425. function HandlerSpy(msg)
  1426. {
  1427. // Example msg.text
  1428. // &nbsp;&nbsp;<b>Spy Success 8/16 (Mon - 21:31):</b> Tony6785 has infiltrated a spy into TFF II Village!
  1429. // <b>Spy Success 3/26 (Sat - 15:48):</b> TeaK has infiltrated a spy into Raftel Village! Their leader is NOT Ascended!
  1430. // <b>Spy Success 3/26 (Sat - 15:48):</b> TeaK has infiltrated a spy into ReHive Village! Their leader is Ascended!
  1431.  
  1432. // Extract Player name
  1433. var name = /<\/b> (.+) has infiltrated a spy into /.exec(msg.text)[1];
  1434. kageTool.CheckPlayer(name);
  1435.  
  1436. // Add bonuses
  1437. kageTool.playerList[name].numSpies++;
  1438.  
  1439. if (/Their leader is Ascended!/.test(msg.text) ||
  1440. /Their leader is NOT Ascended!/.test(msg.text) )
  1441. {
  1442. kageTool.playerList[name].rpOwed += kageTool.info.rpvalBRoSpy;
  1443. kageTool.playerList[name].logText += kageTool.info.rpvalBRoSpy + " RP for BRo2 spy\n";
  1444. }
  1445. else
  1446. {
  1447. kageTool.playerList[name].rpOwed += kageTool.info.rpvalSpy;
  1448. kageTool.playerList[name].logText += kageTool.info.rpvalSpy + " RP for spy\n";
  1449. }
  1450.  
  1451. }
  1452.  
  1453. // Handler for Invasion Success log messages
  1454. function HandlerInvasion(msg)
  1455. {
  1456. // Example msg.text
  1457. // &nbsp;&nbsp;<b>Invasion Success 8/15 (Sun - 21:42):</b> Kazeodori attempted to attack Jidai Village and succeeded! They took 1 Brilliant Crystals, 1 Medicinal Water, 1 Precious Metals, 1 Unmelting Ice!
  1458.  
  1459. // Extract player name
  1460. var name = /<\/b> (.+) attempted to attack/.exec(msg.text)[1];
  1461. kageTool.CheckPlayer(name);
  1462.  
  1463. // Number of resources acquired
  1464. var numBasic =
  1465. (msg.text.indexOf("Brilliant Crystals") >= 0 ? 1 : 0) +
  1466. (msg.text.indexOf("Medicinal Water") >= 0 ? 1 : 0) +
  1467. (msg.text.indexOf("Precious Metals") >= 0 ? 1 : 0);
  1468.  
  1469. var numAdvanced =
  1470. (msg.text.indexOf("Solid Fire") >= 0 ? 1 : 0) +
  1471. (msg.text.indexOf("Unmelting Ice") >= 0 ? 1 : 0);
  1472.  
  1473. // Add bonuses
  1474. kageTool.playerList[name].numInvasion++;
  1475. kageTool.playerList[name].resInvasionBasic += numBasic;
  1476. kageTool.playerList[name].resInvasionAdvanced += numAdvanced;
  1477.  
  1478. var rpOwed = numBasic * kageTool.info.rpvalResInvasionBasic +
  1479. numAdvanced * kageTool.info.rpvalResInvasionAdvanced;
  1480. kageTool.playerList[name].rpOwed += rpOwed;
  1481.  
  1482. // Write logText
  1483. kageTool.playerList[name].logText += rpOwed + " RP for invasion -- " +
  1484. numBasic + " basic, " + numAdvanced + " advanced\n";
  1485. }
  1486.  
  1487. // Handler for Raid Success log messages
  1488. function HandlerRaid(msg)
  1489. {
  1490. // Example msg.text
  1491. // &nbsp;&nbsp;<b>Raid Success 8/16 (Mon - 9:11):</b> SirDuck36 attempted to attack Manetheren Village and succeeded! They got 1303660 Ryo!
  1492.  
  1493. // Extract player name
  1494. var name = /<\/b> (.+) attempted to attack/.exec(msg.text)[1];
  1495. kageTool.CheckPlayer(name);
  1496.  
  1497. // Extract ryo amount and remove commas if present
  1498. var strRyo = /Village and succeeded! They got ([\d,]+) Ryo!/.exec(msg.text)[1];
  1499. var ryo = parseInt(strRyo.replace(/,/gi, ""), 10);
  1500.  
  1501. // RP Earned = Base + floor(ryo/increment)
  1502. var rpBase = kageTool.info.rpvalRaidBase;
  1503. var rpBonus = Math.floor(ryo/kageTool.info.sizeRaidRyoPack) * kageTool.info.rpvalRaidRyoPack;
  1504.  
  1505. // Add bonuses
  1506. kageTool.playerList[name].numRaid++;
  1507. kageTool.playerList[name].ryoRaid += ryo;
  1508. kageTool.playerList[name].rpOwed += rpBase + rpBonus;
  1509.  
  1510. // Write logText
  1511. kageTool.playerList[name].logText += rpBase + "+" + rpBonus +
  1512. " RP for " + strRyo + " ryo raid (base+bonus)\n";
  1513. }
  1514.  
  1515. // Handler for Contract Donation/Milling
  1516. function HandlerContracts(msg)
  1517. {
  1518. // Example msg.text
  1519. // &nbsp;&nbsp;<b>Contracts 8/16 (Mon - 0:32):</b> SirDuck36 milled 1 Major Village Contract for Nothing!
  1520. // &nbsp;&nbsp;<b>Contracts 8/16 (Mon - 14:50):</b> Blasfeemy has submitted 3 Minor Village Contracts for 3000 Ryo!
  1521. // &nbsp;&nbsp;<b>Contracts 8/16 (Mon - 10:43):</b> Freeg milled 5 Major Village Contracts for 5000 Ryo, 1 Brilliant Crystals!
  1522. // &nbsp;&nbsp;<b>Contracts 9/2 (Thu - 11:34):</b> Tony6785 milled 1 Major Village Contract for 1 Solid Fire!
  1523.  
  1524. // Early return if contracts were milled for nothing
  1525. if (msg.text.indexOf("for Nothing!") >= 0)
  1526. return;
  1527.  
  1528. // Extract player name
  1529. var name = /<\/b> (.+) (has submitted |milled )/.exec(msg.text)[1];
  1530. kageTool.CheckPlayer(name);
  1531.  
  1532. var strRyo;
  1533. var ryo;
  1534.  
  1535. // Ryo/Resources acquired
  1536. if (msg.text.indexOf("Ryo") >= 0)
  1537. {
  1538. strRyo = /Village Contracts? for ([\d,]+) Ryo/.exec(msg.text)[1];
  1539. ryo = parseInt(strRyo.replace(/,/gi,""), 10);
  1540. }
  1541. else
  1542. {
  1543. strRyo = "0";
  1544. ryo = 0;
  1545. }
  1546.  
  1547. var temp;
  1548.  
  1549. var numContracts;
  1550. var typeContracts;
  1551.  
  1552. // Extract number of major and minor contracts
  1553. temp = /(milled|has submitted) ([\d,]+) (Major|Minor) Village Contract/.exec(msg.text);
  1554.  
  1555. numContracts = parseInt(temp[2].replace(/,/gi,""), 10);
  1556. typeContracts = temp[3];
  1557.  
  1558. var resBasic = 0;
  1559. var resAdvanced = 0;
  1560.  
  1561. // Extract Basics
  1562. temp = / (\d+) Brilliant Crystals/.exec(msg.text);
  1563. if (temp) resBasic += parseInt(temp[1].replace(/,/gi,""), 10);
  1564. temp = / (\d+) Medicinal Water/.exec(msg.text);
  1565. if (temp) resBasic += parseInt(temp[1].replace(/,/gi,""), 10);
  1566. temp = / (\d+) Precious Metals/.exec(msg.text);
  1567. if (temp) resBasic += parseInt(temp[1].replace(/,/gi,""), 10);
  1568.  
  1569. // Extract Advanceds
  1570. temp = / (\d+) Solid Fire/.exec(msg.text);
  1571. if (temp) resAdvanced += parseInt(temp[1].replace(/,/gi,""), 10);
  1572. temp = / (\d+) Unmelting Ice/.exec(msg.text);
  1573. if (temp) resAdvanced += parseInt(temp[1].replace(/,/gi,""), 10);
  1574.  
  1575. // Award bonuses
  1576. var rpPacks;
  1577. if (typeContracts == "Major")
  1578. rpPacks = Math.floor(numContracts/kageTool.info.sizeContractPackMajor)*kageTool.info.rpvalContractPackMajor;
  1579. if (typeContracts == "Minor")
  1580. rpPacks = Math.floor(numContracts/kageTool.info.sizeContractPackMinor)*kageTool.info.rpvalContractPackMinor;
  1581.  
  1582. var rpBasic = resBasic * kageTool.info.rpvalContractResBasic;
  1583. var rpAdvanced = resAdvanced * kageTool.info.rpvalContractResAdvanced;
  1584.  
  1585. kageTool.playerList[name].ryoContract += ryo;
  1586. kageTool.playerList[name].resContractBasic += resBasic;
  1587. kageTool.playerList[name].resContractAdvanced += resAdvanced;
  1588.  
  1589. kageTool.playerList[name].rpOwed += rpPacks + rpBasic + rpAdvanced;
  1590.  
  1591. // Write logText
  1592. kageTool.playerList[name].logText += rpPacks + "+" + rpBasic + "+" + rpAdvanced + " RP for contracts\n&nbsp;&nbsp;&nbsp;-- "
  1593. + numContracts + " " + typeContracts + ", " + resBasic + " basic, " + resAdvanced + " advanced\n";
  1594.  
  1595. }
  1596.  
  1597. // Outer loop for Village Log Parsing
  1598. // Each specific event type is passed to the Handlers above
  1599. function ParseVillageLogs()
  1600. {
  1601. // Early return if user needs to press the Show all messages button
  1602. if (!VillageAllMessagesShown())
  1603. {
  1604. alert("KageTools: Please show all village messages before running script");
  1605. return;
  1606. }
  1607.  
  1608. // Load KageTools data from DOM Storage (possibly expensive operation)
  1609. kageTool.LoadPlayerData();
  1610.  
  1611. // Flag to prevent village actions from being parsed more than once per day
  1612. var flagDaily = false;
  1613.  
  1614. // Get a snapshot for each message in the village chat
  1615. var snapMessageList = document.evaluate("//ul[@id='messageul']//li/label", document, null,
  1616. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1617.  
  1618. // Examine each message for potential tasty info
  1619. var i;
  1620. for (i=0; i<snapMessageList.snapshotLength; i++)
  1621. {
  1622. var snap = snapMessageList.snapshotItem(i);
  1623.  
  1624. var msg = new Object();
  1625.  
  1626. // Extract the message id number and test against previous update
  1627. msg.id = parseInt(snap.htmlFor.split('-')[1],10);
  1628. if (msg.id <= kageTool.info.prevVillageId)
  1629. break;
  1630.  
  1631. msg.text = snap.innerHTML;
  1632.  
  1633. try
  1634. {
  1635.  
  1636. // Daily collection
  1637. if (msg.text.indexOf("<b>Daily Collection ") >= 0 && !flagDaily)
  1638. {
  1639. flagDaily = true;
  1640. HandlerDailyCollection(msg);
  1641. }
  1642. // Party house wheel resource win
  1643. if (msg.text.indexOf("<b>Party House Win ") >= 0)
  1644. HandlerResWheel(msg);
  1645. // Daily resource tourney from robofighto
  1646. if (msg.text.indexOf("<b>ROBO FIGHTO") >= 0)
  1647. HandlerResRobo(msg);
  1648. // Kaiju Favor
  1649. if (msg.text.indexOf("<b>The Flash!") >= 0 &&
  1650. msg.text.indexOf("and he does a whirlwind of damage to the Kaiju!") >= 0)
  1651. HandlerKaijuFavor(msg);
  1652. // Z-Reward Donation
  1653. if (msg.text.indexOf("<b>Z-Rewards ") >= 0)
  1654. HandlerZRewards(msg);
  1655. // SNAKE OIL and SNAKE OIL lite
  1656. if (msg.text.indexOf("<b>SNAKE Oil") >= 0)
  1657. HandlerSnakeOil(msg);
  1658. // Spy Success
  1659. if (msg.text.indexOf("<b>Spy Success ") >= 0)
  1660. HandlerSpy(msg);
  1661. // Invasion Success
  1662. if (msg.text.indexOf("<b>Invasion Success ") >= 0)
  1663. HandlerInvasion(msg);
  1664. // Raid Success
  1665. if (msg.text.indexOf("<b>Raid Success ") >= 0)
  1666. HandlerRaid(msg);
  1667. // Contracts
  1668. if (msg.text.indexOf("<b>Contracts ") >= 0)
  1669. HandlerContracts(msg);
  1670.  
  1671. }
  1672. catch (err)
  1673. {
  1674. // Display error and ask the user whether they wish to continue
  1675. var text = "Error: " + err.message + "\n\noccured parsing village message:\n" + msg.text + "\n\n"
  1676. + "Press OK to skip this log entry or press CANCEL to halt script execution without save."
  1677. + "\n\n NOTE: RP for this village message must be added manually if you choose to continue.";
  1678.  
  1679. if (!confirm(text))
  1680. throw(err);
  1681. }
  1682. }
  1683. // Update the last message log id
  1684. kageTool.info.prevVillageId = parseInt(snapMessageList.snapshotItem(0).htmlFor.split('-')[1],10);
  1685. // Update the last update time
  1686. kageTool.info.prevVillageTime = (new Date()).getTime();
  1687.  
  1688. // Populate and show the floatingReport window
  1689. floatingReport.Draw();
  1690.  
  1691. // Save the Player data
  1692. kageTool.SavePlayerData();
  1693.  
  1694. // Save the information object
  1695. kageTool.info.SaveInfo();
  1696.  
  1697. }
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709. ////////////////////////////////////////////////////////////////////////
  1710. /////////// STOREHOUSE LOG PARSING /////////////
  1711. ////////////////////////////////////////////////////////////////////////
  1712.  
  1713.  
  1714. // Handler for RP Awarded in storehouse log
  1715. function HandlerRPAward(msg)
  1716. {
  1717. // Example msg.text
  1718. // 8/19 (Thu - 0:51): SirDuck36 gave 3 RP to SirDuck36!
  1719. // 8/19 (Thu - 0:50): SirDuck36 gave 2 RP to SirDuck36! Reason: Awesomeness
  1720.  
  1721. // multi-RP 20 given
  1722. // 9/6 (Thu - 1:56): Kurokage gave 22 RP to Kurokage! (+2 Cold Hard Cash!) (multi-RP give)
  1723.  
  1724. // Parse log string
  1725. var result = / gave (\d+) RP to (.+?)!/.exec(msg.text);
  1726. var chc = /(\d+) Cold Hard Cash!/.exec(msg.text);
  1727. chc = chc === null ? 0 : chc[1] - 0;
  1728.  
  1729. var rpAwarded = parseInt(result[1]) - chc;
  1730. var name = result[2];
  1731. kageTool.CheckPlayer(name);
  1732.  
  1733. // Update Player object
  1734. kageTool.playerList[name].rpAwardedTotal += rpAwarded;
  1735. kageTool.playerList[name].rpOwed -= rpAwarded;
  1736.  
  1737. // Write logText
  1738. kageTool.playerList[name].logText += rpAwarded + "RP Given\n";
  1739. }
  1740.  
  1741.  
  1742. // Outer loop for Storehouse Log Parsing
  1743. // Each specific event type is passed to the Handlers above
  1744. function ParseStorehouseLogs()
  1745. {
  1746. // Load KageTools data from DOM Storage (possibly expensive operation)
  1747. kageTool.LoadPlayerData();
  1748.  
  1749.  
  1750.  
  1751. // Get a snapshot for each message in the village chat
  1752. var snapMessageList = document.evaluate("//div[@id='slog']//label", document, null,
  1753. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1754.  
  1755. // Examine each message for potential tasty info
  1756. var i;
  1757. for (i=0; i<snapMessageList.snapshotLength; i++)
  1758. {
  1759. var snap = snapMessageList.snapshotItem(i);
  1760.  
  1761. var msg = new Object();
  1762.  
  1763. // Extract the message id number and test against previous update
  1764. msg.id = parseInt(snap.htmlFor.split('-')[1],10);
  1765. if (msg.id <= kageTool.info.prevStorehouseId)
  1766. break;
  1767.  
  1768. msg.text = snap.innerHTML;
  1769.  
  1770. try
  1771. {
  1772.  
  1773. // Handlers here
  1774. if (msg.text.indexOf(" RP to ") >= 0)
  1775. HandlerRPAward(msg);
  1776. }
  1777. catch (err)
  1778. {
  1779. // Display error and ask the user whether they wish to continue
  1780. var text = "Error: " + err.message + "\n\noccured parsing village message:\n" + msg.text + "\n\n"
  1781. + "Press OK to skip this log entry or press CANCEL to halt script execution without save."
  1782. + "\n\n NOTE: RP for this village message must be added manually if you choose to continue.";
  1783.  
  1784. if (!confirm(text))
  1785. throw(err);
  1786. }
  1787.  
  1788. }
  1789.  
  1790. // Update the last message log id
  1791. kageTool.info.prevStorehouseId = parseInt(snapMessageList.snapshotItem(0).htmlFor.split('-')[1],10);
  1792.  
  1793. // Update the last update time
  1794. kageTool.info.prevStorehouseTime = (new Date()).getTime();
  1795.  
  1796. // Populate and show the floatingReport window
  1797. floatingReport.Draw();
  1798.  
  1799. // Save the Player data
  1800. kageTool.SavePlayerData();
  1801.  
  1802. // Save the information object
  1803. kageTool.info.SaveInfo();
  1804.  
  1805. }
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814. ////////////////////////////////////////////////////////////////////////
  1815. /////////// HOTKEY CODE /////////////
  1816. ////////////////////////////////////////////////////////////////////////
  1817.  
  1818. var keyCheckRecentEscape = false;
  1819.  
  1820. function KeyCheck(event)
  1821. {
  1822. var KeyID = event.keyCode;
  1823. if (KeyID == 27) // escape key
  1824. {
  1825. // Close both windows if not already
  1826. floatingReport.window.hide();
  1827. floatingPreferences.window.hide();
  1828. // If escape is pressed twice in succession, reset the window positions
  1829. if (keyCheckRecentEscape)
  1830. {
  1831. floatingReport.window.reset();
  1832. floatingPreferences.window.reset();
  1833. }
  1834. else
  1835. {
  1836. keyCheckRecentEscape = true;
  1837. setTimeout(function(){keyCheckRecentEscape = false;}, 1000);
  1838. }
  1839. }
  1840. }
  1841.  
  1842. document.documentElement.addEventListener("keyup", KeyCheck, true);
  1843.  
  1844.  
  1845.  
  1846. ////////////////////////////////////////////////////////////////////////
  1847. /////////// Populate Multi-RP fields ///////////////
  1848. ////////////////////////////////////////////////////////////////////////
  1849.  
  1850.  
  1851. function populateMultiRP() {
  1852. var i, inputs, name, input, rpOwed, total;
  1853.  
  1854. total = 0;
  1855. inputs = document.evaluate("//form[@name='multiresgive']//td/input", document, null, 7, null);
  1856. for (i = 0; i < inputs.snapshotLength; i++) {
  1857. input = inputs.snapshotItem(i);
  1858. name = document.evaluate(".//td/b", input.parentNode.parentNode, null, 7, null).snapshotItem(0).innerHTML;
  1859. name = /\d+ (.*)/.exec(name)[1];
  1860.  
  1861. rpOwed = kageTool.playerList[name] ? kageTool.playerList[name].rpOwed : 0;
  1862. rpOwed = 9 * Math.floor(rpOwed / 9);
  1863. if (rpOwed > 0) {
  1864. input.value = rpOwed;
  1865. total += rpOwed;
  1866. }
  1867. }
  1868.  
  1869. input = document.evaluate("//form[@name='multiresgive']", document, null, 7, null).snapshotItem(0);
  1870. input.previousElementSibling.innerHTML += ' (' + total + ' RP needed)';
  1871. }
  1872.  
  1873.  
  1874. ////////////////////////////////////////////////////////////////////////
  1875. /////////// PAGE LOAD RUNTIME ///////////////
  1876. ////////////////////////////////////////////////////////////////////////
  1877.  
  1878.  
  1879. // Create global instance of KageTool object
  1880. var kageTool = new KageTool();
  1881.  
  1882. // Create the floating window objects
  1883. var floatingReport = new FloatingReport();
  1884. var floatingPreferences = new FloatingPreferences();
  1885.  
  1886.  
  1887. // What page are we on?
  1888. if (/billy.bvs.village\./.test(location.href))
  1889. {
  1890. // Main Village Page
  1891.  
  1892. // Insert the KageTools Button
  1893. InsertKageToolsButton();
  1894. }
  1895. else if(/billy.bvs.villageresourcepoints\./.test(location.href))
  1896. {
  1897. // Resource Points Page
  1898.  
  1899. // Parse the Storehouse Logs
  1900. ParseStorehouseLogs();
  1901. SetupQuickDistribution();
  1902. populateMultiRP();
  1903. }