選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

696 行
14 KiB

  1. const events = require('../../misc/events');
  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 (!blueprint.statCount)
  438. item.stats = {};
  439. const eventMsg = {
  440. item,
  441. blueprint,
  442. result,
  443. ignore: false
  444. };
  445. events.emit('onBeforeGenerateItemStats', eventMsg);
  446. if (eventMsg.ignore)
  447. return;
  448. if (blueprint.noStats)
  449. return;
  450. //If we enchant something we don't add armor
  451. if (!blueprint.statMult)
  452. blueprint.statMult = {};
  453. for (let s in blueprint.statMult) {
  454. if (blueprint.statMult[s] > 0)
  455. this.buildStat(item, blueprint, s);
  456. }
  457. let statCount = blueprint.statCount || (item.quality + 1);
  458. if (blueprint.forceStats) {
  459. for (let i = 0; i < Math.min(statCount, blueprint.forceStats.length); i++) {
  460. let choice = blueprint.forceStats[i];
  461. this.buildStat(item, blueprint, choice, result);
  462. statCount--;
  463. }
  464. }
  465. this.buildImplicitStats(item, blueprint.implicitStat);
  466. if (blueprint.stats) {
  467. let useStats = extend([], blueprint.stats);
  468. let addStats = Math.min(statCount, blueprint.stats.length);
  469. for (let i = 0; i < addStats; i++) {
  470. let choice = useStats[~~(Math.random() * useStats.length)];
  471. useStats.spliceFirstWhere(s => s === choice);
  472. this.buildStat(item, blueprint, choice, result);
  473. statCount--;
  474. }
  475. }
  476. for (let i = 0; i < statCount; i++)
  477. this.buildStat(item, blueprint, null, result);
  478. for (let s in item.stats) {
  479. item.stats[s] = Math.ceil(item.stats[s]);
  480. if (item.stats[s] === 0)
  481. delete item.stats[s];
  482. }
  483. },
  484. buildStat: function (item, blueprint, stat, result, isImplicit) {
  485. let slotStats = this.slots[item.slot] || {};
  486. let statOptions = extend({}, this.stats, slotStats || {});
  487. for (let p in statOptions) {
  488. if ((!slotStats[p]) || (slotStats[p].ignore))
  489. continue;
  490. delete statOptions[p].ignore;
  491. }
  492. let statBlueprint = null;
  493. let value = null;
  494. if ((stat) && (stat.indexOf('|') > -1)) {
  495. let split = stat.split('|');
  496. stat = split[0];
  497. value = ~~split[1];
  498. }
  499. if (
  500. !stat ||
  501. !statOptions[stat] ||
  502. (
  503. blueprint.limitSlotStats &&
  504. statOptions[stat].ignore
  505. )
  506. ) {
  507. let options = Object.keys(statOptions).filter(function (s) {
  508. let o = statOptions[s];
  509. if (o.ignore)
  510. return false;
  511. else if ((o.level) && (o.level.min) && (item.level < o.level.min))
  512. return false;
  513. return true;
  514. });
  515. stat = options[~~(Math.random() * options.length)];
  516. statBlueprint = statOptions[stat];
  517. } else
  518. statBlueprint = statOptions[stat];
  519. if (!value) {
  520. if (statBlueprint.generator) {
  521. let level = Math.min(20, item.originalLevel || item.level);
  522. value = Math.ceil(this.generators[statBlueprint.generator](item, level, blueprint, blueprint.perfection, null, statBlueprint));
  523. } else if (!blueprint.perfection)
  524. value = Math.ceil(random.norm(statBlueprint.min, statBlueprint.max));
  525. else
  526. value = statBlueprint.min + ((statBlueprint.max - statBlueprint.min) * blueprint.perfection);
  527. }
  528. if ((result) && (result.addStatMsgs)) {
  529. result.addStatMsgs.push({
  530. stat: stat,
  531. value: value
  532. });
  533. if (!item.enchantedStats)
  534. item.enchantedStats = {};
  535. if (item.enchantedStats[stat])
  536. item.enchantedStats[stat] += value;
  537. else
  538. item.enchantedStats[stat] = value;
  539. }
  540. if (stat === 'lvlRequire') {
  541. if (!item.originalLevel)
  542. item.originalLevel = item.level;
  543. item.level -= value;
  544. if (item.level < 1)
  545. item.level = 1;
  546. }
  547. if (item.stats[stat])
  548. value += item.stats[stat];
  549. item.stats[stat] = value;
  550. },
  551. rescale: function (item, level) {
  552. let stats = item.stats;
  553. let nStats = extend({}, stats);
  554. let bpt = {
  555. statMult: {}
  556. };
  557. for (let p in stats) {
  558. let generator = this.stats[p].generator;
  559. if (!generator)
  560. continue;
  561. else if (['lvlRequire'].indexOf(p) > -1)
  562. continue;
  563. generator = this.generators[generator];
  564. let perfection = generator(item, item.originalLevel || item.level, bpt, null, stats[p]);
  565. nStats[p] = Math.ceil(generator(item, level, bpt, perfection));
  566. }
  567. return nStats;
  568. },
  569. buildImplicitStats: function (item, implicits) {
  570. if (!implicits)
  571. return;
  572. implicits = implicits.push ? implicits : [ implicits ];
  573. implicits.forEach(i => {
  574. let stat = {
  575. stat: i.stat
  576. };
  577. if (i.value) {
  578. const [min, max] = i.value;
  579. stat.value = Math.ceil(random.expNorm(min, max));
  580. } else if (i.valueMult) {
  581. let statBlueprint = this.stats[i.stat];
  582. if (statBlueprint.generator) {
  583. const generator = this.generators[statBlueprint.generator];
  584. const blueprint = {
  585. statMult: {
  586. [i.stat]: i.valueMult
  587. }
  588. };
  589. const itemLevel = Math.min(20, item.level);
  590. stat.value = Math.ceil(generator(item, itemLevel, blueprint));
  591. } else
  592. stat.value = Math.ceil(random.norm(statBlueprint.min, statBlueprint.max) * i.valueMult);
  593. }
  594. if (!item.implicitStats)
  595. item.implicitStats = [];
  596. item.implicitStats.push(stat);
  597. });
  598. }
  599. };