You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

691 lines
14 KiB

  1. let statsFishingRod = require('./statsFishingRod');
  2. module.exports = {
  3. generators: {
  4. elementDmgPercent: function (item, level, blueprint, perfection, calcPerfection) {
  5. let max = (level / 6.7);
  6. if (calcPerfection)
  7. return (calcPerfection / max);
  8. else if (!perfection)
  9. return random.norm(1, max) * (blueprint.statMult.elementDmgPercent || 1);
  10. return max * perfection * (blueprint.statMult.elementDmgPercent || 1);
  11. },
  12. addCritMultiplier: function (item, level, blueprint, perfection, calcPerfection) {
  13. let div = 1 / 11;
  14. if (item.slot === 'twoHanded')
  15. div *= 2;
  16. let max = (level * 15) * div;
  17. if (calcPerfection)
  18. return (calcPerfection / max);
  19. else if (!perfection)
  20. return random.norm(1, max) * (blueprint.statMult.addCritMultiplier || 1);
  21. return max * perfection * (blueprint.statMult.addCritMultiplier || 1);
  22. },
  23. addCritChance: function (item, level, blueprint, perfection, calcPerfection) {
  24. let div = 1 / 11;
  25. if (item.slot === 'twoHanded')
  26. div *= 2;
  27. let max = (level - 3) * 50 * div;
  28. if (calcPerfection)
  29. return (calcPerfection / max);
  30. else if (!perfection)
  31. return random.norm(1, max) * (blueprint.statMult.addCritChance || 1);
  32. return max * perfection * (blueprint.statMult.addCritChance || 1);
  33. },
  34. vit: function (item, level, blueprint, perfection, calcPerfection) {
  35. let div = 1 / 11;
  36. if (item.slot === 'twoHanded')
  37. div *= 2;
  38. let max = ((-0.6340155 + (13.68923 * level) - (0.34383 * Math.pow(level, 2)) + (0.06754871 * Math.pow(level, 3)) + (0.000174046 * Math.pow(level, 4)) + (0.000007675887 * Math.pow(level, 5))) / 10) * div;
  39. if (calcPerfection)
  40. return (calcPerfection / max);
  41. else if (!perfection)
  42. return random.norm(1, max) * (blueprint.statMult.vit || 1);
  43. return max * perfection * (blueprint.statMult.vit || 1);
  44. },
  45. mainStat: function (item, level, blueprint, perfection, calcPerfection) {
  46. let div = 1 / 11;
  47. if (item.slot === 'twoHanded')
  48. div *= 2;
  49. let min = (level / 15) * div;
  50. let max = (level * 5) * div;
  51. if (calcPerfection)
  52. return ((calcPerfection - min) / (max - min));
  53. else if (!perfection)
  54. return random.norm(min, max) * (blueprint.statMult.mainStat || 1);
  55. return (min + ((max - min) * perfection)) * (blueprint.statMult.mainStat || 1);
  56. },
  57. armor: function (item, level, blueprint, perfection, calcPerfection) {
  58. let min = (level * 20);
  59. let max = (level * 50);
  60. if (calcPerfection)
  61. return ((calcPerfection - min) / (max - min));
  62. else if (!perfection)
  63. return random.norm(min, max) * blueprint.statMult.armor;
  64. return (min + ((max - min) * perfection)) * (blueprint.statMult.armor || 1);
  65. },
  66. elementResist: function (item, level, blueprint, perfection, calcPerfection) {
  67. let div = 1 / 11;
  68. if (item.slot === 'twoHanded')
  69. div *= 2;
  70. if (calcPerfection)
  71. return (calcPerfection / (100 * div));
  72. else if (!perfection)
  73. return random.norm(1, 100) * (blueprint.statMult.elementResist || 1) * div;
  74. return ~~((1 + (99 * perfection)) * (blueprint.statMult.elementResist || 1) * div);
  75. },
  76. regenHp: function (item, level, blueprint, perfection, calcPerfection) {
  77. let div = 1 / 11;
  78. if (item.slot === 'twoHanded')
  79. div *= 2;
  80. let max = (-0.05426729 + (3.477385 * level) - (0.03890282 * Math.pow(level, 2)) + (0.009244822 * Math.pow(level, 3)) + (0.0001700915 * Math.pow(level, 4)) - (0.00000138085 * Math.pow(level, 5))) * div;
  81. if (calcPerfection)
  82. return (calcPerfection / max);
  83. else if (!perfection)
  84. return random.norm(1, max) * (blueprint.statMult.regenHp || 1);
  85. return max * perfection * (blueprint.statMult.regenHp || 1);
  86. },
  87. lvlRequire: function (item, level, blueprint, perfection, calcPerfection) {
  88. let max = ~~(level / 2);
  89. if (calcPerfection)
  90. return (calcPerfection / max);
  91. else if (!perfection)
  92. return random.norm(1, max) * (blueprint.statMult.lvlRequire || 1);
  93. return max * perfection * (blueprint.statMult.lvlRequire || 1);
  94. },
  95. lifeOnHit: function (item, level, blueprint, perfection, calcPerfection, statBlueprint) {
  96. const { min, max } = statBlueprint;
  97. const scale = level / consts.maxLevel;
  98. const maxRoll = scale * (max - min);
  99. if (calcPerfection)
  100. return ((calcPerfection - min) / maxRoll);
  101. else if (!perfection)
  102. return (min + random.norm(1, maxRoll)) * (blueprint.statMult.lifeOnHit || 1);
  103. return (min + (maxRoll * perfection)) * (blueprint.statMult.lifeOnHit || 1);
  104. }
  105. },
  106. stats: {
  107. vit: {
  108. generator: 'vit'
  109. },
  110. regenHp: {
  111. generator: 'regenHp'
  112. },
  113. manaMax: {
  114. min: 1,
  115. max: 8
  116. },
  117. regenMana: {
  118. min: 1,
  119. max: 5
  120. },
  121. lvlRequire: {
  122. level: {
  123. min: 5
  124. },
  125. generator: 'lvlRequire'
  126. },
  127. str: {
  128. generator: 'mainStat'
  129. },
  130. int: {
  131. generator: 'mainStat'
  132. },
  133. dex: {
  134. generator: 'mainStat'
  135. },
  136. elementArcaneResist: {
  137. level: {
  138. min: 15
  139. },
  140. generator: 'elementResist'
  141. },
  142. elementFrostResist: {
  143. level: {
  144. min: 15
  145. },
  146. generator: 'elementResist'
  147. },
  148. elementFireResist: {
  149. level: {
  150. min: 15
  151. },
  152. generator: 'elementResist'
  153. },
  154. elementHolyResist: {
  155. level: {
  156. min: 15
  157. },
  158. generator: 'elementResist'
  159. },
  160. elementPoisonResist: {
  161. level: {
  162. min: 15
  163. },
  164. generator: 'elementResist'
  165. },
  166. elementAllResist: {
  167. level: {
  168. min: 15
  169. },
  170. generator: 'elementResist'
  171. },
  172. elementArcanePercent: {
  173. level: {
  174. min: 10
  175. },
  176. ignore: true,
  177. generator: 'elementDmgPercent'
  178. },
  179. elementFrostPercent: {
  180. level: {
  181. min: 10
  182. },
  183. ignore: true,
  184. generator: 'elementDmgPercent'
  185. },
  186. elementFirePercent: {
  187. level: {
  188. min: 10
  189. },
  190. ignore: true,
  191. generator: 'elementDmgPercent'
  192. },
  193. elementHolyPercent: {
  194. level: {
  195. min: 10
  196. },
  197. ignore: true,
  198. generator: 'elementDmgPercent'
  199. },
  200. elementPoisonPercent: {
  201. level: {
  202. min: 10
  203. },
  204. ignore: true,
  205. generator: 'elementDmgPercent'
  206. },
  207. physicalPercent: {
  208. level: {
  209. min: 10
  210. },
  211. ignore: true,
  212. generator: 'elementDmgPercent'
  213. },
  214. elementPercent: {
  215. level: {
  216. min: 10
  217. },
  218. ignore: true,
  219. generator: 'elementDmgPercent'
  220. },
  221. spellPercent: {
  222. level: {
  223. min: 10
  224. },
  225. ignore: true,
  226. generator: 'elementDmgPercent'
  227. },
  228. allAttributes: {
  229. generator: 'mainStat',
  230. ignore: true
  231. },
  232. attackSpeed: {
  233. min: 1,
  234. max: 8.75,
  235. ignore: true
  236. },
  237. castSpeed: {
  238. min: 1,
  239. max: 8.75,
  240. ignore: true
  241. },
  242. lifeOnHit: {
  243. min: 1,
  244. max: 10,
  245. ignore: true,
  246. generator: 'lifeOnHit'
  247. },
  248. armor: {
  249. generator: 'armor',
  250. ignore: true
  251. },
  252. blockAttackChance: {
  253. min: 1,
  254. max: 10,
  255. ignore: true
  256. },
  257. blockSpellChance: {
  258. min: 1,
  259. max: 10,
  260. ignore: true
  261. },
  262. dodgeAttackChance: {
  263. min: 1,
  264. max: 10,
  265. ignore: true
  266. },
  267. dodgeSpellChance: {
  268. min: 1,
  269. max: 10,
  270. ignore: true
  271. },
  272. addCritChance: {
  273. generator: 'addCritChance',
  274. level: {
  275. min: 7
  276. }
  277. },
  278. addCritMultiplier: {
  279. generator: 'addCritMultiplier',
  280. level: {
  281. min: 12
  282. }
  283. },
  284. addAttackCritChance: {
  285. generator: 'addCritChance',
  286. level: {
  287. min: 7
  288. }
  289. },
  290. addAttackCritMultiplier: {
  291. generator: 'addCritMultiplier',
  292. level: {
  293. min: 12
  294. }
  295. },
  296. addSpellCritChance: {
  297. generator: 'addCritChance',
  298. level: {
  299. min: 7
  300. }
  301. },
  302. addSpellCritMultiplier: {
  303. generator: 'addCritMultiplier',
  304. level: {
  305. min: 12
  306. }
  307. },
  308. magicFind: {
  309. min: 1,
  310. max: 15
  311. },
  312. itemQuantity: {
  313. min: 2,
  314. max: 27
  315. },
  316. xpIncrease: {
  317. min: 1,
  318. max: 6
  319. },
  320. sprintChance: {
  321. min: 1,
  322. max: 20,
  323. ignore: true
  324. }
  325. },
  326. slots: {
  327. feet: {
  328. sprintChance: {
  329. min: 1,
  330. max: 20
  331. },
  332. dodgeAttackChance: {
  333. min: 1,
  334. max: 10
  335. },
  336. dodgeSpellChance: {
  337. min: 1,
  338. max: 10
  339. }
  340. },
  341. offHand: {
  342. lifeOnHit: {
  343. min: 1,
  344. max: 10
  345. }
  346. },
  347. trinket: {
  348. attackSpeed: {
  349. min: 1,
  350. max: 8.75
  351. },
  352. castSpeed: {
  353. min: 1,
  354. max: 8.75
  355. },
  356. lifeOnHit: {
  357. min: 1,
  358. max: 10
  359. }
  360. },
  361. finger: {
  362. elementArcanePercent: {
  363. generator: 'elementDmgPercent'
  364. },
  365. elementFrostPercent: {
  366. generator: 'elementDmgPercent'
  367. },
  368. elementFirePercent: {
  369. generator: 'elementDmgPercent'
  370. },
  371. elementHolyPercent: {
  372. generator: 'elementDmgPercent'
  373. },
  374. elementPoisonPercent: {
  375. generator: 'elementDmgPercent'
  376. },
  377. elementPercent: {
  378. generator: 'elementDmgPercent'
  379. },
  380. physicalPercent: {
  381. generator: 'elementDmgPercent'
  382. },
  383. spellPercent: {
  384. generator: 'elementDmgPercent'
  385. },
  386. allAttributes: {
  387. generator: 'mainStat'
  388. },
  389. attackSpeed: {
  390. min: 1,
  391. max: 8.75
  392. },
  393. castSpeed: {
  394. min: 1,
  395. max: 8.75
  396. }
  397. },
  398. neck: {
  399. elementArcanePercent: {
  400. generator: 'elementDmgPercent'
  401. },
  402. elementFrostPercent: {
  403. generator: 'elementDmgPercent'
  404. },
  405. elementFirePercent: {
  406. generator: 'elementDmgPercent'
  407. },
  408. elementHolyPercent: {
  409. generator: 'elementDmgPercent'
  410. },
  411. elementPoisonPercent: {
  412. generator: 'elementDmgPercent'
  413. },
  414. physicalPercent: {
  415. generator: 'elementDmgPercent'
  416. },
  417. elementPercent: {
  418. generator: 'elementDmgPercent'
  419. },
  420. spellPercent: {
  421. generator: 'elementDmgPercent'
  422. },
  423. allAttributes: {
  424. generator: 'mainStat'
  425. },
  426. attackSpeed: {
  427. min: 1,
  428. max: 8.75
  429. },
  430. castSpeed: {
  431. min: 1,
  432. max: 8.75
  433. }
  434. }
  435. },
  436. generate: function (item, blueprint, result) {
  437. if (item.slot === 'tool') {
  438. statsFishingRod.generate(item, blueprint, result);
  439. return;
  440. }
  441. if (!blueprint.statCount || !item.stats)
  442. item.stats = {};
  443. if (blueprint.noStats)
  444. return;
  445. //If we enchant something we don't add armor
  446. if (!blueprint.statMult)
  447. blueprint.statMult = {};
  448. for (let s in blueprint.statMult) {
  449. if (blueprint.statMult[s] > 0)
  450. this.buildStat(item, blueprint, s);
  451. }
  452. let statCount = blueprint.statCount || (item.quality + 1);
  453. if (blueprint.forceStats) {
  454. for (let i = 0; i < Math.min(statCount, blueprint.forceStats.length); i++) {
  455. let choice = blueprint.forceStats[i];
  456. this.buildStat(item, blueprint, choice, result);
  457. statCount--;
  458. }
  459. }
  460. this.buildImplicitStats(item, blueprint.implicitStat);
  461. if (blueprint.stats) {
  462. let useStats = extend([], blueprint.stats);
  463. let addStats = Math.min(statCount, blueprint.stats.length);
  464. for (let i = 0; i < addStats; i++) {
  465. let choice = useStats[~~(Math.random() * useStats.length)];
  466. useStats.spliceFirstWhere(s => s === choice);
  467. this.buildStat(item, blueprint, choice, result);
  468. statCount--;
  469. }
  470. }
  471. for (let i = 0; i < statCount; i++)
  472. this.buildStat(item, blueprint, null, result);
  473. for (let s in item.stats) {
  474. item.stats[s] = Math.ceil(item.stats[s]);
  475. if (item.stats[s] === 0)
  476. delete item.stats[s];
  477. }
  478. },
  479. buildStat: function (item, blueprint, stat, result, isImplicit) {
  480. let slotStats = this.slots[item.slot] || {};
  481. let statOptions = extend({}, this.stats, slotStats || {});
  482. for (let p in statOptions) {
  483. if ((!slotStats[p]) || (slotStats[p].ignore))
  484. continue;
  485. delete statOptions[p].ignore;
  486. }
  487. let statBlueprint = null;
  488. let value = null;
  489. if ((stat) && (stat.indexOf('|') > -1)) {
  490. let split = stat.split('|');
  491. stat = split[0];
  492. value = ~~split[1];
  493. }
  494. if (
  495. !stat ||
  496. !statOptions[stat] ||
  497. (
  498. blueprint.limitSlotStats &&
  499. statOptions[stat].ignore
  500. )
  501. ) {
  502. let options = Object.keys(statOptions).filter(function (s) {
  503. let o = statOptions[s];
  504. if (o.ignore)
  505. return false;
  506. else if ((o.level) && (o.level.min) && (item.level < o.level.min))
  507. return false;
  508. return true;
  509. });
  510. stat = options[~~(Math.random() * options.length)];
  511. statBlueprint = statOptions[stat];
  512. } else
  513. statBlueprint = statOptions[stat];
  514. if (!value) {
  515. if (statBlueprint.generator) {
  516. let level = Math.min(consts.maxLevel, item.originalLevel || item.level);
  517. value = Math.ceil(this.generators[statBlueprint.generator](item, level, blueprint, blueprint.perfection, null, statBlueprint));
  518. } else if (!blueprint.perfection)
  519. value = Math.ceil(random.norm(statBlueprint.min, statBlueprint.max));
  520. else
  521. value = statBlueprint.min + ((statBlueprint.max - statBlueprint.min) * blueprint.perfection);
  522. }
  523. if ((result) && (result.addStatMsgs)) {
  524. result.addStatMsgs.push({
  525. stat: stat,
  526. value: value
  527. });
  528. if (!item.enchantedStats)
  529. item.enchantedStats = {};
  530. if (item.enchantedStats[stat])
  531. item.enchantedStats[stat] += value;
  532. else
  533. item.enchantedStats[stat] = value;
  534. }
  535. if (stat === 'lvlRequire') {
  536. if (!item.originalLevel)
  537. item.originalLevel = item.level;
  538. item.level -= value;
  539. if (item.level < 1)
  540. item.level = 1;
  541. }
  542. if (item.stats[stat])
  543. value += item.stats[stat];
  544. item.stats[stat] = value;
  545. },
  546. rescale: function (item, level) {
  547. let stats = item.stats;
  548. let nStats = extend({}, stats);
  549. let bpt = {
  550. statMult: {}
  551. };
  552. for (let p in stats) {
  553. let generator = this.stats[p].generator;
  554. if (!generator)
  555. continue;
  556. else if (['lvlRequire'].indexOf(p) > -1)
  557. continue;
  558. generator = this.generators[generator];
  559. let perfection = generator(item, item.originalLevel || item.level, bpt, null, stats[p]);
  560. nStats[p] = Math.ceil(generator(item, level, bpt, perfection));
  561. }
  562. return nStats;
  563. },
  564. buildImplicitStats: function (item, implicits) {
  565. if (!implicits)
  566. return;
  567. implicits = implicits.push ? implicits : [ implicits ];
  568. implicits.forEach(i => {
  569. let stat = {
  570. stat: i.stat
  571. };
  572. if (i.value) {
  573. const [min, max] = i.value;
  574. stat.value = Math.ceil(random.expNorm(min, max));
  575. } else if (i.valueMult) {
  576. let statBlueprint = this.stats[i.stat];
  577. if (statBlueprint.generator) {
  578. const generator = this.generators[statBlueprint.generator];
  579. const blueprint = {
  580. statMult: {
  581. [i.stat]: i.valueMult
  582. }
  583. };
  584. const itemLevel = Math.min(consts.maxLevel, item.level);
  585. stat.value = Math.ceil(generator(item, itemLevel, blueprint));
  586. } else
  587. stat.value = Math.ceil(random.norm(statBlueprint.min, statBlueprint.max) * i.valueMult);
  588. }
  589. if (!item.implicitStats)
  590. item.implicitStats = [];
  591. item.implicitStats.push(stat);
  592. });
  593. }
  594. };