The West Duel Cloth Calc

Calculates the Duel skill values of your opponents.

  1. // ==UserScript==
  2. // @name The West Duel Cloth Calc
  3. // @author Mr. Perseus
  4. // @namespace tw-perseus
  5. // @description Calculates the Duel skill values of your opponents.
  6. // @include https://*.the-west.*/game.php*
  7. // @include http://*.the-west.*/game.php*
  8. // @include https://*.tw.innogames.*/game.php*
  9. // @include http://*.tw.innogames.*/game.php*
  10. // @version 1.0.1
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function (fn) {
  15. const script = document.createElement('script');
  16. script.setAttribute('type', 'application/javascript');
  17. script.textContent = `(${fn})();`;
  18. document.body.appendChild(script);
  19. document.body.removeChild(script);
  20. })(() => {
  21. $(document).ready(() => {
  22. const TWDCC = {
  23. version: '1.0.1',
  24. serverUrl: window.location.hostname.split(/[.0-9]+/)[0],
  25. };
  26.  
  27. TWDCC.Updater = {
  28. init() {
  29. setTimeout(TWDCC.Updater.load, 5000);
  30. },
  31.  
  32. load() {
  33. $.getScript(
  34. 'https://rawcdn.githack.com/mr-perseus/tw-js-library/master/script-updater.js',
  35. () => {
  36. if (scriptUpdater.TWDCC > TWDCC.version) {
  37. const updateMessage = new west.gui.Dialog(
  38. 'Update: The West Duel Cloth Calc',
  39. `<span>Update Available<br><br><b>v${scriptUpdater.TWDCC}:</b><br>${scriptUpdater.TWDCCNew}</span>`,
  40. west.gui.Dialog.SYS_WARNING,
  41. )
  42. .addButton('Update', () => {
  43. updateMessage.hide();
  44. window.location.href =
  45. 'https://gf.qytechs.cn/scripts/210874-the-west-duel-cloth-calc/code/The%20West%20Duel%20Cloth%20Calc.user.js';
  46. })
  47. .addButton('cancel')
  48. .show();
  49. }
  50. },
  51. );
  52. },
  53. };
  54.  
  55. TWDCC.DuelClothCalc = {
  56. init() {
  57. PlayerProfileMain.backup_twdcc_setWear =
  58. PlayerProfileMain.setWear;
  59. PlayerProfileMain.setWear = function () {
  60. PlayerProfileMain.backup_twdcc_setWear.apply(
  61. this,
  62. arguments,
  63. );
  64.  
  65. const playerLevel = this.resp.level;
  66.  
  67. let weaponId = 0;
  68.  
  69. const itemKeys = [];
  70.  
  71. Object.keys(this.resp.wear).forEach((key) => {
  72. if (
  73. this.resp.wear[key] &&
  74. (key === 'animal' ||
  75. key === 'yield' /* Product */ ||
  76. key === 'head' ||
  77. key === 'body' ||
  78. key === 'pants' ||
  79. key === 'foot' ||
  80. key === 'neck' ||
  81. key === 'belt' ||
  82. key === 'right_arm' ||
  83. key === 'left_arm')
  84. ) {
  85. if (key === 'right_arm') {
  86. weaponId = this.resp.wear[key];
  87. }
  88. itemKeys.push(this.resp.wear[key]);
  89. }
  90. });
  91.  
  92. const values =
  93. TWDCC.DuelClothCalc.getSkillValuesFromItemKeys(
  94. playerLevel,
  95. itemKeys,
  96. );
  97. const popupData = TWDCC.DuelClothCalc.getPopupData(values);
  98.  
  99. const duelistPopup = TWDCC.DuelClothCalc.generateNpcPopup(
  100. popupData,
  101. weaponId,
  102. this.resp,
  103. );
  104. const jqueryAvatar = this.window.find('div.profileavatar');
  105. jqueryAvatar.attr('title', duelistPopup);
  106.  
  107. const overlayClass = this.window.find('div.overlay');
  108. overlayClass.removeClass('overlay');
  109. };
  110. },
  111.  
  112. getSkillValuesFromItemKeys(playerLevel, itemKeys) {
  113. const itemObjects =
  114. TWDCC.DuelClothCalc.getItemObjects(itemKeys);
  115. const sets = TWDCC.DuelClothCalc.getSetsNumbers(itemObjects);
  116. const setObjects = TWDCC.DuelClothCalc.getSetData(sets);
  117.  
  118. return TWDCC.DuelClothCalc.calculateValues(
  119. itemObjects,
  120. playerLevel,
  121. sets,
  122. setObjects,
  123. );
  124. },
  125.  
  126. getItemObjects(itemKeys) {
  127. const itemObjects = [];
  128. itemKeys.forEach((key) =>
  129. itemObjects.push(ItemManager.get(key)),
  130. );
  131.  
  132. return itemObjects;
  133. },
  134.  
  135. calculateValues(itemObjects, playerLevel, sets, setObjects) {
  136. const values = {
  137. strength: 0,
  138. flexibility: 0,
  139. dexterity: 0,
  140. charisma: 0,
  141. /* Strength */
  142. build: 0,
  143. punch: 0,
  144. tough: 0,
  145. endurance: 0,
  146. health: 0,
  147. /* flexibility */
  148. ride: 0,
  149. reflex: 0,
  150. dodge: 0,
  151. hide: 0,
  152. swim: 0,
  153. /* Dexterity */
  154. aim: 0,
  155. shot: 0,
  156. pitfall: 0,
  157. // eslint-disable-next-line camelcase
  158. finger_dexterity: 0,
  159. repair: 0,
  160. /* charisma */
  161. leadership: 0,
  162. tactic: 0,
  163. trade: 0,
  164. animal: 0,
  165. appearance: 0,
  166. };
  167.  
  168. itemObjects.forEach((itemObject) => {
  169. const newValuesBonus =
  170. TWDCC.DuelClothCalc.getBonusObjectValues(
  171. itemObject.bonus.item,
  172. );
  173. TWDCC.DuelClothCalc.factorizeValues(
  174. newValuesBonus,
  175. playerLevel,
  176. itemObject.item_level,
  177. );
  178.  
  179. TWDCC.DuelClothCalc.addToValues(values, newValuesBonus);
  180.  
  181. const newValuesSimple =
  182. TWDCC.DuelClothCalc.getSimpleObjectValues(itemObject);
  183. TWDCC.DuelClothCalc.addToValues(values, newValuesSimple);
  184. });
  185.  
  186. TWDCC.DuelClothCalc.addSetsToValues(
  187. sets,
  188. values,
  189. playerLevel,
  190. setObjects,
  191. );
  192.  
  193. return values;
  194. },
  195.  
  196. factorizeValues(values, playerLevel, itemLevel) {
  197. const itemPercent = itemLevel ? 1 + itemLevel / 10 : 1;
  198. Object.keys(values).forEach((key) => {
  199. const ceilValue = Math.ceil(values[key] * playerLevel);
  200. values[key] = Math.round(ceilValue * itemPercent);
  201. if (values[key] === ceilValue && itemPercent !== 1) {
  202. values[key] += 1;
  203. }
  204. });
  205. },
  206.  
  207. addToValues(values, newValues) {
  208. Object.keys(newValues).forEach((key) => {
  209. values[key] = values[key]
  210. ? values[key] + newValues[key]
  211. : newValues[key];
  212. });
  213. },
  214.  
  215. getBonusObjectValues(item) {
  216. const values = {};
  217.  
  218. item.forEach((valueObj) => {
  219. if (
  220. valueObj.type === 'character' &&
  221. valueObj.key ===
  222. 'level' /* valueObj.roundingMethod === "ceil" && */ &&
  223. (valueObj.bonus.type === 'skill' ||
  224. valueObj.bonus.type === 'attribute')
  225. ) {
  226. values[valueObj.bonus.name] = valueObj.bonus.value;
  227. }
  228. });
  229.  
  230. return values;
  231. },
  232.  
  233. getSimpleSetObjectValues(setObject) {
  234. const values = {};
  235.  
  236. setObject.forEach((key) => {
  237. if (key.type === 'attribute' || key.type === 'skill') {
  238. values[key.name] = key.value;
  239. }
  240. });
  241.  
  242. return values;
  243. },
  244.  
  245. getSimpleObjectValues(itemObject) {
  246. const values = {};
  247.  
  248. Object.keys(itemObject.bonus.skills).forEach((key) => {
  249. values[key] = itemObject.bonus.skills[key];
  250. });
  251. Object.keys(itemObject.bonus.attributes).forEach((key) => {
  252. values[key] = itemObject.bonus.attributes[key];
  253. });
  254.  
  255. return values;
  256. },
  257.  
  258. addSetsToValues(sets, values, playerLevel, setObjects) {
  259. Object.keys(sets).forEach((key) => {
  260. const setData = setObjects[key];
  261. if (setData && setData.bonus[sets[key]]) {
  262. const valuesSetBonus = {};
  263. const valuesSetSimple = {};
  264.  
  265. for (let index = 2; index <= sets[key]; index += 1) {
  266. const valuesSetBonusLevel =
  267. TWDCC.DuelClothCalc.getBonusObjectValues(
  268. setData.bonus[index],
  269. );
  270. TWDCC.DuelClothCalc.addToValues(
  271. valuesSetBonus,
  272. valuesSetBonusLevel,
  273. );
  274.  
  275. const valuesSetSimpleLevel =
  276. TWDCC.DuelClothCalc.getSimpleSetObjectValues(
  277. setData.bonus[index],
  278. );
  279. TWDCC.DuelClothCalc.addToValues(
  280. valuesSetSimple,
  281. valuesSetSimpleLevel,
  282. );
  283. }
  284.  
  285. TWDCC.DuelClothCalc.factorizeValues(
  286. valuesSetBonus,
  287. playerLevel,
  288. );
  289.  
  290. TWDCC.DuelClothCalc.addToValues(values, valuesSetBonus);
  291. TWDCC.DuelClothCalc.addToValues(
  292. values,
  293. valuesSetSimple,
  294. );
  295. }
  296. });
  297. },
  298.  
  299. getPopupData(values) {
  300. return {
  301. shot: values.dexterity + values.shot,
  302. punch: values.strength + values.punch,
  303. aim: values.dexterity + values.aim,
  304. appearance: values.charisma + values.appearance,
  305. tactic: values.charisma + values.tactic,
  306. reflex: values.flexibility + values.reflex,
  307. dodge: values.flexibility + values.dodge,
  308. tough: values.strength + values.tough,
  309. health: values.strength + values.health,
  310. };
  311. },
  312.  
  313. getSetsNumbers(itemObjects) {
  314. const sets = {};
  315. itemObjects.forEach((itemObject) => {
  316. if (itemObject.set) {
  317. if (
  318. Object.prototype.hasOwnProperty.call(
  319. sets,
  320. itemObject.set,
  321. )
  322. ) {
  323. sets[itemObject.set] += 1;
  324. } else {
  325. sets[itemObject.set] = 1;
  326. }
  327. }
  328. });
  329. return sets;
  330. },
  331.  
  332. getSetData(sets) {
  333. const setObjects = [];
  334. Object.keys(sets).forEach((key) => {
  335. setObjects[key] = west.storage.ItemSetManager.get(key);
  336. });
  337. return setObjects;
  338. },
  339.  
  340. generateNpcPopup(npcData, weaponId, character) {
  341. let weapon;
  342. let damage;
  343. if (weaponId) {
  344. weapon = ItemManager.get(weaponId);
  345. damage = weapon.getDamage(character);
  346. }
  347. // noinspection HtmlRequiredAltAttribute
  348. return (
  349. `<table class="dln_npcskill_popup">${
  350. weapon
  351. ? '<tr><td colspan="5" class="text_bold">' +
  352. "The opponent's skill bonus" +
  353. '<br />&nbsp;</td></tr>'
  354. : ''
  355. }<tr><td><img src="https://west${
  356. TWDCC.serverUrl
  357. }.innogamescdn.com/images/window/duels/npcskill_shot.jpg" /></td><td><img src="https://west${
  358. TWDCC.serverUrl
  359. }.innogamescdn.com/images/window/duels/npcskill_punch.jpg" /></td>` +
  360. `<td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_aim.jpg" /></td><td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_appearance.jpg" /></td><td></td></tr>` +
  361. `<tr><td class="text_bold">${
  362. npcData.shot || 0
  363. }</td><td class="text_bold">${npcData.punch || 0}</td>` +
  364. `<td class="text_bold">${
  365. npcData.aim || 0
  366. }</td><td class="text_bold">${
  367. npcData.appearance || 0
  368. }</td><td></td></tr>` +
  369. `<tr><td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_tactic.jpg" /></td><td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_reflex.jpg" /></td>` +
  370. `<td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_dodge.jpg" /></td><td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_tough.jpg" /></td><td><img src="https://west${TWDCC.serverUrl}.innogamescdn.com/images/window/duels/npcskill_health.jpg" /></td></tr>` +
  371. `<tr><td class="text_bold">${
  372. npcData.tactic || 0
  373. }</td><td class="text_bold">${npcData.reflex || 0}</td>` +
  374. `<td class="text_bold">${
  375. npcData.dodge || 0
  376. }</td><td class="text_bold">${
  377. npcData.tough || 0
  378. }</td><td class="text_bold">${
  379. npcData.health || 0
  380. }</td></tr>${
  381. weapon
  382. ? `<tr><td colspan="2" class="text_bold"><img src="${weapon.image}" /></td><td colspan="3" class="text_bold"><br />${weapon.name}<br />(` +
  383. 'Damage' +
  384. `:&nbsp;${damage.min} - ${damage.max})</td></tr>`
  385. : ''
  386. }</table>`
  387. );
  388. },
  389. };
  390.  
  391. try {
  392. TWDCC.Updater.init();
  393. TWDCC.DuelClothCalc.init();
  394. } catch (err) {
  395. console.error('TWDCC ERROR', err);
  396. }
  397. });
  398. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址